fix: Use bar[1] (just-closed) and bar[2] (prior closed) everywhere
This commit is contained in:
+27
-25
@@ -5,7 +5,7 @@
|
|||||||
//| Based on: ORB-All-Sessions.pine + LuxAlgo Order Block Detector |
|
//| Based on: ORB-All-Sessions.pine + LuxAlgo Order Block Detector |
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
#property copyright "NANDR"
|
#property copyright "NANDR"
|
||||||
#property version "1.00"
|
#property version "1.10"
|
||||||
#property strict
|
#property strict
|
||||||
|
|
||||||
#include <Trade\Trade.mqh>
|
#include <Trade\Trade.mqh>
|
||||||
@@ -500,49 +500,48 @@ void UpdateORBSessions()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
bool CheckStrictBreakout(int dir, double orbLevel)
|
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;
|
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);
|
int bars = Bars(g_Symbol, PERIOD_CURRENT);
|
||||||
if(bars < N + 2) return false;
|
if(bars < N + 3) return false;
|
||||||
|
|
||||||
if(dir > 0) // bullish
|
if(dir > 0) // bullish
|
||||||
{
|
{
|
||||||
// low[N] < orbLevel (pre-breakout penetration from below)
|
if(iLow(g_Symbol, PERIOD_CURRENT, N + 2) >= orbLevel) return false;
|
||||||
// Then all N bars: low > orbLevel AND close > orbLevel
|
for(int i = 2; i <= N + 1; i++)
|
||||||
// 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, i) <= orbLevel) return false;
|
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, i) <= orbLevel) return false;
|
||||||
}
|
}
|
||||||
if(iClose(g_Symbol, PERIOD_CURRENT, 0) <= iLow(g_Symbol, PERIOD_CURRENT, 1)) return false;
|
if(iClose(g_Symbol, PERIOD_CURRENT, 1) <= iLow(g_Symbol, PERIOD_CURRENT, 2)) return false;
|
||||||
if(iLow(g_Symbol, PERIOD_CURRENT, 0) <= orbLevel) return false;
|
if(iLow(g_Symbol, PERIOD_CURRENT, 1) <= orbLevel) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else // bearish
|
else // bearish
|
||||||
{
|
{
|
||||||
if(iHigh(g_Symbol, PERIOD_CURRENT, N + 1) <= orbLevel) return false;
|
if(iHigh(g_Symbol, PERIOD_CURRENT, N + 2) <= orbLevel) return false;
|
||||||
for(int i = 1; i <= N; i++)
|
for(int i = 2; i <= N + 1; i++)
|
||||||
{
|
{
|
||||||
if(iHigh(g_Symbol, PERIOD_CURRENT, i) >= orbLevel) return false;
|
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, i) >= orbLevel) return false;
|
||||||
}
|
}
|
||||||
if(iClose(g_Symbol, PERIOD_CURRENT, 0) >= iHigh(g_Symbol, PERIOD_CURRENT, 1)) return false;
|
if(iClose(g_Symbol, PERIOD_CURRENT, 1) >= iHigh(g_Symbol, PERIOD_CURRENT, 2)) return false;
|
||||||
if(iHigh(g_Symbol, PERIOD_CURRENT, 0) >= orbLevel) return false;
|
if(iHigh(g_Symbol, PERIOD_CURRENT, 1) >= orbLevel) return false;
|
||||||
return true;
|
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)
|
bool CheckSimpleBreakout(int dir, double orbLevel)
|
||||||
{
|
{
|
||||||
double c0 = iClose(g_Symbol, PERIOD_CURRENT, 0);
|
double c0 = iClose(g_Symbol, PERIOD_CURRENT, 1); // just-closed bar
|
||||||
double c1 = iClose(g_Symbol, PERIOD_CURRENT, 1);
|
double c1 = iClose(g_Symbol, PERIOD_CURRENT, 2); // bar before it
|
||||||
if(dir > 0) return (c1 <= orbLevel && c0 > orbLevel);
|
if(dir > 0) return (c1 <= orbLevel && c0 > orbLevel);
|
||||||
else 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;
|
if(!g_Sessions[sessIdx].inBreakout) return false;
|
||||||
|
|
||||||
double c0 = iClose(g_Symbol, PERIOD_CURRENT, 0);
|
// Use bar[1] (just-closed bar) as the retest candidate and bar[2] as context.
|
||||||
double c1 = iClose(g_Symbol, PERIOD_CURRENT, 1);
|
// This mirrors Pine Script: decisions only on completed candles, never on bar[0]
|
||||||
double h0 = iHigh(g_Symbol, PERIOD_CURRENT, 0);
|
// which is only the opening price at new-bar time.
|
||||||
double l0 = iLow(g_Symbol, PERIOD_CURRENT, 0);
|
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)
|
if(g_Sessions[sessIdx].breakoutDir == 1)
|
||||||
{
|
{
|
||||||
bool retest = (c1 > g_Sessions[sessIdx].orbHigh)
|
bool retest = (c1 > g_Sessions[sessIdx].orbHigh)
|
||||||
@@ -604,7 +606,7 @@ bool DetectRetest(int sessIdx, int &dir)
|
|||||||
&& (c0 >= g_Sessions[sessIdx].orbHigh);
|
&& (c0 >= g_Sessions[sessIdx].orbHigh);
|
||||||
if(retest) { dir = 1; return true; }
|
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)
|
else if(g_Sessions[sessIdx].breakoutDir == -1)
|
||||||
{
|
{
|
||||||
bool retest = (c1 < g_Sessions[sessIdx].orbLow)
|
bool retest = (c1 < g_Sessions[sessIdx].orbLow)
|
||||||
@@ -613,7 +615,7 @@ bool DetectRetest(int sessIdx, int &dir)
|
|||||||
if(retest) { dir = -1; return true; }
|
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
|
if(g_Sessions[sessIdx].breakoutDir == 1
|
||||||
&& c0 < g_Sessions[sessIdx].orbHigh && c1 > g_Sessions[sessIdx].orbHigh)
|
&& c0 < g_Sessions[sessIdx].orbHigh && c1 > g_Sessions[sessIdx].orbHigh)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user