docs: the 2026-07-22 lessons — resolution-timing survivorship (round 3)

FINDINGS: full round-3 section (mechanism, the 81%-vs-26% audit, how the
paper harness caught it, corrected verdicts, three standing rules) +
scorecard updates (surge dead, sub5c dead 0/38, oracle revived at E>=0.07)
+ correction banner on the 07-20 tape-era section. HANDOFF: queue +
snapshot reflect the kill, surgebot's instrument role, scorer law, Friday's
combined agenda. research/README: SCORER LAW + independent-instrument rule
+ full current layout. recorder/README: sync transport fallback. README:
/surge dashboard + research row truth.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
jaxperro
2026-07-22 17:39:46 -04:00
parent 7cb6c620ee
commit 790ef42c40
5 changed files with 118 additions and 32 deletions
+56 -2
View File
@@ -22,8 +22,9 @@ automatable from public data.
| **Multi-outcome logical arb** | ❌ dead | True partitions priced efficiently (min sum 0.999). Apparent "arbs" were non-exclusive market groupings. |
| **Cross-venue arb (Polymarket↔Kalshi)** | ❌ dead | Venues agree to ~1¢; locking both legs costs **>$1 after fees**. Real gaps last ~seconds and are taken by bots. |
| **Insider / sharp detection** | ✅ **works** | Statistical improbability (z-score of wins vs. odds) is a real, hard-to-fake edge signal. See `insider.py`. |
| **In-play surge momentum (tape)** | ⏳ forward window | Sim: ~+$24/fill after fees at measured execution; wallet identity adds NOTHING (controls match). Pre-registered verdict pending — #16. |
| **Crypto oracle fair-value taking** | ⏳ forward window | 86% of mispricings die as craters; big fillable edges are winner's-curse traps. Nothing frozen — #17. |
| **In-play surge momentum (tape)** | ❌ dead | The +$24-46/fill was resolution-timing survivorship (bias round 3, below). Chain truth: **$6/fill over 1,108 forward fills** — pre-registered kill met 2026-07-22, three days before the funding decision. Wallet-identity null stands. |
| **Sub-5¢ surge longshots** | ❌ dead | 0-for-38 under chain truth; the exploratory scan's 4 "winners" were the same resolution bias. |
| **Crypto oracle fair-value taking** | ⏳ forward window | Chain resolution grew the sample 30× and flipped the read: noisy-around-zero, slight positive tilt at E≥0.07 (+$1.8-2.3/fill, n≈470-860 fwd). E0.04 tier killed; stricter tiers accumulating — #17. |
## The big technical findings
@@ -466,6 +467,11 @@ optimistic view, discount accordingly.
## The tape era opens: first RTDS findings (2026-07-20)
> **CORRECTED 2026-07-22**: the Study-A/B *EV figures* in this section were
> inflated by resolution-timing survivorship (see the next section). The
> structural findings — sharp screen, identity-null, crater physics —
> survive; the surge P&L numbers do not.
Three days of the recorder's firehose in `live/rtds.duckdb` (13.8M fills,
160k wallets, every fill *including the losers*) killed the survivorship
problem at the source and produced four findings in one day — details, code,
@@ -507,6 +513,54 @@ fitted on the live bot's own 29 labeled attempts (fills + FAK misses) and
carries a measured **2¢/fill optimism bias** — every pre-registered pass
threshold sits at least 2× above it.
## Survivorship bias, round three: resolution timing kills Study A (2026-07-22)
The forward ledger said the surge signal earned **+$3546/fill**. The truth
was **$6/fill**. The gap was a third, subtler survivorship mechanism — and
the way it was caught is the real finding.
**The mechanism.** The ledger graded fills with the tape's proxy-resolution
and skipped "pending" markets. But tape resolution is *win-biased*: when our
side wins, the losing sibling goes quiet and the market resolves into the
ledger within hours. When our side **loses**, the *winning* sibling keeps
printing at 99¢ until close — the sibling-veto keeps the market "alive" and
the loss hides in the ignored pending bucket. Wins scored same-day; losses
waited. Jul-21 audit: tape-resolved fills hit 81% (+$46/fill); the 329
"pending" fills, chain-resolved on the spot, hit **26% ($49.61/fill)**.
Combined: 53%, ≈ breakeven-negative.
**How it was caught: an independent instrument refused to agree.** The
surge paper harness (wwf-surgebot — real-time, $5 stakes, graded nightly
against CTF payout vectors from day one) read 57.5% while the ledger read
7381%. Decomposition ruled out selection (same-trigger cohorts hit alike)
and entry prices (~1¢ effect); what remained was the scorer itself. The
same pattern as rounds one (unredeemed losers) and two (res_t poison): a
too-good number met a measurement that couldn't be sweet-talked.
**The fix** (`research/forward.py payouts_for()`, d34a4c5): chain-truth
overlay is now mandatory for every arm — tape proxy first, CTF payout
vectors for the remainder, refunds as scratches. Full recompute:
| arm | corrected verdict |
|---|---|
| Study A surge (#16) | **KILL met**: $6.03/fill over 1,108 forward fills; even the fit day negative. Identity-null unchanged (controls deflated equally). |
| sub-5¢ longshots | **0-for-38** — the scan's "winners" were the same bias. |
| Study B oracle (#17) | Sample ×30 under chain resolution (crypto sprints were veto-stuck). Now noisy-zero with a positive tilt at E≥0.07; the 4¢ tier killed, stricter tiers accumulating. |
**What the pre-registration bought.** The kill line was written 2026-07-20,
before any forward data; when the corrected numbers crossed it there was
nothing to argue about and no money at risk — the $100 deployment plan
(#19) was three days from its funding gate. Total cost of the false edge:
$0 real, ~2 days of compute, one paper book that ended at $99-and-change.
**Standing rules extracted:** (1) any scorer that can say "pending" must
prove pending is outcome-neutral, or chain-resolve it — on Polymarket it
never is neutral, because market liveness itself encodes the outcome;
(2) every study needs one instrument that doesn't share the scorer's
assumptions (the paper harness earns its keep even when — especially
when — it disagrees); (3) at 2050× payoffs, no small sample means
anything: the sub-5¢ "edge" survived a 31-fill scan and died at 38.
## Repo layout
- `insider.py` — the detector: z-score/p-value, timing/freshness/sizing signals,
+34 -21
View File
@@ -24,10 +24,14 @@ Builder API Key (SDK gasless relay) the runtime bot deliberately lacks —
LOW urgency, the platform auto-redeems winners itself. auto_redeem OFF.
Open now: #1 Signal A, #2 tape research, #4 redeem builder-key, #13 Fri
bench, #14 edge verdict, #15 tape-pull batching (Stage-0 fold+mirror
superseded the bulk path; per-file sftp batching still worth it), #16
surge momentum (forward window OPEN), #17 oracle fair value (accumulating,
nothing frozen). #18 (empty-cond copies unsettleable) closed same day:
RTDS seed enrichment + falsy-cond repair pass + 1h alarm.
superseded the bulk path; sync now sftp-with-base64-fallback), #16 surge
momentum (**KILL CRITERIA MET 2026-07-22** — resolution-timing scorer bug,
FINDINGS round-3 section; formal close at Friday's read), #17 oracle fair
value (sample ×30 under chain scoring; E0.04 tier killed, E≥0.07 slightly
positive and accumulating), #19 surge sprint plan (Friday decision matrix;
surgebot stays paper through the read). #18 (empty-cond copies
unsettleable) closed same day: RTDS seed enrichment + falsy-cond repair
pass + 1h alarm.
## Operating boundary (user, 2026-07-13 — standing)
**Full autonomy on the bots**; the real-money bot **stays ARMED**. Never
@@ -63,24 +67,33 @@ push through.
`live/parquet/` = complete durable layer (Stage-1 MotherDuck feedstock).
- **VALUE experiment: CLOSED 2026-07-19** — sub-2¢ hypothesis refuted
(1W/993L, 0.075x); post-mortem in value/PLAN.md; app destroyed.
- **research/ (NEW 2026-07-20, SILO — never touches the bots)**: tape-era
edge factory. Sharp screen (`live/tape_sharps.py`, resolution proxy
chain-validated 742/742, 25 copyable candidates); execution sim fitted on
our own 29 labeled attempts (2¢/fill optimism bias, thresholds sit 2×
above it); Study A surge momentum #16 (identity NULL result — controls
match the informed set) and Study B oracle fair value #17 (86% craters,
winner's-curse inversion). Verdicts ONLY from research/forward_ledger.jsonl.
- **research/ (SILO — never touches the bots)**: tape-era edge factory.
Sharp screen (`live/tape_sharps.py`, proxy chain-validated 742/742, 25
copyable candidates); execution sim fitted on 29 labeled live attempts.
**2026-07-22 SCORER LAW (FINDINGS round-3): every arm scores through
payouts_for() — tape proxy + mandatory CTF chain overlay. "Pending" is
never outcome-neutral on Polymarket (market liveness encodes the
outcome: losses hide behind the still-trading winning sibling).** Study
A surge (#16): KILLED by that correction ($6.03/fill × 1,108 forward
fills; identity-null stands). Study B oracle (#17): E0.04 killed,
E≥0.07 accumulating slightly positive. Verdicts ONLY from
research/forward_ledger.jsonl.
- **wwf-surgebot (PAPER, ~$3/mo)**: real-time surge harness — $100 book,
$5 stakes, event cap 2, paper FAK vs live CLOB, /feed endpoint → the
/surge dashboard; chain-graded nightly (grade_surge.py). THE instrument
that caught the scorer bug (its 57.5% refused to match the ledger's
81%). Runs through Friday's read, then archive per #19.
- **Verdicts pending**: edge/size-up (#14, ~end of July, pre-registered) ·
bench review Friday (#13: five new sharps + AIcAIc's prove-it week —
cross-read the tape screen's candidates in live/tape_sharps.json) ·
#16/#17 forward thresholds (in their issues).
- Dashboards: jaxperro.com/{trading,live,value} · daily pipeline on the Mac
at 08:00 (launchd, lockfile) — floors, bench forward table, edge row,
tape sync, Discord digest · tape mirror every 15 min
(com.jaxperro.tape-sync → recorder/sync_tape.py) · research nightly
fires 09:15 then WAITS for fresh tape (com.jaxperro.research-nightly →
research/nightly.sh, self-commits the forward ledger). All launchd agents
removable with `launchctl unload ~/Library/LaunchAgents/<label>.plist`.
Friday's combined read (#13 bench + #16 formal close + #17 oracle-tier
decision + #19 sprint-plan disposition — every number now chain-true).
- Dashboards: jaxperro.com/{trading,live,surge,value} · daily pipeline on
the Mac at 08:00 (launchd, lockfile) — floors, bench forward table, edge
row, tape sync, Discord digest · tape mirror every 15 min
(com.jaxperro.tape-sync → sync_tape.py, sftp + base64-console fallback)
· research nightly fires 09:15 then WAITS for fresh tape
(com.jaxperro.research-nightly; self-commits ledger, informed set,
surge/oracle grades). All launchd agents removable with
`launchctl unload ~/Library/LaunchAgents/<label>.plist`.
## Ops quick-reference
- Follow-set change: edit live/copybot.paper.json → `./live/deploy_bot.sh`;
+2 -2
View File
@@ -29,7 +29,7 @@ Three deployed pieces + one static dashboard:
| **VALUE bot** (CLOSED 2026-07-19 — [`value/README.md`](value/README.md)) | ~~Fly app `wwf-valuebot`~~ destroyed after the paper verdict: 994 tickets, 1W/993L, 0.075x — today's sub-2¢ asks are fully informed; the 2025-era calibration edge is gone — a hard SILO: own code (`value/valuebot.py`, zero copybot imports), own state/feed, own image, no shared wallet ever | Systematically buys sub-2¢ contracts (the calibration study's one underpriced bucket — [`value/PLAN.md`](value/PLAN.md)); honest FAK fill model, chain-truth settles, $1 tickets, event cap 1. Verdict at ~2k resolved tickets vs a ~1.05% break-even hit rate |
| **RTDS tape recorder** ([`recorder/README.md`](recorder/README.md)) | **Fly.io app `wwf-recorder`, `arn`, 24/7** — third silo: no repo clone (code in image), no keys, 25GB volume | Records the FULL firehose (~8M events/day): every trade, order MATCH (maker side), comment, crypto tick — dual-socket capture (one socket alone measured 92.9% coverage; the twin covers per-conn silences). **Stage-0 warehouse (2026-07-21): the box folds its own segments into row-verified Parquet on the volume; the Mac mirrors + appends into `live/rtds.duckdb` every 15 min** (`com.jaxperro.tape-sync`). Nothing deletes without a verified second copy (gz needs its parquet; parquet needs the Mac's ack) |
| **Discord digest** (`live/discord_daily.py`) | end of the daily pipeline | one message/day: the sharp list with profile links + 30-day conviction stats (per-trade pings retired 2026-07-04 for PAPER; the LIVE book pings every real placement/exit/settle) |
| **dashboard** | [jaxperro.com/trading](https://jaxperro.com/trading) + [jaxperro.com/live](https://jaxperro.com/live) (static, in the `jaxperro` repo) | `/trading` renders the paper book, backtest book and sharp table; `/live` is the REAL MONEY page (reads `live/copybot_live_real.json` — live since 2026-07-10). Both pages share `trading/copybot-section.js` — one renderer, no drift |
| **dashboard** | [jaxperro.com/trading](https://jaxperro.com/trading) + [jaxperro.com/live](https://jaxperro.com/live) + [jaxperro.com/surge](https://jaxperro.com/surge) (static, in the `jaxperro` repo) | `/trading` renders the paper book, backtest book and sharp table; `/live` is the REAL MONEY page (reads `live/copybot_live_real.json` — live since 2026-07-10); `/surge` is the Study-A paper harness (reads wwf-surgebot's /feed + the nightly chain-graded ledger). Wallet cards everywhere show LIFETIME numbers server-side (window sums lied twice — 2026-07-21/22) |
**The calibration experiment (running now):** a fresh $1,000 paper book,
**reset 2026-07-08** so it measures exactly one thing — the follow set in
@@ -137,7 +137,7 @@ does).
| `insider.py` | the original detector: z-score, pre-resolution timing, fresh-wallet flags, funding-cluster rings |
| `smart_money.py` | shared HTTP helper + survivorship-corrected win-rate dashboard (`:8899`) |
| `archive/webhook_receiver.py` | retired 2026-07-04: Alchemy webhook → per-trade Discord pings (replaced by `live/discord_daily.py`'s daily digest) |
| `research/` | tape-era edge factory, **SILO'd from the bots** ([research/README](research/README.md)): read-only RTDS loaders, execution sim calibrated on the live ledger, pre-registered studies (#16 surge momentum, #17 oracle fair value), nightly forward ledger — the only source of study verdicts |
| `research/` | tape-era edge factory, **SILO'd from the bots** ([research/README](research/README.md)): read-only RTDS loaders, calibrated execution sim, pre-registered studies scored through a MANDATORY chain-truth overlay (the 2026-07-22 scorer law — tape-resolution timing is win-biased and killed Study A #16 at $6/fill once corrected; oracle #17 continues at E≥0.07), the surge paper harness (wwf-surgebot), nightly forward ledger — the only source of study verdicts |
| `wide/` | frozen-subgraph bulk scanner (1.76M wallets, historical only — subgraph froze Jan 2026) |
| `archive/` | everything retired, kept honest ([archive/README](archive/README.md)): the six failed strategies, earlier research sweeps (`hunt/huntwide/oos/copyback`), the superseded live selection layer (`live-research/`), the scrapped Polymarket-US venue probe (`us-venue/`), and retired infra (`retired-infra/`: Railway config, Mac launchd runner, GH-Actions cron) |
+3 -1
View File
@@ -38,7 +38,9 @@ the tape.
fold can never starve capture. ~250-400MB/day of parquet -> months of
headroom, months more once mirrored+acked files get pruned.
- **`sync_tape.py`** (Mac, every 15 min via `com.jaxperro.tape-sync` +
from daily.sh): pulls new manifest entries over `flyctl sftp`,
from daily.sh): pulls new manifest entries over `flyctl sftp` (240s cap,
then the base64-over-console fallback that carried ingest.py — sftp
flaked twice in two days, 2026-07-22, leaving magic-byte-less partials),
row-verifies each file, appends its rows into `live/rtds.duckdb`'s
native tables (research keeps native speed — views-over-parquet was
rejected: per-asset point queries would crawl), records it in
+23 -6
View File
@@ -16,17 +16,34 @@ anything on the live bot"):
verdict + kill criteria) BEFORE their forward window opens. Exploration
happens on already-collected tape; **verdicts only come from
`forward_ledger.jsonl` rows dated after the params freeze commit.**
- **SCORER LAW (2026-07-22, FINDINGS "round three"): every scorer resolves
outcomes through `forward.payouts_for()` — tape proxy first, CTF chain
overlay for the remainder. A "pending" bucket is NEVER ignorable on
Polymarket: market liveness encodes the outcome (a losing bet's winning
sibling keeps trading, so losses hide in pending while wins score).
This bug inflated Study A from a true $6/fill to +$46/fill.**
- **Every study gets one instrument that does not share the scorer's
assumptions** — the surge paper harness (chain-graded from day one) is
what caught the bug. Divergence between instruments is signal, not noise.
Layout:
tape.py read-only loaders · tape proxy-resolution (terminal-VWAP +
sibling veto, the 742/742 chain-validated method) · title
parsers (niche, crypto strike/expiry/sprint)
sibling veto — exact per-bet, but resolution TIMING is
win-biased; see SCORER LAW) · title parsers · chain_overlay()
sim.py execution replayer calibrated on OUR live fills ledger
(lag, FAK no-match, protected band, 3% taker fee)
study_flow.py Study A — informed-flow state signal
study_oracle.py Study B — crypto oracle fair value vs the book
requote.py crater→requote timing measurement (retry tuning)
forward.py scores frozen studies on new tape days → forward_ledger.jsonl
study_flow.py Study A — surge momentum (KILLED 2026-07-22, #16)
study_oracle.py Study B — crypto oracle fair value (#17: E0.04 killed,
E≥0.07 accumulating)
requote.py crater→requote timing (feeds the bots' per-niche retry)
forward.py scores frozen studies on new tape days → forward_ledger
(payouts_for chain overlay mandatory; controls + sub5c
exploratory arm — 0-for-38, dead)
informed_set.py publishes params/informed_set.json nightly (surgebot input)
surgebot.py real-time PAPER harness (wwf-surgebot, /feed endpoint →
jaxperro.com/surge) — $100 book, $5 stakes, event cap 2
grade_surge.py nightly chain-truth re-grade of the surge paper book
→ surge_paper_ledger.jsonl
params/ frozen study parameters (committed = frozen)
nightly.sh launchd runner (fires 09:15, then WAITS for fresh tape —
Stage 0 keeps the tape ~15-min fresh whenever the Mac is