Case study
shadow mode, 0 live trades, by design
FORTUNA
An autonomous prediction-market trading platform that forms its own calibrated probabilities and runs every decision through layered GO/NO-GO gates. 3,400+ trade decisions evaluated in shadow mode.
- shadow-mode trade intents evaluated
- 3,400+
- regulatory-inspired invariants enforced in code
- 7
- independent systems, none grades its own output
- 3
- calibrated-probability pipeline, every fetch logged and hashed
- 5-stage
FORTUNA is an autonomous platform that reads prediction markets on Kalshi, forms its own calibrated probabilities, and decides what to trade. I built it in Python and Rust on Postgres, with the Anthropic API driving the reasoning. It has never placed a live order, and that is the point: I wanted to prove the machine's judgment was sound before any real money touched it.
The hardest part was resisting the temptation to let one program do everything. A single agent that gathers data, forms a belief, grades that belief, and then trades on it has no way to catch its own mistakes, because the same blind spot runs through every step. So I split the system into three parts with hard seams between them. Alexandria is the data witness, a decoupled research platform with bitemporal storage that can reconstruct exactly what was known at any past moment. Pythia forms beliefs through a five-stage pipeline: base-rate priors, triage, an evidence-gathering analyst, judgment resampling, and mechanical verification. FORTUNA does the judging and execution. The rule I enforced in code is that no system grades its own output, backed by seven regulatory-inspired invariants and an append-only belief ledger.
The thing I got wrong early was the gate. My first instinct was to promote the system up the capital ramp, from shadow to paper to live, when it made money in simulation. That rewards luck. A model can be badly calibrated and still win a run by accident, and I would have been trusting noise. I tore that out and rebuilt the ramp to gate on process metrics instead: closing-line value, Brier score, and CRPS, measured over the full population of intents rather than the wins. Under those gates a version that looked profitable on paper failed on calibration, which is exactly the failure I wanted to catch on the ground instead of with real capital.
What shipped is the whole loop running unattended in shadow mode, with every belief traceable to the fetches that formed it, each logged with its URL, timestamp, and content hash so no decision can quietly reference data it should not have had. I operate it through ROTA, a console I built for watching the gates. Current status is honest and deliberate: shadow mode, zero live trades, capital ramp still gated on the process metrics rather than on any realized profit.


