An autonomous options-trading agent that forms a falsifiable view, prices several ways to express it, sizes by a track record it has to earn, and afterwards scores whether its view was right, its structure was right — or it simply got lucky. Only the first two ever move its confidence.
trdrbot · built on Alpaca's MCP server · $100,000 paper account

Most trading agents score themselves on P&L. We measured what that actually buys you over a hackathon-length window — and it is close to nothing.
of the time a genuinely skilled agent with a 60% edge out-scores a coin flip over 20 trades. Barely better than a coin flip about the coin flip.
the range a zero-skill agent lands in over the same window. Any result in that band proves nothing at all.
roughly the chance a coin flip beats real skill. So a leaderboard over one week ranks variance, not ability.
Worse: an agent that learns from P&L alone reinforces whatever story happened to correlate with money. That is how a system acquires a superstition.

Was the view right? and was the way I expressed it right?
Only one cell is unambiguous — held and profit, top left, genuinely earned. The two amber cells are still useful: a loss is informative whichever way it points, so both feed learning. The red cell is the trap: a profit on a failed thesis. P&L-based scoring treats that as strong confirmation. Here it teaches nothing, and it is excluded from what lets Theo size up.
Every falsifiable claim is pre-registered before it resolves — traded or not. When it resolves, attribution asks which of the four boxes it lands in.
Four stores with four different jobs. Blocks that informed a decision are credited or decayed by that decision's verdict — never by its P&L.
Demonstrated calibration raises the Kelly fraction the agent is allowed. Experience → reliability → larger size. No step rewards mere confidence.
And the deterministic half. The model never executes anything. Code wakes the agent, code runs the gauntlets, code computes Kelly, and code fires the exit rules — every 60 seconds, without asking. The LLM's job is narrow: form a view and propose ways to express it. Everything downstream of that is arithmetic that cannot be talked round.
Look at the world. Prices, positions, news, odds, technicals.
every 60s · no LLM
Form a falsifiable view; price at least two ways to express it.
~15 min · LLM + arithmetic
Place the multi-leg order, then verify it against broker truth.
Alpaca MCP
Guard the position deterministically; then judge it honestly.
every 60s · no LLM
Route what was learned to the store shaped to hold it.
four stores
Refreshes account and position state from the broker, pulls news and prediction-market odds, and computes technicals, realised volatility, beta and a bootstrap forecast from each name's own return history.
analytics | account, positions, quotes, book greeks |
sensors | news + Polymarket odds into one inbox |
market_stats | technicals, realised vol, beta, bootstrap |
reconcile | our record vs the broker's truth |
Measured live: SPY and QQQ correlate at 0.92 — so the research universe was rebuilt for low mutual correlation, not familiarity.
Daily, top-down. Technicals + news + prediction-market odds → a regime page and company dossiers → falsifiable opportunities.
Bottom-up. The news nominates the companies. Every nominee must clear a deterministic gauntlet — technicals, forecast, fundamentals, options liquidity — before an LLM writes anything up.
Creative collision. Random concepts × news × odds, argued into domino chains, every candidate pre-registered and adversarially gated. The top two graduate.
simulate_experiments prices every candidate under one declared
measure — the thesis's own drift and vol, with the market's pricing beside itsize_position computes Kelly from the conditional
payoff and shrinks the claim by measured calibrationSubmits a genuine multi-leg options order through Alpaca's MCP server, stamps it with an idempotent client order id, then reconciles every leg against what the broker actually filled.
max_loss_usd; if that number came from a model and never met a
fill, every later cap is denominated in fiction.| class | mleg — 2-leg vertical, one ticket |
| legs | SPY260903P00766000 buy_to_openSPY260903P00758000 sell_to_open |
| type | limit, net debit $1.70, day |
| id | theo-spy-bps-20260828-766758 |
Every position traces back to its reasoning through one
position_id — journal, wiki, memory, and back to the broker.
Exit rules are the agent's own commitments, executed deterministically. One signal registry: every rule reads a signal, compares to a threshold, debounces. Thesis-level stops watch the underlying, not the noisy option mark.
An exit rule stated only in prose does not exist. Percentages mean what a trader means — a percent of the net debit paid, not of gross premium. On the wrong base, three of the four mark-based rules this book has ever carried could not fire at all.
Attribution waits for the horizon the claim named, then asks the two questions from slide 3. A profit on a wrong view is recorded as luck and teaches nothing.
Calibration then scores every stated probability with a Brier score and its Murphy decomposition — reliability (am I overconfident?) separated from resolution (do my forecasts actually separate winners from losers?).
Attribution is the distinctive signal, and it is deliberately expensive to earn: promotion past the second rung requires that most resolved theses were actually explicable. A book of luck is not competence, however good the P&L looks.
Append-only events. What happened, when, and which model said so. The record, never rewritten.
1,239 rows
Stable reference that rewrites itself: position pages, company dossiers, the regime page.
markdown on disk
Evolving memory with decay and reinforcement — and a ratified constitution of epistemic principles.
credited by verdict, not P&L
Every falsifiable claim ever made, traded or not — so the trial count a multiple-testing correction needs cannot be lost.
48 resolved
The ledger is the quiet one that matters most. Forecasts on setups we declined are scored too, at zero capital risk — and they are the only realistic route to a calibration sample that means anything inside a week.
Chassis: one scheduler, a singleton lock, an ordered model fallback chain, and a health probe that asks every subsystem “you ran — but did you produce anything?”
Roughly 15,700 lines of Python · 535 offline tests · four trader-readable simulation scaffolds
Alpaca's MCP server runs as a local stdio subprocess. The adapter's default starts a fresh process per tool call — six calls cost 12.3s. Sharing one session across the tick cut it to 2.75s.
−78% wall clock, measured
Verticals, condors and butterflies go as mleg tickets with
per-leg position_intent. Calendars and diagonals are refused,
not approximated — pricing the far leg needs a model we deliberately do not have.
a confident wrong payoff is worse than a refusal
Binding all 72 MCP tools cost ~21k tokens of schema per call, 71% of it for tools never used once — and a bigger menu measurably worsens tool selection.
$3.46 → $1.32 per decide cycle
The lesson that generalises. All three of those had already shipped as
code that ran and did nothing: the option-chain compactor failed open against an envelope
shape it did not recognise, the session was never actually shared, and the prompt cache was
never asked for. Each looked healthy in the logs. That is why
trdrbot health exists and asks a different question from the tests —
“you ran, but did you produce anything?”
Fed funds futures flipped intraday to price a September hike as more likely than a hold. Gold, Bitcoin and TLT all sold off. SPY did not — it had printed 775.30 before the remarks and sat at 769.07, down 0.3%, after a +5.7% run.
That asymmetry is the trade. Not a chart shape — a dated, causal claim that one market had repriced and another had not.
“SPY drifts modestly lower into 2026-09-03 as equities digest fed funds futures repricing.”
horizon 2026-09-03 · falsifiable · pre-registered before any order
| 1 | get_stock_snapshot |
| 2 | get_stock_bars |
| 3 | get_clock |
| 4 | get_news |
| 5 | get_option_chain |
| 6 | simulate_experiments |
| 7 | size_position |
| 8 | place_option_order |
| 9 | record_position |
| Candidate | Win rate | Pays | Risks | Verdict |
|---|---|---|---|---|
| 775/780 call credit spread | 76–92% | $95 | $283 | rejected looks safe because it usually wins |
| 760 butterfly | low | — | $70 debit | rejected needs the fall to stop exactly at 760; $22 of 4-leg friction |
| 766/758 put debit spread | 42% | 2.85 : 1 | $2,171 | taken EV-positive even at the market's own drift |
“Honest confidence 0.42. This loses more often than it wins. That is fine — it is the same trade logic as a 38% call spread with 3.8:1 payoff. I resisted rounding up to make it feel better; the number is scored.”
Theo's own decision record, 28 August| profit target | +140% of debit |
| stop | −65% of debit |
| underlying stop | SPY above 776 |
| time stop | expiry day |
| leg divergence | broker truth vs ours |
The agent named the underlying stop as the one it trusts most: if SPY makes new highs, the premise that equities haven't discounted the hike is simply false, and the position should die regardless of what the mark says.
+19.6%
on net debit at last mark. But the P&L is not the question that moves anything.
a profit with a wrong view scores as luck and moves nothing
nothing — the starting allocation
≥5 resolved theses
≥15 resolved, ≥60% attributable
≥40 resolved, ≥70% attributable, reliability <0.04
Colour deepens with earned trust — MATURE's tint is the same green this deck uses for a genuinely earned outcome, nowhere else. Climbing costs evidence, not confidence: each rung names exactly what must be demonstrated, and none of them can be talked round.
Attribution is a promotion criterion, not a metric. This is the rung that makes “right vs lucky” cost something real.
Kelly refuses any structure with unbounded LOSS outright. Unbounded profit is fine — a long call is not a naked short.
SPY's own resampled returns, fair-priced structure, the production sizer. Full explorer →
median gain when the view is right, against the loss when it is wrong
—
from a $100,000 start
peak $102,432 · max drawdown 0.7%
2 closed at +8.2% and +52.8% on debit; 1 open at +19.6%
82 ended in a deliberate no-op
Three positions over five days is not evidence of skill, and we can prove it rather than merely say it. That is exactly the range in which a zero-skill agent lands somewhere between −7.8% and +8.2%. We report the number plainly because it is real — and we built the calibration and attribution machinery precisely so there is something better than this number to judge us on.
| Measure | Value | Reading |
|---|---|---|
| resolved forecasts | 48 | 12.4 effective — concentrated in a few names |
| Brier score | 0.225 | 0.25 is a coin flip |
| reliability | 0.000 | well calibrated not overconfident |
| resolution | 0.000 | no discrimination forecasts are not separating winners from losers |
Theo says 40% and it happens about 40% of the time — honest. But it has not yet shown that its 60%s come in more often than its 30%s — not yet skilful. Those are different claims, and only a decomposed score can tell them apart.
The size ladder already reflects this. Theo is still on the second rung of four. It has not promoted itself on a good week, because the criterion is attribution, not profit. The system that would let us hide this is the same system that found it.
Every threshold that matters needs ~50 resolved forecasts. The record is young and the ladder correctly says so.
Pricing the far leg needs a model we deliberately do not have. A confident wrong payoff is worse than a refusal.
Per-leg IVs set the greeks and the vega-weighted vol, with the EV span across legs printed beside it — but a smile-consistent terminal distribution is refused for the same reason.
No thesis was recorded at entry. Fabricating one retroactively would be worse than the gap.
12 theses simulated, 1 traded. A decline that was right about vol and one that was right about direction are currently indistinguishable. Logged as an open issue.
Paper account, and gates block the feedback loop. What replaces it is stricter: the agent cannot execute a mistake the arithmetic refuses to compute.
A living bug ledger records every defect the moment it is found and removes it only in the commit that fixes it. 69 numbered issues so far.

The distinctive thing here is not the strategy. It is that every claim is written down before it resolves, scored afterwards on whether the reasoning held, and allowed to change how much capital the next decision gets — with a lucky win worth exactly nothing.
| Repo | github.com/…/trdrbot |
| Deep dive | the risk research note · the interactive explorer |
| Account | Alpaca paper · $100,000 start |