What a kill switch should actually do (and the four ways they fail)

VigilDesk engineering notes

A kill switch looks like the simplest component in a trading system: one condition, one action, done. In practice it is the component people trust most and test least, and there are four ways it stops being a switch.

1. It is never armed

The switch exists in code and is never wired to the thing it is supposed to stop. The classic version: the guard sets a flag that the order path never reads. The flag is correct, the logs say "blocked", and orders keep going out.

Design note: the switch must sit on the order path, at the last point before submission - not on a parallel path that is supposed to synchronise with it.

2. It is never disarmed

A switch that latches and never clears turns a bad hour into a flat month. If the "blocked" flag is persisted without the date it belongs to, yesterday's decision is applied to today - silently, because a blocked system is indistinguishable from a quiet one.

Design note: persist the state with the day it belongs to, and make the restart path decide: restore, or reset. Silence is not a decision.

3. It triggers on the wrong thing

Two failure shapes, opposite directions:

Design note: distinguish "healthy" from "no data". A guard that cannot read its input must treat that as an incident, not as a zero.

4. It uses the wrong clock

Anything with a daily boundary - a daily loss cap, a per-day trade limit - depends on which day it is, and the host clock is not the broker's clock. When they disagree the boundary moves by hours, and both directions are bad: the cap resets early (the account spends the daily allowance twice inside one broker day) or never (the daily rule quietly becomes a weekly one). This has its own note in this series.

Design note: derive the date from the system that owns the boundary - in MetaTrader 5 that is TimeTradeServer() - and record the drift between the two clocks every cycle.

What separates a switch from a decoration

PropertyWhy it matters
It sits on the order path, lastFlags on parallel paths get out of sync with reality
It persists state with its dateOtherwise it either resets too eagerly or never clears
It writes state after the decisionA crash between write and action lets one order through
It treats "no data" as an incidentZero and unknown must not look the same
It uses the broker's dayThe broker is who decides whether you broke the rule
It says out loud when it firesA silent switch is indistinguishable from a broken one

The test that matters

Not "does the function return the right boolean" - the boundary tests:

Both take ten minutes and both have found real problems in software that had passing test suites, including mine.


Related notes

Get the guard

Free MT5 kill-switch / daily-loss guard, source included, state persisted across restarts: https://xuks124.github.io/vigildesk/free.html

Risk disclosure

Algorithmic trading carries both technical and market risk. No tool eliminates the possibility of loss. Nothing on this page is investment advice, and no performance is implied or promised.