← All posts
Guideriskdesign

The risk caps that kept our paper bot from blowing up

Six concentric circles of protection between “the strategy wants to trade” and “the order hits the broker.” Most of them have triggered at least once.

Alok Desai··8 min read

We've been running a paper bot in production for ~3 months. In that time the bot has avoided every major explosion that hit the market — not because we're geniuses, but because layered risk controls are a much better idea than “trust the strategy.” This post lists every cap that currently sits between “model says trade” and “order goes out.” All but one have triggered at least once; documenting them in case it's useful.

The cap framework

Risk caps in our bot are refusal gates— boolean checks that either let the order through or drop it with a named reason. They're not soft suggestions; a cap that fires means no order goes out, full stop. The bot writes acircuit_breaker audit event so the user sees exactly which gate fired and why.

Soft suggestions become noise; hard refusals become infrastructure. Risk caps should be infrastructure.

Cap 1: Per-symbol position size

No single symbol can exceed X% of equity (default 5% for the “balanced” preset, 2.5% for “conservative”). The cleanest concentration limit and the one that matters most in tail events: if the bot's 100% in NVDA when NVDA gaps down 15% pre-market, you eat a 15% drawdown overnight. With a 5% cap, you eat 0.75%. Diversification is the only free lunch.

Has triggered:yes, every time the strategy gets enthusiastic about a single symbol after a streak. That's working as intended.

Cap 2: Per-asset-class exposure

Crypto exposure can't exceed 25% of gross gross-equity (default). The reason isn't crypto-specific risk; it's that crypto and stocks have different volatilities and correlation regimes, and we don't want a wide-spread crypto move dominating risk on a stocks-leaning bot.

Has triggered:yes, on weekends when markets are closed and the bot rotates entirely into crypto. Without this cap it would've been 100% crypto on Saturdays. With it, the bot deliberately holds dry powder.

Cap 3: Total leverage

Gross long + gross short can't exceed N× equity (default 1.5x for paper, 1.0x for live unless explicitly enabled). This is the “you can't lose 200% of your account” guarantee. Even if every symbol the bot trades implodes simultaneously, leverage caps the worst-case loss at 1.5×100% × largest single-bar move.

Has triggered: rarely on paper; bot is usually under 0.8x in normal regimes. Triggers near 1.4x when the strategy stacks positions during low-vol uptrends.

Cap 4: Daily drawdown halt

If today's P&L is down ≥ 3% (default), no new entries. Existing positions get tightened stops. The bot is not dead — it's in a defensive mode until tomorrow's open.

Why daily and not per-trade? Because the bot might have ten small losers before lunch on a bad regime day. The per-trade stop fires on each, but the cumulative damage crosses 3% before any single stop is wide enough to notice. Daily DD halt catches that pattern explicitly.

Has triggered:3 times in 3 months on paper. Each time the bot was right to halt — the next bar moved further against the sentiment that triggered the halt. We've never regretted the halt; we've regretted not having one tighter.

Cap 5: Weekly + peak DD halts

Two longer-horizon variants. Weekly DD halt at 7% (sum of daily DD over rolling 5 trading days). Peak DD halt at 10% (drawdown from the bot's all-time-high equity). When either fires, the bot stops opening new positions for the rest of the period and emails the user.

Peak DD is the “something is structurally wrong” signal. If the strategy logic is broken or the market has entered a regime the model wasn't trained on, the daily DD halts won't catch it — they reset every day. Peak DD doesn't reset; it stays armed until you manually clear it after diagnosis.

Has triggered: peak DD has not yet, knock on wood. Weekly has triggered once during a multi-day choppy regime where the bot took small losses every day.

Cap 6: Trades-per-day

Maximum 25 trades per day (default for “balanced”). This isn't classical risk; it's a sanity check. If the bot is flipping positions 100x in a day, something's either whipsawing it on regime flicker or the strategy is misconfigured. Cap fires, bot stops, user investigates.

Has triggered: twice during early debugging when the regime confirmation gate was tuned too loose. Both bugs we needed to know about.

Cap 7 (implicit): Duplicate-entry guard

Not labeled as a cap because it's a behavioral rule, but worth mentioning: the bot won't add to a position it already holds. The strategy might say “buy NVDA” on three consecutive bars; the bot buys once, then refuses subsequent buys until the position closes via stop or take-profit.

Why this matters: without it, a flat-then-trending regime produces ladder positions — buy at $100, buy at $102, buy at $104 — that average up your cost basis precisely when the move is most likely to revert. Removing the duplicate- entry guard reduced the bot's sharpe ratio in our backtests by 30%.

What the caps look like together

Daily DD halt
3%
tight
Weekly DD halt
7%
Peak DD halt
10%
loose

The three drawdown halts form a hierarchy: daily catches the bad day, weekly catches the bad week, peak catches the bad regime. Each one is intentionally looser than the next; you don't want all three triggering on the same day.

The lesson we keep relearning

Every time we've loosened a cap because “the bot is leaving money on the table,” we've been right about the money on average and wrong about the tail. The strategy is a finite-sample estimate of what works; the caps are the protection against the cases where the estimate is wrong.

Tighten before launch. Loosen only when you have months of clean data telling you the cap is the binding constraint on returns AND that the historical distribution of bad days will resemble the future distribution. The second condition is the hard one; lots of strategies have looked great until 2020 March or 2022 May or 2025 November.

Risk caps are unsexy. They're the part of a trading bot that nobody markets. They're also the only reason any of us are still trading.

Try the bot

Run a paper bot in 5 minutes. Free tier, your laptop, no card required.

Start free →