NineFifteenAM

Mistakes that cost me

I switched a strategy to paper. Thirty-three seconds later it traded real money.

4 min readBy NineFifteenAM

A live-routing bug in my trading bot let a rule outrank my manual paper switch. It cost ₹15,947, and fixing it exposed a second bug that could have sold a paper position on the real broker.

Short answer

My bot routes each trade to paper or live using written rules. When I switched one strategy to paper from the dashboard, a matching rule still sent its next trade to the live broker, because the code checked the rule before it checked my switch. The trade lost ₹15,947. The fix makes a manual switch to paper outrank every rule.

On 10 August, at 10:14:27, I switched one of my strategies from live to paper in the dashboard. At 10:15:00 it entered a real trade anyway. That trade lost ₹15,947.

Nothing crashed. No error was logged. The dashboard showed the strategy as paper the whole time. This post is about how that happened, and the second, worse bug I found while fixing it.

How the bot decides between paper and live

Every strategy has a mode — live or paper — that I can flip from the dashboard. On top of that sits a live gate: a set of written rules, per strategy, that describe which trades are allowed to go to the broker. For example, a rule might allow a strategy to trade live only on one side of the market, and send everything else to paper.

The routing code sits in one small wrapper around two engines, one live and one paper. For each entry, it asks the gate for a decision and picks an engine.

The intent was clear in my head: the gate is an allowlist that narrows a live strategy. It can take trades away from live. It should never add them.

What actually happened

When I flipped the strategy to paper, the code re-pointed its fallback engine to paper. But the fallback was only used when the gate returned "no rule applies". This strategy had a rule, and the next signal matched it. The gate returned "live, gated", the wrapper took the gated branch straight to the live engine, and my switch was never read.

In other words, the gate was behaving as a grant that could promote a paper strategy back to live. Thirty-three seconds after I papered it, the rule did exactly that.

The second bug: a paper exit on the real broker

While reviewing the fix I found something worse.

The wrapper remembers which engine it used for the last entry, and routes exits through that same engine. When the bot starts up, that memory is seeded with the live engine. So consider a restart while a strategy holds an open paper position: if the exit fires before any new entry, the wrapper closes it through the live engine. That is a real sell order for a position that only ever existed on paper — and on a real account, selling something you don't hold opens a short.

It had been harmless while the wrapper only wrapped live strategies. It became reachable the day I started wrapping paper-by-default strategies too. No trade was affected, but only because I found it in review.

A related near-miss in the same file: an earlier idea was to shrink trade size for strategies "on probation" by scaling the buy quantity inside the wrapper. But exits take their quantity from the strategy, which would still believe it held full size. The exit would have sold more than was bought. I moved that sizing into the strategy itself, so buy, sell and logging all agree by construction.

The fix

Three changes, each small:

  1. A manual switch to paper outranks everything. It is checked first, before the gate, before the allocator, before any rule. No rule, however specific, can route a manually-papered strategy to live.
  2. The paper choice is recorded, not just returned. When the switch forces paper, the wrapper also updates its memory of the active engine, so the matching exit closes on paper too.
  3. Exits fall back safely after a restart. Until the wrapper has made a routing decision in this session, exits use the strategy's configured default rather than whatever the engine was seeded with.

Each one is pinned by a regression test named after the date of the incident. The test sets the manual switch, feeds a trade that matches a live rule, and asserts it goes to paper.

The rules I follow now

If you run a bot with both paper and live modes, try this today: switch a live strategy to paper, then force a signal that matches one of its live rules, and watch where the order goes. It takes five minutes, and it is cheaper than ₹15,947.

Questions people ask me

How do I make sure my trading bot's paper mode really stops live orders?

Make the manual paper switch the highest-precedence input in your routing code, above every rule and allocator decision, and pin it with a regression test that sets the switch, feeds in a trade that matches a live rule, and asserts it goes to paper.

Can a paper trade's exit be sent to a real broker by mistake?

Yes, if the exit is routed by the strategy's current mode rather than by where the entry actually went. The exit must close through the same engine that opened the position. Restarts are the risky moment, because in-memory routing state resets to a default.

What does fail closed mean for a trading bot?

When the system cannot decide safely — a rule references missing data, a config file is unreadable — it routes to paper or refuses the trade, rather than defaulting to live. Losing a trade is cheaper than taking one you did not intend.

live tradingpaper tradingriskbugsorder routing
N

NineFifteenAM

One trader building an options bot for Indian index markets since early 2026. I write down how it is built, what broke, and what it cost — no tips, no calls, no returns.

Related

25 Sept 2026
Seven bugs in my trading bot that never threw an errorA strategy that could never trade, an order that was silently never placed, a data feed that recorded zero rows for a session. The quiet failures from six months of running a trading bot, and the checks that catch them.
Mistakes that cost me
23 Sept 2026
Six months building an options trading bot: what the log actually showsFrom one opening-range strategy to 157 strategies, 390+ commits and 10,500 logged trades — the real timeline of building a trading bot for Indian index options, including the week I multiplied my size by 27.
The journey
26 Sept 2026
Why my backtest lied: six gaps between testing and live tradingUnrealistic fills, tick-level trailing stops, the wrong bar timeframe, expiry-day strikes and candle-close entries — the specific ways my trading bot's backtests disagreed with live trading, and the replay engine I built to close the gap.
The journey