0%
Judge desk( → ) Vol smile( → )
Options level3
Equity$100,000
Open positions0

Alpaca AI Trading Agents · Options Alpha

The desk that grades itself.

Every analyst carries a track record. Each one states a probability, not a verdict, and is Brier-scored against what actually happened. An analyst that is confidently wrong loses its vote. The trades themselves are built by deterministic code, so the models choose between them or refuse, and can never invent one.

3,686
contracts read from the live chain
632
defined-risk structures built by code
12
shown to the committee
700
tests, no network in any of them
1
it may choose, or none

The inversion

Most agents ask a model what to buy. This one never lets it answer.

Asking a model “what should I trade?” is quick to build and impossible to trust. It can hallucinate a strike, size a position wrongly, or be confidently wrong with no record of why. So the model is handed a numbered menu it did not write, and may return one id, or the word ABSTAIN. A hallucinated id is treated as an abstention. Every decision, including each refusal, is appended to a hash-chained journal that anyone can verify without credentials.

Four stages, every one of them able to say no

Four chances to refuse. One to trade.

Python reads the live option chain and constructs every legal defined-risk structure it supports: bull put spreads, bear call spreads, iron condors, long straddles. Each one is fully specified before any model is called: strikes, legs, quantity, limit price, max loss, breakevens. Candidates that fail the liquidity gate, or that the guard would certainly refuse, are dropped before the model ever sees them. There is no function in this codebase that produces a naked short option.

3,686
contracts read
1,078
pass liquidity
632
structures built

A volatility analyst weighs implied against realized vol. A dedicated adversary argues against the trade and looks for the failure mode. Each returns a probability and its reasoning. An analyst that abstains is removed from both the numerator and the denominator of the aggregate, so no opinion ever counts as neutral. In a recorded cycle the adversary's objection about a thin hedge moved the trader off the highest-credit candidate onto a safer one.

2
analysts
~29s
run concurrently
0.2–1.0
voting weight range

One is pure code: it checks the position's own delta against the structure's stated thesis, and fails closed when the Greeks cannot be measured. The other is a model shown the candidate and the price action but never the committee's reasoning. Two calls to the same model on the same context agree with each other and prove nothing, so decorrelation is engineered rather than assumed. Both must pass.

code
thesis check
blind
second opinion
both
must agree])

Every order is judged against risk.yaml: max loss per position, concurrent positions, net delta and vega, daily loss, one new trade per underlying per day. It returns allow, deny, or a smaller size than requested. Any error, any missing data, any exception inside the guard is a refusal, verified by mutation testing rather than asserted.

$1,000
max loss / position
|30|
net delta cap
2%
daily loss halt

Who is on the desk

Three roles. One of them exists to disagree.

vol_analyst
Weighs implied against realized volatility
claude-haiku-4-5
“IV is +2.27pp above realized vol — options are rich, strongly favouring premium-selling structures.”
bear_adversary
Argues against every trade on the table
claude-haiku-4-5
“The +2.27% IV advantage is razor-thin — realized vol need only rise from 9.52% to ~10.7% to halve the edge.”
trader
Picks one candidate by id, or abstains
claude-sonnet-5
“Unlike c1 it clears bear_adversary's specific objection: the 777c short strike sits further out.”

Quotes are verbatim from a recorded cycle, not written for this page. In that cycle the adversary's objection about a thin hedge moved the trader off the highest-credit candidate, which is the reason a committee is not a rubber stamp.

Measured over 43 replayed decisions

It refused 72% of the time.

That is not timidity, and it is not a failure rate. Replaying the real committee over 43 post-cutoff windows, 31 ended in a refusal. Every one of them gave a reason, and the reasons are recorded in the journal whether or not they prevailed. Two examples, verbatim:

A refusal that was a defect
"Every available candidate is a short-premium credit structure, but implied vol sits below realized, a regime that argues for buying premium rather than selling it."
23 of 31 refusals said a version of this. The desk was right, and the menu was broken: the only long-premium structure it could build cost $2,270 against a $1,000 cap, so it was dropped before the committee ever saw it. Fixed.
A refusal that was the product
"vol_analyst favors a bullish long-premium structure (cheap calls, c7 to c9) while bear_adversary flags material downside and gap risk. The two views don't converge on a single direction, so per veto policy that disagreement forces ABSTAIN."
After the fix, zero of eight refusals cite a missing structure. Seven of eight are the two reviewers failing to agree. That is the system working.

