From 9abe4d4ef6e157720074245bbfedb80fc7149814 Mon Sep 17 00:00:00 2001 From: Naji El Chemaly Date: Wed, 3 Jun 2026 23:10:17 +0300 Subject: [PATCH] fix: Use bar[1] (just-closed) and bar[2] (prior closed) everywhere --- NANDR_ORB_OB_EA.mq5 | 52 +++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/NANDR_ORB_OB_EA.mq5 b/NANDR_ORB_OB_EA.mq5 index a1e1179..e2d377b 100644 --- a/NANDR_ORB_OB_EA.mq5 +++ b/NANDR_ORB_OB_EA.mq5 @@ -5,7 +5,7 @@ //| Based on: ORB-All-Sessions.pine + LuxAlgo Order Block Detector | //+------------------------------------------------------------------+ #property copyright "NANDR" -#property version "1.00" +#property version "1.10" #property strict #include @@ -500,49 +500,48 @@ void UpdateORBSessions() //+------------------------------------------------------------------+ bool CheckStrictBreakout(int dir, double orbLevel) { - int N = g_BreakoutConfBars; // number of confirmation bars (already shifted) + int N = g_BreakoutConfBars; if(N < 2) N = 2; - // Need at least N+1 bars of history + // Need at least N+3 closed bars (all indices shifted +1 vs simple version) int bars = Bars(g_Symbol, PERIOD_CURRENT); - if(bars < N + 2) return false; + if(bars < N + 3) return false; if(dir > 0) // bullish { - // low[N] < orbLevel (pre-breakout penetration from below) - // Then all N bars: low > orbLevel AND close > orbLevel - // Current bar: close > low[1] AND low > orbLevel - if(iLow(g_Symbol, PERIOD_CURRENT, N + 1) >= orbLevel) return false; - for(int i = 1; i <= N; i++) + if(iLow(g_Symbol, PERIOD_CURRENT, N + 2) >= orbLevel) return false; + for(int i = 2; i <= N + 1; i++) { if(iLow(g_Symbol, PERIOD_CURRENT, i) <= orbLevel) return false; if(iClose(g_Symbol, PERIOD_CURRENT, i) <= orbLevel) return false; } - if(iClose(g_Symbol, PERIOD_CURRENT, 0) <= iLow(g_Symbol, PERIOD_CURRENT, 1)) return false; - if(iLow(g_Symbol, PERIOD_CURRENT, 0) <= orbLevel) return false; + if(iClose(g_Symbol, PERIOD_CURRENT, 1) <= iLow(g_Symbol, PERIOD_CURRENT, 2)) return false; + if(iLow(g_Symbol, PERIOD_CURRENT, 1) <= orbLevel) return false; return true; } else // bearish { - if(iHigh(g_Symbol, PERIOD_CURRENT, N + 1) <= orbLevel) return false; - for(int i = 1; i <= N; i++) + if(iHigh(g_Symbol, PERIOD_CURRENT, N + 2) <= orbLevel) return false; + for(int i = 2; i <= N + 1; i++) { if(iHigh(g_Symbol, PERIOD_CURRENT, i) >= orbLevel) return false; if(iClose(g_Symbol, PERIOD_CURRENT, i) >= orbLevel) return false; } - if(iClose(g_Symbol, PERIOD_CURRENT, 0) >= iHigh(g_Symbol, PERIOD_CURRENT, 1)) return false; - if(iHigh(g_Symbol, PERIOD_CURRENT, 0) >= orbLevel) return false; + if(iClose(g_Symbol, PERIOD_CURRENT, 1) >= iHigh(g_Symbol, PERIOD_CURRENT, 2)) return false; + if(iHigh(g_Symbol, PERIOD_CURRENT, 1) >= orbLevel) return false; return true; } } //+------------------------------------------------------------------+ -//| Simple breakout: close crosses ORB level | +//| Simple breakout: uses bar[1] (just-closed) vs bar[2] | +//| Matches Pine Script bar-close evaluation — never checks an | +//| in-progress candle so no premature signals at bar open. | //+------------------------------------------------------------------+ bool CheckSimpleBreakout(int dir, double orbLevel) { - double c0 = iClose(g_Symbol, PERIOD_CURRENT, 0); - double c1 = iClose(g_Symbol, PERIOD_CURRENT, 1); + double c0 = iClose(g_Symbol, PERIOD_CURRENT, 1); // just-closed bar + double c1 = iClose(g_Symbol, PERIOD_CURRENT, 2); // bar before it if(dir > 0) return (c1 <= orbLevel && c0 > orbLevel); else return (c1 >= orbLevel && c0 < orbLevel); } @@ -591,12 +590,15 @@ bool DetectRetest(int sessIdx, int &dir) { if(!g_Sessions[sessIdx].inBreakout) return false; - double c0 = iClose(g_Symbol, PERIOD_CURRENT, 0); - double c1 = iClose(g_Symbol, PERIOD_CURRENT, 1); - double h0 = iHigh(g_Symbol, PERIOD_CURRENT, 0); - double l0 = iLow(g_Symbol, PERIOD_CURRENT, 0); + // Use bar[1] (just-closed bar) as the retest candidate and bar[2] as context. + // This mirrors Pine Script: decisions only on completed candles, never on bar[0] + // which is only the opening price at new-bar time. + double c0 = iClose(g_Symbol, PERIOD_CURRENT, 1); // just-closed bar + double c1 = iClose(g_Symbol, PERIOD_CURRENT, 2); // bar before it + double h0 = iHigh(g_Symbol, PERIOD_CURRENT, 1); + double l0 = iLow(g_Symbol, PERIOD_CURRENT, 1); - // Bullish retest: previous bar was above ORB, this bar touched it and closed back above + // Bullish retest: bar[2] confirmed above ORB high, bar[1] dipped to ORB and closed back above if(g_Sessions[sessIdx].breakoutDir == 1) { bool retest = (c1 > g_Sessions[sessIdx].orbHigh) @@ -604,7 +606,7 @@ bool DetectRetest(int sessIdx, int &dir) && (c0 >= g_Sessions[sessIdx].orbHigh); if(retest) { dir = 1; return true; } } - // Bearish retest: previous bar was below ORB, this bar touched it and closed back below + // Bearish retest: bar[2] confirmed below ORB low, bar[1] ticked back to ORB and closed back below else if(g_Sessions[sessIdx].breakoutDir == -1) { bool retest = (c1 < g_Sessions[sessIdx].orbLow) @@ -613,7 +615,7 @@ bool DetectRetest(int sessIdx, int &dir) if(retest) { dir = -1; return true; } } - // Failed retest + // Failed retest — only on a COMPLETED bar, never on bar open if(g_Sessions[sessIdx].breakoutDir == 1 && c0 < g_Sessions[sessIdx].orbHigh && c1 > g_Sessions[sessIdx].orbHigh) {