Skip to content

Circuit breakers & the operator contract

ExpertDuration 35 minTools Python 3, A trade/equity log, A text editor for your contract

A strategy optimises for profit. A circuit breaker optimises for survival, and when the two disagree, survival must win. This is the layer that outranks everything — entries, exits, sizing, even your own conviction in the moment. It exists because the two ways retail accounts die catastrophically are (1) a tail event the strategy never imagined, and (2) a human overriding the system mid-drawdown and destroying the very attribution that would have told them whether to. This lesson builds the hard limits and the written contract that make both failures harder.

Almost no free video teaches this directly — so the lesson leads with the explainer. Two short segments give you the real-world texture:

Segment: 38:39–45:18 — discretionary overrideswatch full video

Watch for: A professional being honest about the rare cases where overriding a system is defensible — and how easily that becomes an excuse. This is exactly the boundary the operator contract has to draw.

Segment: 0:00–19:11 — rollover mechanics + circuit-breaker debatewatch full video

Watch for: The Q&A on whether a broker should HALT trading during the rollover spread spike so stops aren't hit on an artificial price — a live instance of anomaly-halt thinking. (The clip stops before the off-topic company chat.)

Circuit breakers are the top of the hierarchy. Everything else in your system answers “should I trade this signal?” A circuit breaker answers a higher question: “should the system be trading at all right now?” When a breaker trips, it does not negotiate with the strategy — it halts. Three belong in every retail system.

Max daily loss. Pick a number — say 3% of equity, or a fixed dollar figure — measured from the session’s starting balance. When realised-plus-open loss reaches it, the breaker closes exposure (or blocks new entries) and locks until the next session. The lock matters: without it, a bot that just lost its daily budget will happily “make it back,” which is how a bad afternoon becomes a blown account. The state is not “am I down?” — it is “am I locked until the session rolls?”

Exposure caps. A hard ceiling on total risk on at once: max simultaneous positions, max risk per instrument, max aggregate risk across correlated instruments. Caps stop a cascade of individually-reasonable signals from adding up to a position that a single gap can end. They are calendar- and correlation-aware ceilings, not per-trade sizing (that was Level 2).

Anomaly halts. Some market states are simply outside the distribution your strategy was validated on, and the honest response is to stop, not to trade louder. The cleanest trigger is spread: if the current spread is more than, say, three times the session-normal spread, halt — you are almost certainly looking at a rollover spike, a news dislocation, or thin liquidity where your fills will be terrible (spreads widen 10–20+ pips at the daily rollover). Other anomaly triggers: a price gap beyond N times normal, or a data feed that has gone stale.

Why breakers, and not just good stops? Because stops fail exactly when you need them most. On 15 January 2015 the Swiss National Bank abandoned its EUR/CHF floor and the pair gapped roughly 40% in minutes, straight through every resting stop. FXCM was left with about $225M of negative client balances — clients who owed more than their deposits — and Alpari UK went bankrupt. A software stop, or even a broker-side stop, is a price you hope to exit at; in a 40% gap there is no liquidity at that price. Kevin Davey’s Swiss franc walkthrough shows a $21,000-per-contract hour that no resting order could have escaped. Circuit breakers do not prevent the tail — nothing does — but exposure caps and anomaly halts shrink how much of your account is exposed when it arrives.

The operator contract. Here is the discipline that ties it together. Before your first live trade, you write a one-page contract — for yourself — that states: the strategy trades on its rules; the breakers outrank the strategy; and you do not manually intervene. The reason is behavioural, and it is the whole reason systematic trading exists: humans under P&L stress deviate from their own plans, and the classic failure mode is overriding the system mid-drawdown, which destroys attribution — now you can never tell whether the system or your meddling produced the result.

The contract does not pretend you will never override. It does something smarter: any override is logged as its own strategy. Timestamp it, record the reason, record what the system would have done, and evaluate your discretionary calls later as a track record of their own. If your overrides make money over time, you have discovered a real discretionary edge worth systematising. If they lose — as they usually do — you have the evidence to stop. Either way, attribution survives. The contract turns “I couldn’t help myself” from a hole in your data into a logged, measurable experiment. Davey makes the same move with pre-written quitting criteria: decide, in writing and while calm, what would make you stop — because in-the-moment decisions under drawdown are not to be trusted.

Part 1 — build the daily-loss breaker. It locks until the next session, so a lost budget cannot be “won back” today.

from datetime import date
class DailyLossBreaker:
"""Halts trading once the session loss limit is hit; stays locked until the next session."""
def __init__(self, start_equity: float, max_daily_loss_pct: float = 0.03):
self.session = date.today()
self.session_start_equity = start_equity
self.max_loss = start_equity * max_daily_loss_pct
self.locked = False
def _roll_session_if_new_day(self, equity: float):
today = date.today()
if today != self.session: # new session -> reset and unlock
self.session = today
self.session_start_equity = equity
self.max_loss = equity * (self.max_loss / self.session_start_equity) if self.session_start_equity else self.max_loss
self.locked = False
def can_trade(self, equity: float) -> bool:
"""Call before every new entry. Returns False once the breaker has tripped."""
self._roll_session_if_new_day(equity)
drawdown = self.session_start_equity - equity # realised + open loss vs session start
if drawdown >= self.max_loss:
if not self.locked:
print(f"BREAKER TRIPPED: session loss {drawdown:.2f} >= limit {self.max_loss:.2f} - locked until next session")
self.locked = True
return not self.locked
# smoke test
b = DailyLossBreaker(start_equity=10_000, max_daily_loss_pct=0.03) # $300 budget
print(b.can_trade(9_900)) # True (down $100)
print(b.can_trade(9_650)) # False (down $350 -> tripped, locked)
print(b.can_trade(9_950)) # False (still locked even though we "recovered")

Part 2 — write your operator contract. One page, in plain language, before any live trade. Fill in the blanks and commit it to your repo:

# Operator Contract — <strategy name>, drafted <date>
1. HARD LIMITS (outrank the strategy; tripping any one halts trading)
- Max daily loss: ____% of session-start equity, locked until next session.
- Max simultaneous positions: ____. Max risk per instrument: ____%.
- Max aggregate risk across correlated instruments: ____%.
- Anomaly halt: no new entries while spread > ____x session-normal.
2. THE RULE: I do not manually intervene in the system's decisions.
3. THE EXCEPTION, GOVERNED: If I override, I log it immediately as its own
strategy — timestamp, reason, and what the system would have done — and I
review my overrides as a separate track record every ____ weeks.
4. KILL CRITERIA (written cold, see Lesson 3.5): I stop the strategy if ____.
Signed (to myself): ____________

Check yourself

  1. A circuit breaker in a trading system is…

  2. Why must the operator contract be written BEFORE the first live trade?

  3. In this course's operator contract, a manual override of the system is treated as…

  4. What made the January 2015 Swiss franc event so instructive for circuit-breaker design?

You can move on when you can… implement a daily-loss breaker that locks until the next session, name the three breaker types (max daily loss, exposure caps, anomaly halts) and why they outrank the strategy, cite the 2015 SNB event as the reason a resting stop is not tail protection, and write a one-page operator contract that turns any override into its own logged strategy.

  • Kevin Davey, Building Winning Algorithmic Trading Systems — quitting/kill criteria as a formal, written-in-advance stage.
  • LeapRate’s account of the 2015 SNB flash crash and CNBC on FXCM’s insolvency — the tail event that justifies exposure caps.
  • Robert Carver, Systematic Trading, Part One — the behavioural case for committing to rules and not meddling under stress.