v5.7: self-heal GridHigh/GridLow if left at 0 by a restart-timing race

GridHigh/GridLow are never persisted (only lastPivotCalcDate is), so if
two restarts land close together near a server-day boundary, a fresh
process can find lastPivotCalcDate already matching 'today' and skip
CalculatePivotPoints() entirely -- leaving the band at its uninitialized
0/0 and every IsRangingMarket() check failing 'Invalid grid bounds' until
the next real day rollover. Cost XAUUSD/XAGUSD ~17h of dead trading on
2026-07-23 after the drift-enable and sizing deploys landed back-to-back.

Fix: both the OnInit guard and the OnTick day-rollover guard now also
recalc when GridHigh<=0 || GridLow<=0, regardless of date match. The
OnTick path recalcs only (no cancel/reset side effects) when it's the
same-day self-heal case, since that's not a real day transition.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-24 08:45:58 -04:00
co-authored by Claude Fable 5
parent 0e2409bfcf
commit 2bde52e43b
+17 -3
View File
@@ -5,12 +5,12 @@
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
#property copyright "Copyright 2024, Garfield Heron" #property copyright "Copyright 2024, Garfield Heron"
#property link "https://fetcherpay.com" #property link "https://fetcherpay.com"
#property version "5.6" #property version "5.7"
#include <Trade\Trade.mqh> #include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh> #include <Trade\PositionInfo.mqh>
#define VERSION "Version 5.6 Smart Grid Breakout BO MT5" #define VERSION "Version 5.7 Smart Grid Breakout BO MT5"
#define MAX_TRADES 600 #define MAX_TRADES 600
#define MAX_LOG_TRADES 1200 #define MAX_LOG_TRADES 1200
@@ -1351,7 +1351,13 @@ int OnInit()
LoadGridState(); LoadGridState();
if(lastPivotCalcDate != TodayStartBroker()) // GridHigh/GridLow are NOT persisted (only lastPivotCalcDate is) — if a
// prior process already recalculated today before this restart, the
// date-match guard alone would skip CalculatePivotPoints() and leave the
// band at its uninitialized 0/0, causing "Invalid grid bounds" until the
// next real day rollover (5.7 fix — cost XAUUSD/XAGUSD ~17h on 2026-07-23
// after two restarts landed close together near a day boundary).
if(lastPivotCalcDate != TodayStartBroker() || GridHigh <= 0 || GridLow <= 0)
CalculatePivotPoints(); CalculatePivotPoints();
bGetOutOK = (GetOut=="L"||GetOut=="l"||GetOut=="A"||GetOut=="a"|| bGetOutOK = (GetOut=="L"||GetOut=="l"||GetOut=="A"||GetOut=="a"||
@@ -1471,6 +1477,14 @@ void OnTick()
cycleProfitStop = false; cycleProfitStop = false;
CalculatePivotPoints(); // also updates lastPivotCalcDate & saves CalculatePivotPoints(); // also updates lastPivotCalcDate & saves
} }
else if(GridHigh <= 0 || GridLow <= 0)
{
// Self-heal (5.7): same-day, but the band was never actually computed
// this process (see OnInit comment above). Recalc only — no
// cancel/reset, since this isn't a real day transition.
PrintS("Grid bounds invalid on same-day check — self-healing recalc");
CalculatePivotPoints();
}
// --- Profit target check runs every tick (cheap) --- // --- Profit target check runs every tick (cheap) ---
if(CheckProfitTarget()) if(CheckProfitTarget())