← Research log

We killed our trading bot

On 12 September 2026 we turned off the intraday lane of our own trading bot. It had been running since June, it looked like it was working, and it had no edge at all. This is the whole thing, including the numbers that flattered us for two months.

The thesis

The idea was ordinary enough. Our early strategy used a tight 0.35% stop-loss, and it was losing: a 33% win rate and negative expectancy. The suspicion was that the stop itself was the problem — that it kept selling dips moments before they recovered, converting temporary drawdowns into permanent losses.

So in July we widened it to 1.5%, then to 2.0%. In August we removed it entirely and let positions run to a 3% take-profit or a 48-hour time-stop. Each change was justified by a counterfactual replay: re-simulate every historical entry forward under stop widths from 0.35% to none, hold the exits constant, and compare.

The replay was unambiguous. No-stop won, and it kept winning as we added data.

What the numbers said while it ran

MeasureNo-stop era
Replay expectancy+0.709% per trade
Profit factor1.83
SQN2.37
Live, 28 days+0.581% per trade over 59 trades

Those are good numbers. They are also, in hindsight, almost meaningless — because every one of them was computed on the same 2026 data the rules had been tuned on, in a market that spent the period going up.

The test that ended it

We had cached 15-minute bars for our ten symbols going back to January 2022. In September we finally ran the frozen rules over all of it: 4.7 years, no parameter fitting, entry slippage charged at the median we had measured on real fills.

Then we ran the control that matters. Same cadence, same four position slots, same exits, same entry rate — but entries drawn at random. A long-only strategy in a rising market earns from exposure alone, so the only question worth asking is whether the signal beats a coin flip with identical mechanics.

Expectancy per trade
Our entry rule+0.084
Random entries, same slots and exits+0.127

The rule was worse than random. When we re-ran it later with 40 seeded control runs, our rule landed on the 50th percentile — z = 0.02. Not marginally better, not marginally worse. Exactly average.

And against doing nothing at all

Expectancy above zero is a low bar when the underlying stocks tripled. So we ran the benchmark we should have run first: equal-weight the ten symbols on day one and never trade again.

Approach$1,000 over 4.47 years
Buy and hold$2,653
Our strategy$1,492

2,221 trades, a 32.9% drawdown, and $1,161 destroyed against sitting still.

Three attempts to rescue it

Before retiring it we tried to find the conditions under which it did work. All three failed:

That last one is the diagnosis. The strategy was a tax on holding: it sold every winner at +3% in a market that tripled, while letting the losers run to their time-stop.

What we would do differently

Run the out-of-sample test and the random-entry control first, before a single live trade. We had the historical bars the whole time. We spent two months and 2,221 simulated trades learning something a four-minute backtest would have told us in June.

The forward-running lane produced roughly 0.6 entries a day. A 30-trade verdict took weeks. The backwards test produced 2,526 trades in minutes and could see the 2022 drawdown, which no amount of waiting in 2026 would have given us.