Prop-Firm Gold EAs Fail on the Reset, Not the Stop
A prop firm measures the daily loss on equity from a balance taken at midnight, ratchets the max-loss floor at that same instant, and charges a Friday gold position to Monday. What an MT5 expert advisor has to enforce, and what it cannot.
Most gold EAs are built to survive the market. Prop-firm accounts fail them on arithmetic: which number the loss limit is measured from, and at what instant it is taken. The desk's EA library covers sizing, regime gates and costs; this sits above all of it, because an edge can still lose an account without breaking a single stop.
1. The daily floor is anchored to a balance taken at midnight
FTMO's Maximum Daily Loss lesson defines the limit as the level below which equity cannot drop at any point in the day, where equity is balance plus open position P/L, plus swaps, minus commissions. Floating loss counts the moment it exists.
The floor itself is rebuilt at 00:00 CE(S)T. The trading objectives page says it is the difference between the account balance recorded at 00:00 of the current day and the loss amount — 3% of initial capital on 1-Step products, 5% on 2-Step and Verification.
Two anchors, two different measurements, and the gap between them is where EAs die:
- The floor moves with balance, so a floating profit held through midnight does not enlarge tomorrow's allowance.
- The breach test runs on equity, so a floating loss at 00:00 is spent against the new day before anything closes.
- A loss realised at 00:05 is charged to the new day, because the anchor was taken at 00:00.
On a $100,000 account at 3% the allowance is $3,000. If the balance at midnight is $103,000, the floor is $100,000. An EA carrying a $2,400 floating loss into the Asia session has $600 of room, and one more trade at its normal risk breaches a rule it never tested. The fix is not a tighter stop; it is being flat across the reset.
2. The max-loss floor moves once a day, and only up
The same page defines the second floor as an end-of-day trailing limit: the highest balance recorded at 00:00 of any preceding trading day, or the initial capital if that is higher, minus 10% of initial capital. It can only increase.
Note what is absent: the intraday equity peak. A gold EA that prints a new equity high at 14:00 and gives it back by 21:00 has raised nothing. Only a midnight balance ratchets the floor, so booking profit before the reset moves it and booking it after does not. An EA's protection floor can therefore sit thousands below the equity it just printed, in exactly the session that produces the drawdown.
Confirm which product the account is on: the 1-Step and 2-Step definitions do not share an anchor, and everything above is the 1-Step one.
3. Friday's position is charged to Monday
Gold is where this stops resembling EURUSD, and the desk has its own numbers. Across the 17 Sunday reopens between 1 July and 27 October 2026, on Investing.com daily bars where Monday's open is the Sunday reopen print:
- median gap $4.52, mean $9.11, largest $39.45
- 8 of the 17 gaps exceeded $5; 4 exceeded $15
- ATR(14) over the same window: $66.99, so a 0.7×ATR stop is $46.89
- median daily range across the 84 completed sessions: $86.62
Read that honestly: no weekend gap in the sample came close to a properly sized stop. Gap risk is not a case for a wider stop on gold. It is a case about the clock, because the gap prints on the first tick of the new server day. On a CE(S)T account the Sunday 22:00 UTC reopen is 00:00 Monday — the loss lands on Monday's equity, against Monday's anchor, with no order sent and no stop touched.
It is also a case about the rulebook. FTMO's forbidden practices list gap trading explicitly: opening trades when major news is scheduled, or two hours or less before a market closes for at least two hours. A gold EA whose Friday signal fires at 19:00 UTC is doing that, however good the setup looks.
4. The news window blocks exits as well
The news rule restricts order execution for two minutes before and after selected releases, and the restricted list names gold (XAUUSD) alongside dollar pairs and US indices. What EAs get wrong is the scope: it covers any order execution, "including your Stop Loss, Take Profit or any other pending orders".
A trailing stop that moves at 12:31 on a CPI day is a rule violation, not a risk adjustment. The guard has to freeze every send — entries, exits, stop and target modifications, pending-order edits — and the bracket has to be set wide enough beforehand that it needs no touching inside the window. The rule skips Swing accounts and the Challenge and Verification phases, which is why it gets discovered on the funded account.
5. The guard, in MQL5
Account values come from the MQL5 account constants. The block is small on purpose: a guard that can throw is worse than none.
#define GV_INIT "rg.initial"
#define GV_ANCHOR "rg.anchor"
#define GV_DAY "rg.day"
#define GV_PEAK "rg.peak"
input double InpDailyPct = 3.0; // % of initial capital (1-Step)
input double InpMaxPct = 10.0;
input double InpAct = 0.75; // act at 75% of the allowance
double Initial()
{
if(!GlobalVariableCheck(GV_INIT))
GlobalVariableSet(GV_INIT, AccountInfoDouble(ACCOUNT_BALANCE));
return GlobalVariableGet(GV_INIT);
}
void RollDay()
{
MqlDateTime d; TimeToStruct(TimeCurrent(), d);
datetime day = StringToTime(StringFormat("%04d.%02d.%02d", d.year, d.mon, d.day));
if(day == (datetime)GlobalVariableGet(GV_DAY)) return;
double bal = AccountInfoDouble(ACCOUNT_BALANCE);
GlobalVariableSet(GV_ANCHOR, bal);
if(bal > GlobalVariableGet(GV_PEAK)) GlobalVariableSet(GV_PEAK, bal);
GlobalVariableSet(GV_DAY, (double)day);
}
bool Breached()
{
double eq = AccountInfoDouble(ACCOUNT_EQUITY);
double init = Initial();
double daily = GlobalVariableGet(GV_ANCHOR) - init * InpDailyPct / 100.0 * InpAct;
double peak = MathMax(GlobalVariableGet(GV_PEAK), init);
double total = peak - init * InpMaxPct / 100.0;
return (eq <= daily || eq <= total);
}Three details matter more than the code. TimeCurrent() is server time, so the reset is the broker's midnight, not yours. RollDay() records the balance on the first tick after it — the balance at that tick, not at 00:00:00, which on a quiet Sunday can be minutes later. And Breached() reads account equity, so it covers every position, not the ones carrying your magic number: the firm measures the account, not the strategy.
In OnTick the order matters: RollDay(), then if(Breached()) { FlattenAll(); return; }, then the entry logic. FlattenAll() should walk PositionsTotal() downwards with PositionGetTicket(i) and close each position — on a hedging account, closing by symbol and magic leaves the manual trade that caused the breach.
6. What the guard cannot fix
- The hyperactivity threshold. FTMO's strategy FAQ calls more than 2,000 server requests per day hyperactivity, on top of a 200-order and 2,000-position daily ceiling. A trailing stop rewritten every tick is how a quiet EA gets there: batch the modification, and skip it inside 0.1×ATR of the current level.
- The allocation cap. $400,000 per trader or strategy across accounts, which a widely sold EA reaches quickly.
- A gap through a limit order. Nothing in the EA layer changes a fill; the only control is not holding the position.
The discipline that survives this is the desk's own: fixed fractional risk, a stop outside the noise band, and the account flat when the clock rolls over. The position-size calculator covers the first, the regime-gate and setfile notes the second, and the reset covers the rest.
Not financial advice. Prop-firm terms differ by product and change without notice — read your own rulebook and treat the percentages above as examples.
Sources
- FTMO Academy — Maximum Daily Loss
- FTMO — Trading Objectives
- FTMO — Can I trade news?
- FTMO — Forbidden Trading Practices
- FTMO — Instruments and strategies
- MQL5 — Account Properties
- XAUUSD daily bars, 1 Jul – 27 Oct 2026: 17 Sunday reopens, 84 completed sessions, Investing.com