fix: 3 duplicate trades in 1 second, London SELL fired against established bullish bias
This commit is contained in:
+54
-17
@@ -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.33"
|
#property version "1.34"
|
||||||
#property strict
|
#property strict
|
||||||
|
|
||||||
#include <Trade\Trade.mqh>
|
#include <Trade\Trade.mqh>
|
||||||
@@ -90,6 +90,7 @@ input bool InpWaitForRetest = true; // Wait for ORB Retest
|
|||||||
input int InpBreakoutExpireBars = 20; // Bars Before Breakout Expires (0=never)
|
input int InpBreakoutExpireBars = 20; // Bars Before Breakout Expires (0=never)
|
||||||
input bool InpUseOBRetestEntry = true; // OB Retest Entry (enter on OB boundary retest)
|
input bool InpUseOBRetestEntry = true; // OB Retest Entry (enter on OB boundary retest)
|
||||||
input int InpMaxRetestsPerSession = 3; // Max Retest Entries Per Session (per breakout)
|
input int InpMaxRetestsPerSession = 3; // Max Retest Entries Per Session (per breakout)
|
||||||
|
input bool InpUseSessionBiasFilter = true; // Session Bias Filter: block signals against day bias
|
||||||
|
|
||||||
// --- Lot Size & Risk ---
|
// --- Lot Size & Risk ---
|
||||||
input group "═══ Lot Size & Risk ═══"
|
input group "═══ Lot Size & Risk ═══"
|
||||||
@@ -155,19 +156,21 @@ struct SSession
|
|||||||
int breakoutBarsAgo;
|
int breakoutBarsAgo;
|
||||||
|
|
||||||
int tradesThisSession;
|
int tradesThisSession;
|
||||||
|
bool retestFiredThisBar; // blocks duplicate entries on consecutive ticks within same bar
|
||||||
|
|
||||||
void Reset()
|
void Reset()
|
||||||
{
|
{
|
||||||
orbHigh = 0;
|
orbHigh = 0;
|
||||||
orbLow = DBL_MAX;
|
orbLow = DBL_MAX;
|
||||||
orbBarCount = 0;
|
orbBarCount = 0;
|
||||||
orbComplete = false;
|
orbComplete = false;
|
||||||
orbStartTime = 0;
|
orbStartTime = 0;
|
||||||
breakoutDir = 0;
|
breakoutDir = 0;
|
||||||
inBreakout = false;
|
inBreakout = false;
|
||||||
inRetest = false;
|
inRetest = false;
|
||||||
breakoutBarsAgo= 0;
|
breakoutBarsAgo = 0;
|
||||||
tradesThisSession = 0;
|
tradesThisSession = 0;
|
||||||
|
retestFiredThisBar = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -209,6 +212,11 @@ SOrderBlock g_BearOBs[];
|
|||||||
int g_BullOBCount = 0;
|
int g_BullOBCount = 0;
|
||||||
int g_BearOBCount = 0;
|
int g_BearOBCount = 0;
|
||||||
|
|
||||||
|
// Day bias: direction of the first confirmed ORB breakout of the day (0=none, 1=bull, -1=bear).
|
||||||
|
// When InpUseSessionBiasFilter=true, subsequent session breakouts and all OB entries that
|
||||||
|
// contradict this bias are suppressed, preventing counter-trend trades.
|
||||||
|
int g_GlobalBiasDir = 0;
|
||||||
|
|
||||||
// Daily stats
|
// Daily stats
|
||||||
datetime g_LastDayReset = 0;
|
datetime g_LastDayReset = 0;
|
||||||
int g_TodayTrades = 0;
|
int g_TodayTrades = 0;
|
||||||
@@ -466,6 +474,10 @@ void UpdateORBSessions()
|
|||||||
double bar1High = iHigh(g_Symbol, PERIOD_CURRENT, 1);
|
double bar1High = iHigh(g_Symbol, PERIOD_CURRENT, 1);
|
||||||
double bar1Low = iLow(g_Symbol, PERIOD_CURRENT, 1);
|
double bar1Low = iLow(g_Symbol, PERIOD_CURRENT, 1);
|
||||||
|
|
||||||
|
// New bar: clear per-bar retest flag so the next wick can trigger a fresh entry
|
||||||
|
for(int s = 0; s < g_SessionCount; s++)
|
||||||
|
g_Sessions[s].retestFiredThisBar = false;
|
||||||
|
|
||||||
for(int s = 0; s < g_SessionCount; s++)
|
for(int s = 0; s < g_SessionCount; s++)
|
||||||
{
|
{
|
||||||
if(!g_Sessions[s].enabled) continue;
|
if(!g_Sessions[s].enabled) continue;
|
||||||
@@ -590,19 +602,35 @@ void DetectBreakouts()
|
|||||||
|
|
||||||
if(bullBO)
|
if(bullBO)
|
||||||
{
|
{
|
||||||
|
// Bias filter: suppress if day bias is already bearish
|
||||||
|
if(InpUseSessionBiasFilter && g_GlobalBiasDir == -1)
|
||||||
|
{
|
||||||
|
PrintFormat("NANDR EA: [%s] Bullish breakout SUPPRESSED — day bias is BEARISH",
|
||||||
|
g_Sessions[s].name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
g_Sessions[s].breakoutDir = 1;
|
g_Sessions[s].breakoutDir = 1;
|
||||||
g_Sessions[s].inBreakout = true;
|
g_Sessions[s].inBreakout = true;
|
||||||
g_Sessions[s].breakoutBarsAgo= 0;
|
g_Sessions[s].breakoutBarsAgo= 0;
|
||||||
PrintFormat("NANDR EA: [%s] Bullish ORB breakout at %.2f",
|
if(g_GlobalBiasDir == 0) g_GlobalBiasDir = 1; // first breakout of the day sets bias
|
||||||
g_Sessions[s].name, g_Sessions[s].orbHigh);
|
PrintFormat("NANDR EA: [%s] Bullish ORB breakout at %.2f [DayBias=%d]",
|
||||||
|
g_Sessions[s].name, g_Sessions[s].orbHigh, g_GlobalBiasDir);
|
||||||
}
|
}
|
||||||
else if(bearBO)
|
else if(bearBO)
|
||||||
{
|
{
|
||||||
|
// Bias filter: suppress if day bias is already bullish
|
||||||
|
if(InpUseSessionBiasFilter && g_GlobalBiasDir == 1)
|
||||||
|
{
|
||||||
|
PrintFormat("NANDR EA: [%s] Bearish breakout SUPPRESSED — day bias is BULLISH",
|
||||||
|
g_Sessions[s].name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
g_Sessions[s].breakoutDir = -1;
|
g_Sessions[s].breakoutDir = -1;
|
||||||
g_Sessions[s].inBreakout = true;
|
g_Sessions[s].inBreakout = true;
|
||||||
g_Sessions[s].breakoutBarsAgo= 0;
|
g_Sessions[s].breakoutBarsAgo= 0;
|
||||||
PrintFormat("NANDR EA: [%s] Bearish ORB breakout at %.2f",
|
if(g_GlobalBiasDir == 0) g_GlobalBiasDir = -1; // first breakout of the day sets bias
|
||||||
g_Sessions[s].name, g_Sessions[s].orbLow);
|
PrintFormat("NANDR EA: [%s] Bearish ORB breakout at %.2f [DayBias=%d]",
|
||||||
|
g_Sessions[s].name, g_Sessions[s].orbLow, g_GlobalBiasDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1056,6 +1084,10 @@ void CheckRetestEntriesTick()
|
|||||||
|
|
||||||
if(dir == 0) continue;
|
if(dir == 0) continue;
|
||||||
|
|
||||||
|
// One entry per wick touch per bar — prevents 3 duplicate trades on consecutive ticks
|
||||||
|
if(g_Sessions[s].retestFiredThisBar) continue;
|
||||||
|
g_Sessions[s].retestFiredThisBar = true;
|
||||||
|
|
||||||
double obTop = 0, obBottom = 0;
|
double obTop = 0, obBottom = 0;
|
||||||
IsOBNearLevel(orbLevel, dir, obTop, obBottom);
|
IsOBNearLevel(orbLevel, dir, obTop, obBottom);
|
||||||
if(InpOBRequireConf && obTop == 0) continue;
|
if(InpOBRequireConf && obTop == 0) continue;
|
||||||
@@ -1066,8 +1098,9 @@ void CheckRetestEntriesTick()
|
|||||||
if(!InpUseOBRetestEntry) return;
|
if(!InpUseOBRetestEntry) return;
|
||||||
|
|
||||||
// ── Bearish OB Retest → SELL at wick touch ───────────────────────
|
// ── Bearish OB Retest → SELL at wick touch ───────────────────────
|
||||||
// Fires the moment the current bar's live high reaches the OB bottom.
|
// Suppressed when day bias is bullish (session takes priority).
|
||||||
// prev bar[1] (or current open) must have been at/below OB bottom.
|
if(InpUseSessionBiasFilter && g_GlobalBiasDir == 1) return;
|
||||||
|
|
||||||
for(int i = 0; i < g_BearOBCount; i++)
|
for(int i = 0; i < g_BearOBCount; i++)
|
||||||
{
|
{
|
||||||
if(!g_BearOBs[i].active || g_BearOBs[i].traded) continue;
|
if(!g_BearOBs[i].active || g_BearOBs[i].traded) continue;
|
||||||
@@ -1104,6 +1137,9 @@ void CheckRetestEntriesTick()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Bullish OB Retest → BUY at wick touch ────────────────────────
|
// ── Bullish OB Retest → BUY at wick touch ────────────────────────
|
||||||
|
// Suppressed when day bias is bearish (session takes priority).
|
||||||
|
if(InpUseSessionBiasFilter && g_GlobalBiasDir == -1) return;
|
||||||
|
|
||||||
for(int i = 0; i < g_BullOBCount; i++)
|
for(int i = 0; i < g_BullOBCount; i++)
|
||||||
{
|
{
|
||||||
if(!g_BullOBs[i].active || g_BullOBs[i].traded) continue;
|
if(!g_BullOBs[i].active || g_BullOBs[i].traded) continue;
|
||||||
@@ -1275,6 +1311,7 @@ void CheckDailyReset()
|
|||||||
g_TodayPnL = 0;
|
g_TodayPnL = 0;
|
||||||
g_DayStartEquity = AccountInfoDouble(ACCOUNT_EQUITY);
|
g_DayStartEquity = AccountInfoDouble(ACCOUNT_EQUITY);
|
||||||
g_TradingHalted = false;
|
g_TradingHalted = false;
|
||||||
|
g_GlobalBiasDir = 0; // clear day bias — first session breakout will re-establish it
|
||||||
|
|
||||||
// Reset all session ORB data for the new day
|
// Reset all session ORB data for the new day
|
||||||
for(int s = 0; s < g_SessionCount; s++)
|
for(int s = 0; s < g_SessionCount; s++)
|
||||||
|
|||||||
Reference in New Issue
Block a user