Daily loss limit in an Expert Advisor: four decisions prop firms make you get right
A daily loss limit sounds like one line of code: "if today's loss is more than X%, stop". In practice it is four decisions, and each of them changes when the limit fires. Prop firms have made them unavoidable: break the daily limit once and the account is gone, whatever the strategy did the rest of the month. Here is how the limit is usually counted, where a simple implementation goes wrong, and the code I use in my Expert Advisor.
1. What is "today"?
The day of the trading server, not of your computer: TimeCurrent() is the clock MetaTrader shows everywhere. Prop firms reset the limit at midnight of their server or of a fixed time zone - check which one yours uses; if it is not the server's midnight, the reset hour has to be shifted. The start of the server day is simply:
datetime now = TimeCurrent(); datetime day = now - now % 86400; // 00:00 server time
2. Loss from what?
From the balance at the start of the day. Many prop firms take the balance or the equity at that moment, whichever is higher, so the stricter choice is the safe one: if you go into the night with a floating profit of 300, that profit is part of the base, and losing it back counts as a loss.
double base = MathMax(AccountInfoDouble(ACCOUNT_BALANCE), AccountInfoDouble(ACCOUNT_EQUITY));
3. Loss measured how?
On the equity, not on closed trades. A limit that looks only at closed trades lets an open position run far past it: the prop firm's monitor sees the floating loss, your code does not. So the check runs on every tick:
if(AccountInfoDouble(ACCOUNT_EQUITY) <= base * (1.0 - limitPercent / 100.0)) stopped = true; // close the positions, open nothing until the next day
and it is on the whole account. A limit per Expert Advisor is fine for your own risk control, but the prop firm counts every position together. If several copies of the program run on several charts, each of them sees the same account equity and each closes its own positions.
4. What survives a restart?
This is the one that a simple implementation always gets wrong. The base is remembered in a variable; the terminal restarts at 14:00 (an update, a VPS reboot, a change of inputs); the program starts again, takes the current balance as "the start of the day" - after the morning's losses - and allows another full limit. The day's state has to be stored outside the program. Terminal global variables are made for that:
string key = StringFormat("DL_%I64d_%I64u_%s_", AccountInfoInteger(ACCOUNT_LOGIN), magic, _Symbol);
if(GlobalVariableCheck(key + "day") && (datetime)GlobalVariableGet(key + "day") == day)
{
base = GlobalVariableGet(key + "base"); // the real start of the day
stopped = GlobalVariableGet(key + "stop") != 0.0;
}
else
{
GlobalVariableSet(key + "day", (double)day); // a new day: remember it
GlobalVariableSet(key + "base", base);
GlobalVariableSet(key + "stop", 0.0);
} Global variables are kept by the terminal for four weeks after the last access and are written to disk, so they survive a restart, a recompilation and a change of inputs.
Smaller details that matter
- Close and stop: when the limit fires, close this program's positions and refuse every new signal until the next day. Report it where the user looks (a line on the chart panel, an alert, a push notification), not only in the journal.
- A close can fail - the market is closed, the price moved, the server is busy. Retry, but not on every tick: once a second while the trading session is open is enough.
- In the Strategy Tester the global variables belong to the testing agent, and a test does not restart in the middle: the in-memory state is enough there.
- Choose the percent below the prop firm's limit. With 1% risk per trade, a 3% daily limit is three stopped trades; set your own limit at 4% if the firm's is 5%, because the price can gap past your stop.
In the product
Since version 1.09 Indicator Signal Trader Kb has exactly this: "Daily loss limit" in the inputs, off by default, counted on the whole account from the higher of balance and equity at the start of the server day, kept across restarts, with a red line on the panel when it fires. In the Strategy Tester, with the limit at 0.5% and 1% risk per trade, it fired 372 times over 2022-2026 on GBPUSD, and not a single position was opened after it on the same day - which is the only thing a daily limit has to guarantee.


