From 5eaeb13087e60a7834d3e2522bda2aa3c32c79b1 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Thu, 11 Sep 2025 14:54:31 +0330 Subject: [PATCH] add Guard Event and Attached it to all Realted Classes till Final Handler in eaTradeManager ... --- Classes/x-saherelm.x-guard.class.mq5 | 129 ++++- Classes/x-saherelm.x-trade-manager.class.mq5 | 531 ++++++++++--------- Experts/x-saherelm.xom1.ea.mq5 | 19 +- XOM1EA/Classes/xom1ea.expert.class.mq5 | 19 + 4 files changed, 452 insertions(+), 246 deletions(-) diff --git a/Classes/x-saherelm.x-guard.class.mq5 b/Classes/x-saherelm.x-guard.class.mq5 index 91ef6b57..fb330229 100644 --- a/Classes/x-saherelm.x-guard.class.mq5 +++ b/Classes/x-saherelm.x-guard.class.mq5 @@ -160,6 +160,12 @@ struct XGuard } }; +// +// an Event Type for Notify Guard Triggered ... +typedef void (*TOnGuarded)( + ENUM_X_GUARD_ACTIONS guard, + XPosition &positions[]); + // // Extensions ... @@ -226,6 +232,7 @@ class XCGuard : public XCBase // Props ... double minVolumeFactorForHedge; // Minimum Volume Factor for Hedge Profit Calculation ... double minProfitPerVolumeFactorForHedge; // Minimum Required Profit per Volume Factor for Hedg ... + TOnGuarded onGuardEventListener; // On Guard Event Listener ... // // Constructor(s) ... @@ -1005,6 +1012,9 @@ class XCGuard : public XCBase ); if (has) { + // + HandleNotifyPositionGuard(guard.action, position); + // string message = "Guard Closed " + @@ -1070,6 +1080,9 @@ class XCGuard : public XCBase ); if (has) { + // + HandleNotifyPositionsGuard(guard.action, positions); + // string message = "Guard Closed " + @@ -1135,6 +1148,9 @@ class XCGuard : public XCBase ); if (has) { + // + HandleNotifyPositionsGuard(guard.action, positions); + // string message = "Guard Closed " + @@ -1200,6 +1216,9 @@ class XCGuard : public XCBase ); if (has) { + // + HandleNotifyPositionsGuard(guard.action, positions); + // string message = "Guard Closed " + @@ -1265,6 +1284,9 @@ class XCGuard : public XCBase ); if (has) { + // + HandleNotifyPositionsGuard(guard.action, positions); + // string message = "Guard Closed " + @@ -1330,6 +1352,9 @@ class XCGuard : public XCBase ); if (has) { + // + HandleNotifyPositionsGuard(guard.action, positions); + // string message = "Guard Closed " + @@ -1395,6 +1420,9 @@ class XCGuard : public XCBase ); if (has) { + // + HandleNotifyPositionsGuard(guard.action, positions); + // string message = "Guard Closed " + @@ -1426,7 +1454,50 @@ class XCGuard : public XCBase } // - // Do What we want ... + // Retrieve Positions ... + XPosition positions[]; + int count = GetShortPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close Shorts ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + HandleNotifyPositionsGuard(guard.action, positions); + + // + string message = + "Guard Closed " + + ToXString(count) + + " Long Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); } // @@ -1477,6 +1548,9 @@ class XCGuard : public XCBase ); if (has) { + // + HandleNotifyPositionsGuard(guard.action, positions); + // string message = "Guard Closed " + @@ -1542,6 +1616,10 @@ class XCGuard : public XCBase ); if (has) { + // + HandleNotifyPositionsGuard(guard.action, positions); + + // // string message = "Guard Closed " + @@ -1633,6 +1711,9 @@ class XCGuard : public XCBase ); if (has) { + // + HandleNotifyPositionGuard(guard.action, position); + // string message = "Guard Closed Partially " + @@ -1736,6 +1817,9 @@ class XCGuard : public XCBase ); if (has) { + // + HandleNotifyPositionGuard(guard.action, position); + // double before = NormalizePrice(position.sl, position.symbol); double after = NormalizePrice(guard.sl, position.symbol); @@ -1841,6 +1925,9 @@ class XCGuard : public XCBase ); if (has) { + // + HandleNotifyPositionGuard(guard.action, position); + // double before = NormalizePrice(position.tp, position.symbol); double after = NormalizePrice(guard.tp, position.symbol); @@ -1981,6 +2068,9 @@ class XCGuard : public XCBase has = IsValidSize(closedCount); if (has) { + // + HandleNotifyPositionsGuard(guard.action, positions); + // string message = "Guard Hedge " + @@ -2007,6 +2097,43 @@ class XCGuard : public XCBase XCTrade *trader; XCAlert *alert; + // + void HandleNotifyPositionGuard( + ENUM_X_GUARD_ACTIONS action, + XPosition &position // + ) + { + // + if (!IsSpecifiedValid(action) || !position.IsValid() || onGuardEventListener == NULL) + { + return; + } + + // + XPosition positions[]; + AddRef( + position, + positions // + ); + HandleNotifyPositionsGuard(action, positions); + } + + // + void HandleNotifyPositionsGuard( + ENUM_X_GUARD_ACTIONS action, + XPosition &positions[] // + ) + { + // + if (!IsSpecifiedValid(action) || !HasChild(positions) || onGuardEventListener == NULL) + { + return; + } + + // + onGuardEventListener(action, positions); + } + // }; diff --git a/Classes/x-saherelm.x-trade-manager.class.mq5 b/Classes/x-saherelm.x-trade-manager.class.mq5 index d5282b4a..9d017814 100644 --- a/Classes/x-saherelm.x-trade-manager.class.mq5 +++ b/Classes/x-saherelm.x-trade-manager.class.mq5 @@ -510,6 +510,16 @@ class XCTradeManager : public XCBase return; } + // + XGuard guards[]; + int guardsCount = CheckForGuard(guards); + bool hasGuard = IsValidSize(guardsCount); + if (hasGuard) + { + // + guard.DoGuards(guards); + } + // double swapSum = 0; double profitSum = 0; @@ -1022,39 +1032,6 @@ class XCTradeManager : public XCBase return result; } - /** - * Handle All Exists Symbol Configurations Restrictions ... - */ - void HandleRestrictions() - { - // - // Count Symbol Configurations ... - int count = ArraySize(symbolTradeConfigs); - bool has = IsValidSize(count); - if (!has) - { - return; - } - - // - // Handle Restrictions ... - datetime cTime = TimeCurrent(); - bool isNewDay = timeTracker.IsNewDay(); - for (int i = 0; i < count; i++) - { - // - // Reset Force Close At Time ... - if (isNewDay) - { - symbolTradeConfigs[i].isForceCloseAtTime = false; - } - - // - // Handle Restrictions ... - symbolTradeConfigs[i].HandleRestrictions(cTime); - } - } - /** * Handle Signal Recieved ... * @@ -1440,220 +1417,16 @@ class XCTradeManager : public XCBase } /** - * Handle Force Close Trades ... + * Handle Guard Events ... + * + * @param action: ENUM_X_GUARD_ACTIONS + * @param positions: XPosition[] */ - bool HandleForceCloseTrades( + void HandleGuardEvent( + ENUM_X_GUARD_ACTIONS action, XPosition &positions[] // ) { - // - bool result = false; - - // - result = HasChild(positions); - if (!result) - { - return result; - } - - // - string prefix = "Protector: "; - string comment = "Force Close ..."; - - // - int count = ArraySize(positions); - for (int i = 0; i < count; i++) - { - HandleForceClose(positions[i]); - } - - // - result = IsValidSize(count); - if (result) - { - // - string message = prefix + "Force Close (" + ToXString(count) + ") Trades at Specified Time ..."; - HandleReportProtector(message); - } - - // - return result; - } - - // - // TODO: Complete this ... - void HandleGuard() - { - } - - /** - * Apply Signal Volume ... - * - * @param signal: XSignal - */ - void HandleSignalVolume(XSignal &signal) - { - // - // Validate ... - if (!signal.IsValid()) - { - return; - } - - // - // Handle Volume Management ... - double iVolume = volume.CalculateVolume(signal); - bool has = iVolume > X_MIN_VOLUME && - iVolume != signal.volume; - if (has) - { - signal.volume = iVolume; - } - } - - /** - * Find Executed Trade by Providing Position Ticket ... - * - * @param index: int reference, holding founded item index ... - * @param ticket: ulong, Specified Position Ticket ... - * - * @return ( bool ) - */ - bool HasTrade( - int &index, - ulong ticket // - ) - { - // - bool result = false; - - // - index = -1; - - // - result = - ticket > 0 && - HasChild(trades); - if (!result) - { - return result; - } - - // - int count = ArraySize(trades); - for (int i = 0; i < count; i++) - { - // - XTradeInfo iTrade = trades[i]; - - // - result = - iTrade.HasSignal() && - iTrade.IsExecuted() && - iTrade.positionID == ticket; - if (result) - { - // - index = i; - - // - iTrade.Clean(); - break; - } - - // - iTrade.Clean(); - } - - // - result = IsValidIndex(index); - - // - return result; - } - - /** - * Find Trade Item By Signal ... - * - * @param index: int reference, holding founded item index ... - * - * @return ( bool ) - */ - bool HasTrade( - int &index, - XSignal &signal // - ) - { - // - bool result = false; - - // - index = -1; - - // - result = - signal.IsValid() && - HasChild(trades); - if (!result) - { - return result; - } - - // - int count = ArraySize(trades); - for (int i = 0; i < count; i++) - { - // - XTradeInfo iTrade = trades[i]; - - // - result = - iTrade.HasSignal() && - iTrade.signal.IsSameAs(signal); - if (result) - { - // - index = i; - - // - iTrade.Clean(); - break; - } - - // - iTrade.Clean(); - } - - // - result = IsValidIndex(index); - - // - return result; - } - - /** - * Remove a Trade From List ... - * - * @param index: int ... - */ - void RemoveTrade(int index) - { - // - bool has = - HasChild(trades) && - IsValidIndex(index) && - index < ArraySize(trades); - if (!has) - { - return; - } - - // - ArrayRemove( - trades, - index, - 1 // - ); } // @@ -1787,6 +1560,133 @@ class XCTradeManager : public XCBase alert.SendAlert(message); } + /** + * Handle All Exists Symbol Configurations Restrictions ... + */ + void HandleRestrictions() + { + // + // Count Symbol Configurations ... + int count = ArraySize(symbolTradeConfigs); + bool has = IsValidSize(count); + if (!has) + { + return; + } + + // + // Handle Restrictions ... + datetime cTime = TimeCurrent(); + bool isNewDay = timeTracker.IsNewDay(); + for (int i = 0; i < count; i++) + { + // + // Reset Force Close At Time ... + if (isNewDay) + { + symbolTradeConfigs[i].isForceCloseAtTime = false; + } + + // + // Handle Restrictions ... + symbolTradeConfigs[i].HandleRestrictions(cTime); + } + } + + /** + * Apply Signal Volume ... + * + * @param signal: XSignal + */ + void HandleSignalVolume(XSignal &signal) + { + // + // Validate ... + if (!signal.IsValid()) + { + return; + } + + // + // Handle Volume Management ... + double iVolume = volume.CalculateVolume(signal); + bool has = iVolume > X_MIN_VOLUME && + iVolume != signal.volume; + if (has) + { + signal.volume = iVolume; + } + + // + // Here we Can Implement Custom Signalling Volume Management + // based on Different Symbol Configurations ... + } + + /** + * Handle Force Close Trades ... + */ + bool HandleForceCloseTrades( + XPosition &positions[] // + ) + { + // + bool result = false; + + // + result = HasChild(positions); + if (!result) + { + return result; + } + + // + string prefix = "Protector: "; + string comment = "Force Close ..."; + + // + int count = ArraySize(positions); + for (int i = 0; i < count; i++) + { + HandleForceClose(positions[i]); + } + + // + result = IsValidSize(count); + if (result) + { + // + string message = prefix + "Force Close (" + ToXString(count) + ") Trades at Specified Time ..."; + HandleReportProtector(message); + } + + // + return result; + } + + /** + * Check For Guards ... + * + * @param dest: XGuard[] + */ + int CheckForGuard(XGuard &dest[]) + { + // + int result = 0; + + // + // Cleanup Dest ... + SpecifiedClean(dest); + + // + // Check For Guards ... + + // + result = ArraySize(dest); + + // + return result; + } + // // Save Trades ... bool SaveTrade( @@ -1995,6 +1895,151 @@ class XCTradeManager : public XCBase XTradeInfo trades[]; XSymbolTradeConfig symbolTradeConfigs[]; + /** + * Find Executed Trade by Providing Position Ticket ... + * + * @param index: int reference, holding founded item index ... + * @param ticket: ulong, Specified Position Ticket ... + * + * @return ( bool ) + */ + bool HasTrade( + int &index, + ulong ticket // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = + ticket > 0 && + HasChild(trades); + if (!result) + { + return result; + } + + // + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + XTradeInfo iTrade = trades[i]; + + // + result = + iTrade.HasSignal() && + iTrade.IsExecuted() && + iTrade.positionID == ticket; + if (result) + { + // + index = i; + + // + iTrade.Clean(); + break; + } + + // + iTrade.Clean(); + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Find Trade Item By Signal ... + * + * @param index: int reference, holding founded item index ... + * + * @return ( bool ) + */ + bool HasTrade( + int &index, + XSignal &signal // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = + signal.IsValid() && + HasChild(trades); + if (!result) + { + return result; + } + + // + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + XTradeInfo iTrade = trades[i]; + + // + result = + iTrade.HasSignal() && + iTrade.signal.IsSameAs(signal); + if (result) + { + // + index = i; + + // + iTrade.Clean(); + break; + } + + // + iTrade.Clean(); + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Remove a Trade From List ... + * + * @param index: int ... + */ + void RemoveTrade(int index) + { + // + bool has = + HasChild(trades) && + IsValidIndex(index) && + index < ArraySize(trades); + if (!has) + { + return; + } + + // + ArrayRemove( + trades, + index, + 1 // + ); + } + // void AddOrUpdateSymbolConfiguration(XSymbolTradeConfig &config) { diff --git a/Experts/x-saherelm.xom1.ea.mq5 b/Experts/x-saherelm.xom1.ea.mq5 index c2967a56..56342b6e 100644 --- a/Experts/x-saherelm.xom1.ea.mq5 +++ b/Experts/x-saherelm.xom1.ea.mq5 @@ -207,6 +207,7 @@ int OnInit() // // Attach Event Handlers ... eaExpert.AddOnSignalEventHandler(OnSignalTriggered); + eaExpert.onGuardedEventHandler = OnGuardedTriggered; eaExpert.AddOnDealsChangedEventHandler(OnDealsChanged); eaExpert.AddOnStopLossEventHandler(OnStopLossTriggered); eaExpert.AddOnOrdersChangedEventHandler(OnOrdersChanged); @@ -296,11 +297,11 @@ void OnChartEvent( /** * Handle CanAnalyse Event Triggered ... - * + * * @param symbol: Symbol ... * @param period: Period ... * @param time: Analysing Time ... - * + * * @return ( bool ) */ bool CanAnalyseEventTriggered( @@ -316,6 +317,20 @@ bool CanAnalyseEventTriggered( ); } +/** + * Handle Guard Events ... + * + * @param action: ENUM_X_GUARD_ACTIONS + * @param positions: XPosition[] + */ +void OnGuardedTriggered( + ENUM_X_GUARD_ACTIONS action, + XPosition &positions[] // +) +{ + eaExpert.OnGuardedTriggered(action, positions); +} + /** * Trigger OnSignal Event ... * diff --git a/XOM1EA/Classes/xom1ea.expert.class.mq5 b/XOM1EA/Classes/xom1ea.expert.class.mq5 index 5f0f1452..58bd5286 100644 --- a/XOM1EA/Classes/xom1ea.expert.class.mq5 +++ b/XOM1EA/Classes/xom1ea.expert.class.mq5 @@ -114,6 +114,7 @@ class XCXOM1EAExpert : public XCBase // Tools / Actions / Handlers ... // + TOnGuarded onGuardedEventHandler; TCanAnalyse canAnalyseEventHandler; // @@ -502,6 +503,10 @@ class XCXOM1EAExpert : public XCBase eaTrade // ); + // + // Attach Event Handler ... + eaGuard.onGuardEventListener = onGuardedEventHandler; + // // Initialize Trae Manager ... eaTradeManager = new XCTradeManager( @@ -737,6 +742,20 @@ class XCXOM1EAExpert : public XCBase eaTradeManager.HandleSignal(signal); } + /** + * Handle Guard Events ... + * + * @param action: ENUM_X_GUARD_ACTIONS + * @param positions: XPosition[] + */ + void OnGuardedTriggered( + ENUM_X_GUARD_ACTIONS action, + XPosition &positions[] // + ) + { + eaTradeManager.HandleGuardEvent(action, positions); + } + // // Check Can Analyse ... bool HandleCanAnalyseEventTriggered(