From bc73aebe664b07491b3dadd2f7db7969dbc013d4 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Mon, 20 Oct 2025 23:03:21 +0330 Subject: [PATCH] last works ... --- Classes/x-saherelm.x-account.class.mq5 | 10 ++ Classes/x-saherelm.x-signaller.class.mq5 | 161 ++++++++++++++++++ Experts/x-saherelm.xfima.backtester.ea.mq5 | 54 ++++++ Libraries/x-saherelm.x-trade.lib.mq5 | 4 +- .../x-saherelm.xfima.signaller.class.mq5 | 76 +++++++-- 5 files changed, 290 insertions(+), 15 deletions(-) diff --git a/Classes/x-saherelm.x-account.class.mq5 b/Classes/x-saherelm.x-account.class.mq5 index c451091d..3e63cfbc 100644 --- a/Classes/x-saherelm.x-account.class.mq5 +++ b/Classes/x-saherelm.x-account.class.mq5 @@ -374,6 +374,16 @@ class XCAccount : public XCBase return result; } + /** + * Retrieve Specified Message for Report Balance ... + * + * @return ( string ) + */ + string GetBalanceReportMessage() + { + return "Balance: " + ToXString(GetBalance()) + " " + GetCurrency(); + } + // // END Provided Functions ... // diff --git a/Classes/x-saherelm.x-signaller.class.mq5 b/Classes/x-saherelm.x-signaller.class.mq5 index 2dae49e0..d9862f62 100644 --- a/Classes/x-saherelm.x-signaller.class.mq5 +++ b/Classes/x-saherelm.x-signaller.class.mq5 @@ -56,6 +56,16 @@ class XCBaseSignaller : public XCBase string symbol; // Symbol ... ENUM_TIMEFRAMES period; // Period ... + // + double slAdditionDistance; // SL Addition Distance ... + + // + // Restrictions ... + datetime restUntil; // Resting Time ... + int restingSignals; // Resting Signals ... + datetime lastSignalAt; // Holding Last Signal's Time ... + int restingDelay; // Resting Bars After Last Signal ... + // TCanAnalyse canAnalyseEventListener; @@ -80,6 +90,9 @@ class XCBaseSignaller : public XCBase symbol = _symbol; period = _period; + // + slAdditionDistance = 0; + // processAllTicks = _processAllTicks; defaultSignalR2R = _defaultSignalR2R; @@ -350,12 +363,27 @@ class XCBaseSignaller : public XCBase return; } + // + // Check Restrictions ... + if (HasRestrictions()) + { + // + bool ignore = HandleRestrictions(signal); + if (ignore) + { + return; + } + } + // // Do Notify ... for (int i = 0; i < count; i++) { onSignalEventListeners[i](signal); } + + // + lastSignalAt = signal.time; } /** @@ -526,6 +554,139 @@ class XCBaseSignaller : public XCBase return result; } + /** + * Check Signaller Has Restrictions or not ... + * + * @return ( bool ) + */ + bool HasRestrictions() + { + // + bool result = false; + + // + result = + // + // Rest Delay ... + restingDelay > 0 || + // + // Resting Signals ... + restingSignals > 0 || + // + // Rest Until ... + IsXValid(restUntil) + // + ; + + // + return result; + } + + /** + * Handle Restrictions On Signal ... + * + * @param signal: XSignal, reference to Provided Sginal ... + * + * @return ( bool ) + */ + bool HandleRestrictions(XSignal &signal) + { + // + // Ignore Signal Execution ... + bool result = true; + + // + // Check Restrictions Exists ... + if (!HasRestrictions()) + { + // + // Disable Signal Ignoring and Allow Notify Signal ... + result = false; + return result; + } + + // + datetime cTime = TimeCurrent(); + + // + // Resting Signals ... + if (restingSignals > 0) + { + // + restingSignals--; + return result; + } + + // + // Rest Until ... + if (IsXValid(restUntil)) + { + // + if (cTime > restUntil) + { + // + restUntil = NULL; + + // + // Disable Signal Ignoring and Allow Notify Signal ... + result = false; + return result; + } + else + { + // + // Ignore Signal ... + return result; + } + } + + // + // Resting Delay ... + if (restingDelay > 0 && + IsXValid(lastSignalAt)) + { + // + int lastSignalIDX = GetBarIndex( + signal.symbol, + signal.period, + lastSignalAt // + ); + if (IsValidIndex(lastSignalIDX)) + { + // + if (lastSignalIDX > restingDelay) + { + // + restingDelay = 0; + // + // Disable Signal Ignoring and Allow Notify Signal ... + result = false; + return result; + } + else + { + // + // Ignore Signal ... + return result; + } + } + } + + // + return result; + } + + /** + * Reset All Restrictions ... + */ + void ResetRestrictions() + { + // + restingDelay = 0; + restUntil = NULL; + restingSignals = 0; + } + // // Private ... private: diff --git a/Experts/x-saherelm.xfima.backtester.ea.mq5 b/Experts/x-saherelm.xfima.backtester.ea.mq5 index 19d9614b..b66d0f50 100644 --- a/Experts/x-saherelm.xfima.backtester.ea.mq5 +++ b/Experts/x-saherelm.xfima.backtester.ea.mq5 @@ -362,6 +362,7 @@ int OnInit() eaSignallerRiskInPoint, // Default Risk In Points ... eaSignallerVolume // Defaul Volume ... ); + fima1Signaller.slAdditionDistance = 15; fima1Signaller.AddOnSignalEventHandler(OnSignalTriggered); // @@ -722,7 +723,12 @@ int CheckForGuard( */ void OnStopLossTriggered(const XDeal &deal) { + // eaExpert.HandleOnStopLossTriggered(deal); + + // + HandleBalanceReport(); + HandleLoosingPosition(deal.positionId, deal.profit); } /** @@ -732,7 +738,11 @@ void OnStopLossTriggered(const XDeal &deal) */ void OnTakeProfitTriggered(const XDeal &deal) { + // eaExpert.HandleOnTakeProfitTriggered(deal); + + // + HandleBalanceReport(); } /** @@ -754,6 +764,10 @@ void OnPositionForceClosed( position, comment // ); + + // + HandleBalanceReport(); + HandleLoosingPosition(ticket, position.profit); } /** @@ -838,4 +852,44 @@ void OnTradeStateChanged(const XOnTradeHandlerState &state) eaExpert.HandleOnTradeStateChanged(state); } +/** + * Test Resting Signals ... + * + * @param ticket: ulong, Position Ticket ... + */ +void HandleLoosingPosition( + ulong ticket = 0, + double profit = 0 // +) +{ + // + // Check Position Loose ... + bool has = ticket > 0 && + profit < 0; + if (!has) + { + return; + } + + // + // NOTE: Here we Can Add Restrictions on Signaller based on our Requirements ... + // restingSignals: Specified Number of Signals which must to Ignore ... + // restUntil: Specified DateTime to Ignore all Signals before it Expiration ... + // restingDelay: Specified Bars Delay to Ignore all Signals before it passed ... + + // + // Increase Resting Signals of Signallers ... + fima1Signaller.restingSignals++; +} + +/** + * Handle Balance Report ... + */ +void HandleBalanceReport() +{ + // + string message = eaExpert.eaTrader.mAccount.GetBalanceReportMessage(); + eaExpert.eaAlert.SendAlert(message); +} + // \ No newline at end of file diff --git a/Libraries/x-saherelm.x-trade.lib.mq5 b/Libraries/x-saherelm.x-trade.lib.mq5 index 7a729375..354aaf97 100644 --- a/Libraries/x-saherelm.x-trade.lib.mq5 +++ b/Libraries/x-saherelm.x-trade.lib.mq5 @@ -719,11 +719,11 @@ struct XTarget // // Props ... bool doRF; // Do RF on Target - bool doRFOnEntry; // Do RF on Entry + bool doRFOnEntry; // Do RF on Entry double actingDistance; // Acting Distances double target; // Target Price for Actions double volumeMultiplier; // Volume Multiplier for Partial Close - double tpValue; // TP Value Changed ... + double tpValue; // TP Value Changed ... // // Constructor ... diff --git a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 index 473b0f93..5107bb92 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 @@ -215,6 +215,10 @@ class XCXFIMABaseSignaller : public XCBaseSignaller result = fimaInputs.IsValid() && fimaHelper != NULL && poiDetector != NULL; + if (!result) + { + return result; + } // return result; @@ -358,13 +362,11 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller ); // + // Handle Resting Signals ... has = HasDirection(iDir) && iZone.IsValid(); if (has) { - // - // Draw Zone ... - // // has = false; // iZone.Clean(); @@ -372,6 +374,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller } // + // Prepare Signal ... if (has) { // @@ -379,30 +382,73 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller isBearish = IsXBearish(iDir); // - // TODO: Provided SL ... + // Provided SL ... double _point = GetPoints(iBar.symbol); - double slAddition = 10 * _point; - double atrAddition = GetAverageTrueRange( - iZone.symbol, - iZone.period, - 0 // - ); + double slAddition = + slAdditionDistance <= 0 + ? 0 + : slAdditionDistance * _point; double slPrice = isBullish ? iZone.lower - slAddition : iZone.upper + slAddition; // - // Prepare Founded Signal ... + // Preparing Signal Targets ... + XTarget iTarget; + double spread = GetSpread(iZone.symbol); + double entry = GetEntry(iZone.symbol, iZone.dir); + double risk = MathAbs(entry - (isBullish ? iZone.lower : iZone.upper)); // - // Handle Signal Targets ... + // Handle Partial Close Position if Reached TP 1.5 ... + iTarget.Clean(); + iTarget.actingDistance = 1; + iTarget.volumeMultiplier = 0.5; + iTarget.target = isBullish ? entry + (1.5 * risk) : entry - (1.5 * risk); + iTarget.tpValue = isBullish ? entry + (2.5 * risk) : entry - (2.5 * risk); + AddRef(iTarget, iTargets); + + // + // Handle Ignore Signal Targets if Forced ... if (ignoreTargets) { XClean(iTargets); } // + // Handle Restrictions Based Signal Targets ... + if (risk > 0 && HasRestrictions()) + { + // + // Here we Can Do Target Preparing if Signaller Restricted and + // then ignore restrictions if required ... + + // + // Risk Free On Entry: + iTarget.Clean(); + iTarget.doRF = true; + iTarget.actingDistance = (5 * spread) / _point; + iTarget.target = isBullish ? entry + (2 * spread) : entry - (2 * spread); + AddRef(iTarget, iTargets); + + // + // Partial Close Position Half on TP 1 ... + // Increase Rewards to TP 3 ... + iTarget.Clean(); + iTarget.actingDistance = 1; + iTarget.volumeMultiplier = 0.5; + iTarget.target = isBullish ? entry + risk : entry - risk; + iTarget.tpValue = isBullish ? entry + (3 * risk) : entry - (3 * risk); + AddRef(iTarget, iTargets); + + // + // Reset Restrictions ... + ResetRestrictions(); + } + + // + // Prepare Founded Signal ... has = PrepareSignal( iSignal, iDir, @@ -417,10 +463,14 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // Notify On Signal Event ... NotifySignalEventListeners(iSignal); } + + // + // Cleanup ... + iTarget.Clean(); } // - // Cleanup Resources ... + // Cleanup ... iBar.Clean(); iZone.Clean(); iSignal.Clean();