Your daily loss limit resets itself every time MetaTrader restarts

# bug# programming# software
Your daily loss limit resets itself every time MetaTrader restartsxuks124

Most MT5 "daily loss guard" implementations look like this: double today_pnl = 0.0; //...

Most MT5 "daily loss guard" implementations look like this:

double today_pnl = 0.0;      // module-level variable
bool   daily_blocked = false;
Enter fullscreen mode Exit fullscreen mode

It works fine — until the terminal restarts, the EA is recompiled, the chart is switched, or the config is reloaded. Every one of those calls OnInit() again and zeroes the variable. Your hard daily cap cheerfully hands you back the full day's risk budget.

If you trade a prop-firm account (5% daily drawdown rule), this is not a small bug: crashes and restarts cluster on bad trading days, exactly when you need that guard most.

VigilDesk risk-control dashboard

What "persistence" actually has to survive

Event Memory var Terminal globals File (common folder)
New tick / new bar yes yes yes
EA recompile / re-attach no yes yes
Terminal restart no yes yes
Reinstall / another machine / several terminals no no yes

GlobalVariableSet() covers the common cases. The file wins the last row.

The three fields you must persist

struct GuardState
{
   long   day_stamp;          // which trading day this state belongs to
   double day_start_balance;  // anchor for the daily drawdown
   bool   blocked;            // has the day already tripped
};
Enter fullscreen mode Exit fullscreen mode

day_stamp is the field people forget. Without it the restored state is either ignored forever or applied forever. Both are wrong.

Pitfall 1: the trading day must come from the broker clock

long TradingDayStamp()
{
   MqlDateTime t;
   TimeToStruct(TimeTradeServer(), t);   // NOT TimeLocal()
   return((long)t.year * 10000 + t.mon * 100 + t.day);
}
Enter fullscreen mode Exit fullscreen mode

TimeLocal() resets your cap in the middle of the session. TimeCurrent() is the last quote time and lags badly in quiet markets.

Pitfall 2: persist first, then act

if(blocked) return;                  // cheap, and catches externally triggered blocks
if(!risk_ok) { blocked = true; SaveState(); return; }
SendOrder();
Enter fullscreen mode Exit fullscreen mode

Wrong order + one crash between the two lines = one order that should never have been sent.

Pitfall 3: one EA cannot police another EA

MQL5 has no cross-program order hook. Your "guard EA" cannot stop an order another EA (or a Python strategy on the same account) is about to send. Three options: close positions when the cap trips, publish a terminal global your own strategies respect, or move risk control outside the terminal.

The free guard EA attached to an XAUUSD chart

The only test worth running

  1. Set a cap that trips within minutes.
  2. Let it trip.
  3. Kill the terminal process (not just the EA) with positions open.
  4. Reopen it and try to send another order.

If the new process happily sends the order, your state was in memory and the guard was decoration.

Conclusion

Three lines of discipline: state on disk, broker trading day, write before send. That is the difference between a risk limit and a wish.

I packaged this as a free, open MT5 tool (pure MQL5, no DLL, no network calls, percentages only):
https://xuks124.github.io/vigildesk/free.html

No profit promises — it only handles risk control.