A deterministic fact-checker between the AI and the exchange. It asks whether the claimed setup is on the chart, what happened the last eighty times, and whether the edge survives fees. Then it says yes, maybe, or no, with every number.
Size caps, slippage collars, symbol allowlists: all of them verify what the agent is about to do. None of them verify why. When an agent says "buy SOL, momentum is strong", nothing asks whether that setup has ever paid.
"AI can make mistakes, act on outdated or hallucinated information, or send incorrect parameters — always verify before execution."
"Momentum" maps to measurable setups: a big up day by the coin's own 90th percentile, three green closes, a 20-day breakout. If none is present on the signal bar, the rationale is hallucinated. Hard veto.
thesis_presentMedian forward return, hit rate, sample size and a bootstrap 95% interval, from the symbol's own daily candles, with no lookahead. Shown at 1, 3 and 7 days.
base_rate · n · median · CI95Taker fees both legs plus order-book impact both legs, walked against the live depth for the proposed size. Edge is judged after cost, never before.
edge_after_cost_bpsAn MCP server any client can ask, and a Claude Code hook that runs on every Binance order tool before Binance sees the call. They share one code path, so they cannot disagree.
"Buy $100 of SOL, momentum looks strong."
Recalls the thesis, computes the base rate and cost, returns APPROVE, CAUTION or VETO with receipts. Fail closed.
Sees only approved orders, then applies its own confirm-before-execute. No withdrawal scope exists.
Base rates over 20 Binance markets, up to 1,000 daily bars each. "Paid" means the lower 95% bound clears a 30 bps round trip; "lost" means the upper bound does not reach it.
| setup | markets where it paid | where it reliably lost |
|---|---|---|
| Three green days in a row | 0 | 8 |
| 20-day breakout | 0 | 4 |
| Big up day | 0 | 3 |
| Three red days in a row | 5 | 0 |
Then the gate was tested on itself: a $100 buy judged on every one of 5,568 days across eight symbols, using only the data available that day. Nothing was tuned on the result.
| specific-setup days | days | median 3d | hit |
|---|---|---|---|
| every such day, no gate | 2,440 | +0.08% | 51% |
| days the gate did not veto | 1,480 | +0.33% | 53% |
| vetoes on strength setups | 742 | -0.68% | 45% |
| vetoes on weakness setups | 218 | +0.47% | 55% |
| approvals | 109 | -0.04% | 50% |
The gate's job is stopping an AI from chasing strength, and out of sample that is where it is right: the 742 strength-chasing trades it vetoed lost a median 0.68%. But APPROVE is not a buy signal; its 109 approvals did no better than average. And it is wrong when it vetoes dip buys, which went on to pay. Both findings stay in the code and the tables, because a gate fitted to its own evaluation would be worth nothing.
Try it
# clone and judge a trade on live data, no keys git clone https://github.com/DannyTrillion/second-opinion.git cd second-opinion python3 -m secondopinion check SOL buy 100 --thesis "momentum" # replay the August 27 veto, offline python3 -m secondopinion demo --offline
Wire it into Agent OS
# as an MCP tool beside binance-mcp-server claude mcp add second-opinion \ --env PYTHONPATH=$PWD -- python3 -m secondopinion serve # as a hook that fires on every Binance order tool python3 -m secondopinion install-hook --apply