Most Expert Advisors are designed to keep doing their job: find a setup, open a trade, manage it, and move on to the next one.
That’s exactly what you want when everything is working normally.
The problem starts when something goes wrong.
A strategy can perform well for months and then suddenly run into a broker issue, unexpected slippage, an extreme news event, or a market regime that simply doesn’t suit the strategy. The EA doesn’t know that anything is wrong. As long as its entry conditions are met, it will continue trading.
That’s where a kill-switch becomes useful.
Think of it as a circuit breaker for the EA. It watches the account from outside the normal trading logic and stops the EA when predefined risk limits are reached.
The important part is that those limits are decided beforehand, when you’re thinking clearly — not after watching the account fall into a serious drawdown.
Why the Kill-Switch Should Be Separate From the Strategy
It’s easy to add a loss check somewhere inside the strategy code and call it a risk-management feature.
But that’s not really the same thing.
A proper kill-switch should be independent of the strategy’s entry and exit logic. If the strategy has a bug or starts behaving badly in a particular market, you don’t want the mechanism responsible for stopping it to depend on that same logic.
A simple implementation might look like this:
void OnTick()
{
if (KillSwitchActive())
return; // stop all trading logic while the breaker is active
// Normal EA logic
}
The idea is simple: the kill-switch gets checked first. If it’s active, the rest of the trading logic doesn’t get a chance to run.
That separation becomes especially important when the EA is managing multiple strategies, symbols, or different types of trades.
What Should Trigger the Kill-Switch?
There isn’t a single number that works for every EA.
A scalping strategy, a swing strategy, and a grid-based system can have completely different normal drawdown characteristics. Your threshold needs to make sense for the strategy and the account.
It’s also useful to have more than one trigger because different problems can produce different types of losses.
Daily Loss Limit
This is probably the easiest place to start.
The EA records the account equity when the trading session begins and stops trading when the loss reaches a predefined percentage.
double sessionStartEquity;
void OnInit()
{
sessionStartEquity = AccountInfoDouble(ACCOUNT_EQUITY);
}
bool DailyLossLimitHit(double maxLossPercent)
{
double currentEquity = AccountInfoDouble(ACCOUNT_EQUITY);
double lossPercent =
(sessionStartEquity - currentEquity) /
sessionStartEquity * 100.0;
return lossPercent >= maxLossPercent;
}
For example, if the session starts at $10,000 and your daily loss limit is 3%, the EA stops trading once equity falls to the $9,700 area.
The important detail is how the session starting equity is maintained. It shouldn’t simply reset every time the EA is restarted, otherwise a terminal restart could effectively give the EA a fresh daily limit.
Trailing Equity Drawdown
A daily loss limit isn’t enough to catch every problem.
Suppose an EA loses a little today, a little tomorrow, and continues doing the same thing for several weeks. None of those individual days may hit the daily limit, but the account could still end up significantly below its previous high.
That’s where a peak-equity or high-water-mark approach helps.
double peakEquity;
void OnTick()
{
double currentEquity = AccountInfoDouble(ACCOUNT_EQUITY);
peakEquity = MathMax(peakEquity, currentEquity);
double drawdownPercent =
(peakEquity - currentEquity) /
peakEquity * 100.0;
if (drawdownPercent >= MaxDrawdownPercent)
TripKillSwitch("Trailing drawdown limit exceeded");
}
Here, the EA keeps track of the highest equity reached and measures the current drawdown from that level.
This can catch a slow deterioration that a daily reset would miss.
Consecutive Losses
Another useful signal is the number of losing trades in a row.
A string of losses doesn’t automatically mean that an EA is broken. Losing streaks are normal for many strategies. But if the EA normally experiences two or three losses in a row and suddenly starts producing eight, ten, or fifteen, it’s worth having a mechanism that forces a pause.
int consecutiveLosses = 0;
void OnTradeClose(double profit)
{
if (profit < 0)
consecutiveLosses++;
else
consecutiveLosses = 0;
if (consecutiveLosses >= MaxConsecutiveLosses)
TripKillSwitch("Consecutive loss limit exceeded");
}
This is especially useful when combined with an equity-based limit.
A sudden large loss and a slow sequence of small losses are two different problems. A good risk layer should have a way to detect both.
Don’t Keep the Kill-Switch State Only in Memory
This is one of the easiest mistakes to make.
Imagine the EA reaches its drawdown limit, sets a variable like:
bool killSwitch = true;
Everything looks fine.
Then the terminal restarts.
That variable is gone.
The EA starts again with:
bool killSwitch = false;
and trading resumes.
The breaker technically worked, but the restart completely defeated it.
Important state such as the tripped status, peak equity, and loss counters should therefore be persisted.
For example, MQL5 terminal global variables can be used for simple state management:
void TripKillSwitch(string reason)
{
GlobalVariableSet("KillSwitch_Tripped", 1);
GlobalVariableSet("KillSwitch_TripTime", (double)TimeCurrent());
Print("Kill-switch tripped: ", reason);
}
bool KillSwitchActive()
{
if (GlobalVariableCheck("KillSwitch_Tripped"))
return GlobalVariableGet("KillSwitch_Tripped") == 1;
return false;
}
For more complex systems, you may choose to store the state in a file or use another persistence mechanism.
The important point isn’t which storage method you choose. It’s that restarting the EA shouldn’t silently erase the fact that a risk limit was already hit.
What Should Happen After the Kill-Switch Trips?
“Stop trading” sounds straightforward, but there are actually several possible policies.
Block New Trades Only
The EA stops opening new positions but continues managing positions that are already open.
This is probably the least disruptive approach and can make sense when the trigger is simply a daily loss limit.
Block New Trades and Close Existing Positions
This is much more aggressive.
It can make sense when the trigger indicates something more serious, such as a rapid and unexpected equity collapse.
Stop All EA Activity
In a more serious situation, you may want the EA to stop everything, including pending-order management.
This is the most conservative option and is more appropriate when the problem may be related to execution, connectivity, or the trading environment itself.
There isn’t one correct answer here. The action should match the reason for the trigger.
A normal losing day doesn’t necessarily justify closing every open position. A severe and unexpected drawdown might.
Don’t Automatically Turn It Back On
Once the kill-switch trips, it can be tempting to have it automatically reset the next day.
I’d be careful with that.
The whole reason for having a kill-switch is to force a pause when something unusual happens. If the EA automatically resumes without anyone checking what happened, you can end up with the same problem repeating over and over.
A better approach is to require a deliberate manual reset.
For example:
bool KillSwitchActive()
{
if (!GlobalVariableCheck("KillSwitch_Tripped"))
return false;
if (GlobalVariableGet("KillSwitch_Tripped") == 1 && !ManualResetInput)
return true;
return false;
}
The exact implementation can vary, but the principle is useful: once the breaker trips, somebody should have to make a conscious decision to allow trading again.
That gives you a chance to check the trades, broker conditions, market conditions, execution logs, and anything else that might explain the problem.
Test the Kill-Switch Like You Test the Strategy
A risk-control feature shouldn’t be considered finished simply because the code compiles.
You need to test the situation it’s supposed to handle.
One way is to deliberately create a bad test scenario in the Strategy Tester and make sure the EA:
- detects the loss limit;
- stops opening trades at the expected point;
- records the tripped state;
- keeps the state after a restart;
- handles existing positions according to your chosen policy;
- requires the intended manual reset;
- resumes normally only after the reset is completed.
This kind of testing is easy to overlook because nobody wants to intentionally make an EA lose money.
But that’s exactly what makes the test valuable.
A kill-switch is supposed to deal with a situation you hope never happens in live trading. You need to know that it actually works before you depend on it.
The Takeaway
An EA doesn’t know when it’s having a bad day.
It doesn’t know that the market has changed, that execution has suddenly deteriorated, or that its recent losing streak is far outside its normal behavior. It simply follows the rules it was programmed to follow.
That’s why a kill-switch is worth treating as a separate risk-control layer.
A good implementation should have clearly defined triggers, persistent state, a deliberate policy for handling open positions, and a manual reset rather than quietly starting again on its own.
It’s not complicated compared with building the strategy itself, but it can make a big difference when something goes wrong.
If your EA doesn’t have an equity-based circuit breaker, it’s one of the areas we commonly look for during our free EA diagnosis. It’s a relatively small addition compared with the losses it may help prevent.