Here’s a question I’ve been wrestling with for weeks: how do you know your AI traders actually learned something?
Not “did the code deploy” — I can check that with git. Not “did they make money” — paper trading returns are noise in the short term. The real question is harder. If I tell my trading agents to be less impulsive, and the next day they trade less impulsively, did they learn? Or did the market just give them an easy day?
I’ve been building autonomous trading agents for a while now — Kairos, Stonks, Aldridge — and if you’ve been following along, you know they have a whole learning loop that’s supposed to make them better over time. Parameter tuning, weekly prompt synthesis, code changes overnight. The works.
But here’s the thing nobody tells you about building self-improving systems: you can’t prove improvement without a time machine.
The Control Group Problem#
In science, if you want to know whether a drug works, you give the drug to one group and a placebo to another. Same conditions, same timing, same everything — except the variable you’re testing.
In trading, this is almost impossible. Markets never repeat themselves. Monday’s market is different from Tuesday’s. A trading decision that was brilliant in June might be disastrous in July, but not because your agent got worse — because the context shifted.
So when my agent makes better trades after a learning update, I can’t say “the learning worked.” I can only say “the agent did better in a different market.” Those are not the same thing.
What I needed was a way to run the same market against two versions of the same agent: the “before” version and the “after” version. A historical replay harness — a controlled experiment for AI traders.
What It Does#
Imagine you’re a sports coach reviewing game tape. You watch the game, pause at key moments, ask yourself: what should the player have done here? Then you go back, watch again, and see if the player makes a different decision now that they’ve learned from the tape.
That’s exactly what the historical replay harness does for my trading agents:
graph LR
DB[(Historical<br/>Market Data)] --> RP[Replay Pipeline]
RP --> QC[Quality Gate]
QC --> |Pass| CT[Controlled Test]
CT --> AG[Agent v1 → Decisions]
CT --> AG2[Agent v2 → Decisions]
AG --> COMP{Compare}
AG2 --> COMP
COMP --> RES[Learning<br/>Measurement]
style DB fill:#2d3748,color:#fff
style RP fill:#4a6cf7,color:#fff
style QC fill:#ecc94b,color:#000
style CT fill:#4a6cf7,color:#fff
style AG fill:#805ad5,color:#fff
style AG2 fill:#38a169,color:#fff
style COMP fill:#e53e3e,color:#fff
style RES fill:#dd6b20,color:#fffYou take a slice of real market history — let’s say a week of trading data from June — and feed it to the agent exactly as it happened. Tick by tick, price by price. The agent makes decisions, records them, and you see the results.
Then you take the same week of data and feed it to the updated agent. Same market conditions, same timing, same price movements. The only difference is what the agent has learned in between.
That’s the time machine. And it took a while to get it right.
The Quality Gate Problem#
The first version of the harness was straightforward: pull historical data from our data sources (Finnhub, Alpaca), replay it, compare the results. Simple, right?
Not quite. The quality gate — a check that ensures the historical data is complete and accurate enough to use — started rejecting data immediately. Sweep scores (a quality metric we use to measure data completeness) were coming back at -1.500, which is basically the data equivalent of “this is garbage.”
Why? Because the data sources we rely on don’t have the same coverage for past dates as they do for today. A stock that trades actively right now might have had zero volume on a specific historical date. The data was technically there, but it wasn’t useful.
So the nightly backtesting pipeline would run dutifully, find nothing worth testing, and report back: “0 trades due to quality gate.” The pipeline code worked. The data didn’t.
This is one of those problems that sounds boring but is actually fascinating: your system can be perfectly engineered and still produce nothing useful because the inputs aren’t good enough. It’s like having a race car that’s mechanically flawless but only has access to muddy dirt roads. The car isn’t the bottleneck — the road is.
The Integration Test That Made It Real#
The turning point came when we needed integration tests for the harness. PR #204 was specifically about making the historical replay harness testable in CI — no real data, no external APIs, just deterministic tests that prove the replay logic works.
This is where the system crossed from “experiment” to “infrastructure.” Once you have tests for something, it’s real. It exists. It has to keep working.
The integration tests check things like:
- Can the harness correctly replay a known sequence of ticks?
- Does it handle gaps in data gracefully?
- Does the quality gate reject bad data and accept good data?
- Do two replay runs with the same data produce the same results? (Reproducibility is the whole point.)
These are boring questions with exciting answers. Because once you know the replay is faithful, you can start asking the interesting questions: did the agent actually get better?
What’d I Learn?#
Building the historical replay harness taught me something about learning itself. Here it is:
You don’t know if you’ve learned until you face the same test twice.
That sounds obvious when I write it down, but it’s easy to forget. We had all this machinery for making the agents better — parameter optimizers, prompt synthesis, weekly retrospectives — but no way to measure whether any of it worked under controlled conditions. We were optimizing without verification.
The replay harness isn’t just a testing tool. It’s an honesty mechanism. It prevents me from believing the system is improving when it’s just drifting. It replaces “feels like it’s working” with “here’s the before-and-after on the exact same data.”
I’m still collecting data. The quality gate issue means I need better historical data before I can run meaningful comparisons. But the infrastructure is there. The time machine exists.
Now I just need to fill it with good data.
What’s Next#
The next step is running actual replay comparisons — take a version of Kairos from last week, run it against this week’s version on the same historical market data, and measure the difference. If the numbers say “yes, the agent makes better decisions now,” that’s proof the learning loop is working. If they don’t, that’s also useful — it means the loop needs fixing.
Either way, I’ll know. And that’s the whole point.
If you want the gory technical details — the test architecture, the quality gate implementation, the replay algorithm — I’ll be posting a technical deep dive once we have some actual comparison data. For now, the tl;dr is: building a time machine for trading bots is harder than it sounds, but it’s the only way to know if you’re actually getting better.