The rate did not fall when we fixed the menu: 8 of 10 before, 8 of 10 after, on matched dates. We are reporting that as measured. What changed is the reason, and the reason is the part that matters.

The question this literature keeps failing

Is it reasoning, or is it remembering?

The standing criticism of LLM trading agents is knowledge contamination. Papers such as TradingAgents (arXiv 2412.20138) and FinMem (arXiv 2311.13743) backtest models over dates that sit inside their own training data, so a good result may be recall wearing the costume of analysis. Reviewers flag Sharpe ratios above the plausible empirical range for exactly this reason.

Our position is checkable. The model's knowledge cutoff is May 2026. Every live committee decision runs on August 2026 market data: prices, chains and a volatility regime that post-date the training corpus. A decision here cannot be memorised, because there was nothing to memorise.

The converse, stated plainly: the walk-forward harness below spans 720 days that partly predate the cutoff. That is acceptable only because it runs no model at all. It is a deterministic proxy, measured in code. We would not put an LLM over those dates and call the result evidence.

Out-of-sample, computed from real bars

A backtest that cannot lose is broken.

symbolwindowstrades win rateexpectancyprofit factormax drawdown
SPY13887.5%+0.62R3.502.0R
QQQ13785.7%+0.57R3.002.0R
AAPL13862.5%-0.12R0.836.0R
MSFT13785.7%+0.57R3.002.0R
Read this before the numbers. Thirty trades across four symbols proves nothing statistically, and one symbol loses money. That is the point. An earlier version of this harness scaled its risk threshold to the wrong horizon and produced a 97% win rate by construction. It was caught and corrected before publication. The repository this was converted from shipped a hardcoded “82.2% out-of-sample win rate” computed from nothing. That was deleted, not adapted.
Replay it yourself
python3 scripts/replay.py --all --verify reproduces every recorded verdict offline, with the environment stripped.
Verify the chain
make verify-journal verifies the chain. Empty, intact and tampered are three distinct outcomes.
Watch it decide
make session runs the whole pipeline against the live chain and sends nothing. Submitting needs an explicit flag.
Read the limits
risk.yaml is the single source of truth. If a number matters, it lives there and nowhere else.

The fitted volatility smile per expiry is rendered at /smile, with every strike whose deviation sits inside its own bid-ask noise drawn grey and scored zero. Across the live chain only about a fifth clear that bar.

( 01 )

Replay a real decision

Four recorded cycles, including two refusals. Verdicts are recomputed in your browser from the committed fixtures.

Open the judge desk →
( 02 )

Check it yourself

Clone it and run the verifier offline with the environment stripped. It reproduces the same verdicts.

View on GitHub

Where the audit trail stops

What we cannot prove.

No fill quality evidence
Paper trading only. We have no slippage data, no partial-fill behaviour under stress, and no evidence about what a real counterparty would do with these orders.
No claim of edge
Thirty out-of-sample trades across four symbols. That is a measurement harness proving the engine reports honestly, not a demonstration that the strategy makes money.
Calibration is mostly dormant
The loop is wired and proven end to end in tests, but few live trades have closed, so most analyst weights are still 1.0. Demoting an analyst on a handful of outcomes is the error we refuse to make.
One scenario is constructed
The fail-closed replay was produced by injecting a data outage into the real entrypoint. No live cycle has hit one yet, and the fixture says so in its own provenance field.
Paper fills are simulated
Nothing here has crossed a real spread against a real counterparty. A five-day window cannot establish edge under any statistical test, and we make no such claim.
Richness is not edge
The measured smile deviation is smaller than the bid-ask spread it would have to cross: the median strike that clears its own noise is worth about $3.94 per contract against a $4.00 median spread. It is used only to break ties between strikes that are already viable, never as a reason to trade.
The most famous track record in this industry, Medallion's, is known through a journalist's interviews rather than an audit. What keeps it credible is that the book says plainly where the evidence stops. This section is that sentence for us.
PA3JR0GVVEN0 · paper Options level 3 [ 00 : 00 : 00 ] Defined risk only Kill switch armed GitHub ↗