Page 1 of 1

Kill-switch script: my daily loss cap enforced by code instead of willpower

Posted: Wed Sep 30, 2026 9:46 pm
by Fairman
I've written about daily loss limits before, and I follow mine most of the time. "Most of the time" is why I wrote a small kill-switch script. It watches my realized and open P&L through the broker API. When the combined figure hits my daily limit, it cancels every working order, flattens every position, and stops sending anything else for the rest of the day.

## Rails
- The limit is set in dollars in a config file the night before. The script only reads that file at startup, so I can't loosen it mid-session.
- It polls positions and P&L every few seconds. If the API call fails three times in a row, that counts as a trigger too, and the script tries to flatten through the backup route and alerts me.
- It triggers at the limit on realized plus open P&L, not realized alone, so a large open loser can't hide.
- Once it has triggered, the order-sending part of my own tools refuses to start until the next session date.

## Worked example (illustrative)
Daily limit: $150. At 09:58 ET I'm down $95 realized after two stops. At 10:14 ET I'm long 300 of a $33 name from 33.40, and it drops to 33.22. Open P&L is −$54, and combined with the realized loss that's −$149. At 33.21 it's −$152.

The script fires at 10:15:03 ET. It cancels the working stop and target, sends a market sell for 300, and gets a fill at 33.20. Final day: roughly −$155 after a few cents of slip. It writes "KILL 10:15:03 combined −152" to the log, and my order tool shows "LOCKED until next session."

I was annoyed at 10:15, and by the next morning I was grateful.

## Failure modes
- Keeping an override flag "for emergencies." If it exists, I'll use it.
- Counting only realized P&L.
- Assuming the polling loop is running without a heartbeat. Mine writes a line every minute, and a missing line is itself an alert.

## When to skip
- If the kill-switch isn't running at 09:25 ET, I don't trade. It isn't optional.
- If I'm trading on a device where the script can't reach the API, like a phone while travelling, I trade a fixed tiny size or not at all.
- After any code change to the script, it runs on paper for a full session before going live.

Diagram: a flow from "poll P&L" to "realized + open <= −limit?" with a YES branch to cancel all, flatten, and lock, and a heartbeat box on the side.