diff --git a/.gitignore b/.gitignore index 81928454..4dc7babb 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,4 @@ live/tape_sync.log research/meta/ research/.surge*.pull.* research/.oracle*.pull.* +research/replay_out/ diff --git a/FINDINGS.md b/FINDINGS.md index a7041af3..6f0cac6b 100644 --- a/FINDINGS.md +++ b/FINDINGS.md @@ -613,6 +613,48 @@ trigger, and the label-gap artifact class dies at the source. Tests are additive, never subtractive: raw streams are append-only, analysis reads only, and a study that needs different data records a NEW stream. +## The fill model is the next scorer (2026-07-23) + +The first full chain grades of both measurement harnesses landed together +and told one story from two directions. + +**Study A, confirmed dead twice.** The A2 arm's 1,344 chain-graded settles +read **−$7.54/fill** — within $2 of the corrected ledger, at real +execution, on the full trigger stream. Meanwhile the offline replay of the +v1 $100/5% bankroll spec over the same attempts stream sat at **+26%** — +its cash gate picked 70 of 2,692 attempts and got lucky (29W/17L). A book +trajectory at n=46 carries no information a measurement at n=1,344 +doesn't overrule; that asymmetry is why bankroll specs lost verdict power +in the A2 redesign, filed here as the standing example. + +**Study B, the divergence that matters.** The oracle harness's first chain +grade: **E≥0.07 −$8.51/fill (n=235) · E≥0.10 −$5.90 (n=127) · ~40% hit** +— while the forward ledger holds those tiers slightly positive. Both now +score through payouts_for, so this is not round three again — it is the +same LESSON one layer down: after the resolution model, the **fill model** +is the next place a sim quietly manufactures edge. The ledger's +6.7s-lag/3s-hold worst-print fills include entries no real order could +have gotten (the book repriced) and price the rest against prints instead +of the adversely-selected residue a live taker actually receives. The +capturability instrument existed precisely to veto this; it has. Taker +arm: evidence-dead (formal tier bars keep accruing, per pre-registration). + +**Five tandem tests, one day, all on already-flowing data** (scripts in +research/, each rerunnable): the copy edge is REAL but concentrated +(esports ~all of it; the live book's drag sits exactly there — the #14 +tension quantified); resting-bid copy entries beat taker FAKs **+$17.45 +vs +$12.86 per $100 signal** at 93% 60s trade-through (→ #20, +pre-registered, dark-deployed); mirrored sharp exits are bankroll ops, +not signal — no wallet's exits added value, 0xbadaf319's were 99% wrong +(→ #21, same); the orders_matched stream holds a **673-wallet +maker-sharp species** (+$5.9M pooled, ~33 expected by chance, 86% +invisible to every taker screen) — not copyable by taking, the +inventory-lean signal is the follow-on; and the sibling-sum scan showed +print-substrate "arbs" are resolution-dust artifacts — standing-book data +or nothing. The through-line of the week, now written as one sentence: +**every taker edge died at the requote wall, and every instrument that +measured the wall found the makers standing on top of it.** + ## Repo layout - `insider.py` — the detector: z-score/p-value, timing/freshness/sizing signals, diff --git a/HANDOFF.md b/HANDOFF.md index 277d7b6d..bcbe622b 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -42,14 +42,18 @@ min_order_usd $1 = venue reality). If something looks genuinely dangerous, DISARM (`flyctl secrets unset LIVE_CONFIRM -a wwf-copybot-live`) rather than push through. -## Snapshot (2026-07-21) +## Snapshot (2026-07-23) - **wwf-copybot-live** (REAL, ARMED): ~$62 equity ($66.42 contributed, realized −$12.17 lifetime — day-one incident + honest recognitions), - 6-wallet Set E rev 4, 4% of working equity/bet, alarm-free after the - 07-20 reconcile (CASH≠CHAIN −$1.75: empty-cond Odyssey bet the venue - auto-redeemed → hand-settled won +$0.68, $0.05 rounding folded; root - cause FIXED same day, #18: RTDS metadata-less rows now enrich at seed, - repair_market_meta un-sticks cond-less books each settle pass). **wwf-copybot** (paper $1k): same set, FAK-parity fills. + **7-wallet Set E rev 5** (JuiceFarm promoted 2026-07-23 off the #13 + bench method run early: +17%/+34% both windows, insider z 2.5, 1% + refunds; auto p80 floor $753), 4% of working equity/bet. + **#20/#21 dark flags deployed 2026-07-23** (`follow.entry_mode` / + `exit_mode`, defaults taker/mirror = byte-identical behavior; flip at + Friday's read opens the pre-registered forward windows — maker entries + rest at the sharp's price w/ 60s registry TTL; hold-through logs every + ignored sell to copybot_ignored_exits[.live].jsonl as the mirror + counterfactual). **wwf-copybot** (paper $1k): same set, FAK-parity fills. Both on the audit-hardened build (locks, chain-gated sweep, boot-id single-writer guard, TLS'd user-ws — HANDOFF_ARCHIVE rev 16). 2026-07-20: FAK no-match OPENs get one re-quote retry on both bots, PER-NICHE waits @@ -66,7 +70,7 @@ push through. nightly → ~15 min; the box no longer needs the Mac to stay healthy. `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. + (1W/993L, 0.075x); post-mortem in archive/value/PLAN.md; app destroyed. - **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. @@ -89,9 +93,13 @@ push through. - **wwf-oraclebot (PAPER, ~$3/mo, live 2026-07-22)**: Study B real-time harness — fair value tick-by-tick on the venue's own settlement feed, all E-tiers tracked, $100 FAK walks, three settle layers ending in - nightly chain truth (grade_oracle.py → oracle_paper_ledger.jsonl). Early - live cells lean positive at E≥0.07 — consistent with the corrected tape - read. Same attempts/markouts/settles streams as A2. + nightly chain truth (grade_oracle.py → oracle_paper_ledger.jsonl). + **First chain grade (2026-07-23): E≥0.07 −$8.51/fill (n=235), E≥0.10 + −$5.90 (n=127), ~40% hit — real execution loses at every tier while the + sim ledger reads positive. Both instruments share the scorer now, so the + divergence is the sim's 6.7s-lag FILL model flattering the tiers (round + 3's lesson recurring in the fill model). Taker arm is evidence-dead; + formal tier bars keep accruing; maker pivot (T1 sim) is the successor.** - **Data moat (2026-07-22, DATA LAW in research/README)**: all raw streams append-only and Mac-independent (Fly volumes + daily snapshots; recorder has ~3+ weeks offline headroom); forward.py backfills ledger-missing @@ -100,8 +108,16 @@ push through. study (chain-true): NO scalp inside the dead surge signal — hidden-loss cohort bleeds from minute one; taker case closed at every horizon. - **Verdicts pending**: edge/size-up (#14, ~end of July, pre-registered) · - Friday's combined read (#13 bench + #16 formal close + #17 oracle-tier - decision + #19 sprint-plan disposition — every number now chain-true). + Friday's combined read (#13 bench + #16 formal close [A2 chain grade + −$7.54/fill × 1,344 independently confirms the kill; virtual book's + +26% on n=46 is the variance footnote, not a signal] + #17 taker-arm + decision + #19 disposition + **#20/#21 flip decisions** — every number + chain-true). Five tandem tests 2026-07-23 (research/: copy_edge_slices, + copy_maker_entry, maker_sharps, sibling_sum_scan, sell_mirror_study): + T3 maker entries +$17.45 vs +$12.86 taker → #20; sells anti-signal → + #21; 673-wallet maker-sharp species (+$5.9M, 86% invisible to taker + screens) → inventory-lean follow-on; sibling-sum = print artifact, + parked; T1 crypto maker-quote sim needs its re-run. - Dashboards: jaxperro.com/{trading,live,test,value} — /test = both paper studies on one page (old /surge + /oracle URLs redirect) · daily pipeline on the Mac at 08:00 (launchd, lockfile) — floors, bench forward table, @@ -126,4 +142,4 @@ push through. - The bots commit their own state — always `git pull --rebase --autostash` before pushing from a session. - Read next: README.md (architecture + gotchas 1-18) · FINDINGS.md (research - story) · value/PLAN.md (the refutation) · HANDOFF_ARCHIVE.md (history). + story) · archive/value/PLAN.md (the refutation) · HANDOFF_ARCHIVE.md (history). diff --git a/HANDOFF_ARCHIVE.md b/HANDOFF_ARCHIVE.md index f89a7237..3d5778a7 100644 --- a/HANDOFF_ARCHIVE.md +++ b/HANDOFF_ARCHIVE.md @@ -365,7 +365,7 @@ reviewing the fix. Recommended: re-run a probe on an IN-PLAY market first.** Self-contained pickup for a fresh session (human or AI). Read [README.md](README.md) gotchas 1–16 (16 is the new-stack one), -[FINDINGS.md](FINDINGS.md), [ETHERSCAN_MIGRATION.md](ETHERSCAN_MIGRATION.md), +[FINDINGS.md](FINDINGS.md), [archive/ETHERSCAN_MIGRATION.md](archive/ETHERSCAN_MIGRATION.md), [LIVE_ROLLOUT.md](LIVE_ROLLOUT.md). The repo is authoritative. ## THE CRITICAL PATH IS DONE (2026-07-10 05:08Z) @@ -474,7 +474,7 @@ that; the 5-min backstop poll covers detection meanwhile). ## Queued work (unchanged priorities) -1. ETHERSCAN_MIGRATION.md phases 0→5. +1. archive/ETHERSCAN_MIGRATION.md phases 0→5. 2. Empirical fill model from `book` snapshots; depth gate before sizing up. 3. Funding-cluster tracer port to Etherscan logs. 4. Live-app watchdog (poll mode has no /health). diff --git a/README.md b/README.md index b4377d2e..3115810d 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,10 @@ Three deployed pieces + one static dashboard: | **daily pipeline** (`live/daily.sh`) | this Mac, launchd **08:00** (a `pmset repeat wakeorpoweron` RTC wake at **07:58** makes this run on time even from sleep — set 2026-07-08, undo with `sudo pmset repeat cancel`; job wrapped in `caffeinate -i` so mid-run idle-sleep can't kill it. Heads-up: the wake fires even lid-closed-in-a-bag — cancel it if the Mac travels) | refresh the bet cache → 5-gate skill scan → fee-aware sharp selection → conviction floors → backtest book → publish JSON feeds to GitHub | | **copybot worker** (`copybot.py` via `host/start.sh`) | **Fly.io app `wwf-copybot`, region `arn` (Stockholm), 24/7** — migrated off Railway 2026-07-06: Railway ran it in a US region, which Polymarket's IP geoblock would 403 the moment orders got real; Stockholm is unrestricted AND ~25ms from the CLOB's eu-west-2 primaries. Every boot self-checks the geo-gate (`host/geocheck.py`) and verifies the clone against `git ls-remote` (stale-replica guard) | **T0 = the RTDS trade stream** (gotcha 18): every platform trade, wallet-attributed, **~1s detection** (measured p50 0.8s over 22k msgs), silent-stale guard force-reconnects a quiet socket. Backstops: the Alchemy address-activity webhook (~3s, `POST /alchemy`, signature-verified — **T0b chain seed** 2026-07-14: its tx hashes decode straight from the receipt's OrderFilled logs when the data-api indexer lags, so RTDS-silent markets still copy at push speed), a 5-min backstop poll, and the reconcile janitor. Per-wallet **trade cursor** paginates the activity feed so clip bursts can't scroll past a fetch (H3). 60s heartbeat settles/publishes; paper-copies with real fees/lag/slippage AND live-FAK thin-book reality (**paper FAK parity** 2026-07-16: a quote with no ask inside the protected band books a MISS, not a fill — keeps the live-vs-paper per-signal ratio honest; `live/edge.py` turns it into the daily bankroll-decision verdict in `history/edge.csv` + the Discord digest footer); commits its book back to the repo | | **REAL-MONEY worker** (same code, `COPYBOT_ROLE=live`) | **Fly.io app `wwf-copybot-live`, `arn`, 24/7, ARMED 2026-07-10** — separate app so the two books never share a process, state file, or failure mode. Trades the signer's **Deposit Wallet** `0x455e…45a1` (pUSD collateral) via the unified SDK (`polymarket-client`) | Same T0 RTDS detection (`RTDS_DETECT=1`) + Alchemy/poll backstops; **own-fill push** via the CLOB user channel (`userws` in the heartbeat) makes in-play pending holds adopt the moment they match — ws events only *trigger* the resolver, `get_order` stays the arbiter (gotcha 17). Paper-parity sizing (4% of equity, $1 venue floor, no price floor, hard caps retired — the **depth gate** is the scaling rail: skip dust books (ask5c<$50), stake ≤10% of 5c depth — the spread>0.08 SKIP was retired 2026-07-19 as a lag-era relic (guard + protected band bound overpay)). Every placement/exit/settle pings Discord. Disarm: `flyctl secrets unset LIVE_CONFIRM -a wwf-copybot-live` | -| **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 | +| **VALUE bot** (CLOSED 2026-07-19 — [`archive/value/README.md`](archive/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 — [`archive/value/PLAN.md`](archive/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) + [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) | +| **dashboard** | [jaxperro.com/trading](https://jaxperro.com/trading) + [jaxperro.com/live](https://jaxperro.com/live) + [jaxperro.com/test](https://jaxperro.com/test) (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); `/test` is BOTH paper studies on one page (A2 surge measurement arm + oracle harness, each reading its bot's /feed + nightly chain-graded ledger; old /surge and /oracle URLs redirect). 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, 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 | +| `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, independently confirmed by the A2 measurement arm at −$7.54/fill chain-true; oracle #17: E0.04 killed, higher tiers ledger-positive but vetoed by the harness's real-latency chain grade — the 2026-07-23 fill-model lesson), TWO measurement harnesses (wwf-surgebot A2 + wwf-oraclebot: every-trigger $100 paper FAKs, attempts/markouts/settles append-only, bankroll specs replayed offline), 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) | diff --git a/ETHERSCAN_MIGRATION.md b/archive/ETHERSCAN_MIGRATION.md similarity index 100% rename from ETHERSCAN_MIGRATION.md rename to archive/ETHERSCAN_MIGRATION.md diff --git a/host/order_probe.py b/archive/order_probe_v1.py similarity index 100% rename from host/order_probe.py rename to archive/order_probe_v1.py diff --git a/value/PLAN.md b/archive/value/PLAN.md similarity index 100% rename from value/PLAN.md rename to archive/value/PLAN.md diff --git a/value/README.md b/archive/value/README.md similarity index 100% rename from value/README.md rename to archive/value/README.md diff --git a/value/fly.Dockerfile b/archive/value/fly.Dockerfile similarity index 100% rename from value/fly.Dockerfile rename to archive/value/fly.Dockerfile diff --git a/value/fly.value.toml b/archive/value/fly.value.toml similarity index 100% rename from value/fly.value.toml rename to archive/value/fly.value.toml diff --git a/value/start.sh b/archive/value/start.sh similarity index 100% rename from value/start.sh rename to archive/value/start.sh diff --git a/tests/test_valuebot.py b/archive/value/test_valuebot.py similarity index 100% rename from tests/test_valuebot.py rename to archive/value/test_valuebot.py diff --git a/value/valuebot.json b/archive/value/valuebot.json similarity index 100% rename from value/valuebot.json rename to archive/value/valuebot.json diff --git a/value/valuebot.py b/archive/value/valuebot.py similarity index 100% rename from value/valuebot.py rename to archive/value/valuebot.py diff --git a/value/valuebot_fills.jsonl b/archive/value/valuebot_fills.jsonl similarity index 100% rename from value/valuebot_fills.jsonl rename to archive/value/valuebot_fills.jsonl diff --git a/value/valuebot_state.json b/archive/value/valuebot_state.json similarity index 100% rename from value/valuebot_state.json rename to archive/value/valuebot_state.json diff --git a/research/README.md b/research/README.md index ad2d6763..4d7a6138 100644 --- a/research/README.md +++ b/research/README.md @@ -39,9 +39,26 @@ Layout: 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 — surge momentum (KILLED 2026-07-22, #16) - study_oracle.py Study B — crypto oracle fair value (#17: E0.04 killed, - E≥0.07 accumulating) + study_flow.py Study A — surge momentum (KILLED 2026-07-22, #16; A2 + chain grade −$7.54/fill × 1,344 independently confirms) + study_oracle.py Study B — crypto oracle fair value (#17: E0.04 killed; + E≥0.07/0.1 ledger-positive but the harness chain grade + 2026-07-23 reads −$8.51/−$5.90 per fill at real latency + — taker arm evidence-dead, tiers accrue to their formal + bars, maker pivot is the successor hypothesis) + copy_edge_slices.py T5 — parity-era copy edge by niche/lag/band/wallet + (esports carries it; feeds #14) + copy_maker_entry.py T3 — resting-bid copy entries beat taker FAKs + (+$17.45 vs +$12.86/signal; basis of #20) + sell_mirror_study.py sharp exits are bankroll ops, not signal + (basis of #21 hold-through) + maker_sharps.py T2 — 673 improbably-winning MAKERS in + orders_matched (86% invisible to taker screens); + follow-on: inventory-lean signal + sibling_sum_scan.py T4 — print-substrate sum-arb scan (artifact- + dominated; needs standing-book data; parked) + maker_quote_sim.py T1 — crypto maker quoting at fair−m (stale-quote + latency model; re-run pending) 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 diff --git a/research/maker_quote_sim.py b/research/maker_quote_sim.py new file mode 100644 index 00000000..23cd5ee2 --- /dev/null +++ b/research/maker_quote_sim.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 +"""T1 EXPLORATORY (2026-07-23) — crypto maker quoting on the oracle feed. + +Every taker study died at the requote wall (60-83% craters; makers repriced +in <4s). This sims BEING the maker: a resting bid pinned to oracle-fair +minus a margin, refreshed with latency R (the stale-quote window is the +risk), filled when a tape print crosses it, graded to chain truth. + +Model per print at t: our active bid = fair(S(t-R), vol(t)) - m (vol drift +over R<=4s is negligible; S(t-R) is the staleness that matters). Fill if +print px <= bid (the book crossed our level — queue-position optimism +stated). Fill price = our bid. Maker pays no taker fee. Per-token cooldown +60s, max 5 lots. Sprints only inside their window (no s0 lookahead — +harness rule, not the tape scorer's). + +Grid (pre-declared, not tuned after): m in {2c, 4c, 7c} x R in {1s, 4s}. +Readouts: EV/fill (chain), hit, fills/day, fair-markout at +60s (adverse +selection: how far fair moves against us right after we're filled). +NOT pre-registered — Stage 1 of the maker pivot; a live paper maker arm +only if this survives its own optimism caveats.""" +import json +import os +import sys +import time + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import tape # noqa: E402 +import study_oracle as so # noqa: E402 +import forward as fwd # noqa: E402 + +MARGINS = (0.02, 0.04, 0.07) +LATENCIES = (1.0, 4.0) +COOLDOWN_S = 60 +MAX_LOTS = 5 +STAKE = 100.0 + + +def main(): + db = tape.connect() + series = {s: so.TickSeries(tape.load_ticks(db, s)) + for s in ("btcusdt", "ethusdt", "solusdt", "xrpusdt", + "bnbusdt", "dogeusdt")} + outcomes = so.outcome_map(db) + tape.build_resolved(db) + uni = so.crypto_universe(db, outcomes, series) + tick_lo = min(s.ts[0] for s in series.values() if s.ts) + tick_hi = max(s.ts[-1] for s in series.values() if s.ts) + span_d = (tick_hi - tick_lo) / 86400 + print(f"universe {len(uni)} tokens · tick span {span_d:.1f}d") + cells = {(m, R): dict(fills=[], last=0.0, n_tok={}) + for m in MARGINS for R in LATENCIES} + for u in uni: + mkt = u["mkt"] + prints = db.execute("""SELECT ts, price FROM trades + WHERE asset = ? AND ts >= ? ORDER BY ts""", + [u["asset"], tick_lo]).fetchall() + if not prints: + continue + s = series[mkt["sym"]] + last_fill = {k: 0.0 for k in cells} + n_tok = {k: 0 for k in cells} + for ts, px in prints: + px = float(px) + if mkt["kind"] == "sprint" and ts < (mkt["t0"] or 0): + continue # no pre-window quoting + sig = s.vol_1s(ts) + if sig is None: + continue + for R in LATENCIES: + S_stale = s.at(ts - R) + f = so.fair_value(mkt, u["up"], S_stale, sig, ts) + if f is None: + continue + for m in MARGINS: + k = (m, R) + bid = f - m + if not (0.02 <= bid <= 0.95): + continue + if px > bid: + continue # print didn't reach our level + if ts - last_fill[k] < COOLDOWN_S or n_tok[k] >= MAX_LOTS: + continue + last_fill[k] = ts + n_tok[k] += 1 + # adverse selection: where is fair 60s after our fill + f60 = so.fair_value(mkt, u["up"], s.at(ts + 60), sig, + ts + 60) + cells[k]["fills"].append( + {"asset": u["asset"], "ts": ts, "bid": bid, + "fair": f, "mo60": (f60 - bid) if f60 else None}) + filled_assets = {f["asset"] for c in cells.values() for f in c["fills"]} + pays = fwd.payouts_for(db, list(filled_assets)) + print(f"grading {len(filled_assets)} filled tokens (chain overlay)…") + for (m, R), c in sorted(cells.items()): + fs = c["fills"] + graded = [(f, pays.get(f["asset"])) for f in fs] + graded = [(f, p) for f, p in graded if p is not None and p != 0.5] + if not graded: + print(f"m={m:.2f} R={R:.0f}s: {len(fs)} fills, none graded") + continue + pnl = wins = 0.0 + for f, p in graded: + sh = STAKE / f["bid"] + pnl += sh * (p - f["bid"]) # maker: no taker fee + wins += p == 1.0 + mo = [f["mo60"] for f, _ in graded if f["mo60"] is not None] + n = len(graded) + print(f"m={m:.2f} R={R:.0f}s: fills {len(fs)} ({n} graded) · " + f"{len(fs)/span_d:.0f}/day · EV/fill {pnl/n:+7.2f} · " + f"hit {wins/n:.2f} · avg bid " + f"{sum(f['bid'] for f,_ in graded)/n:.2f} · " + f"fair-markout60 {sum(mo)/len(mo)*100:+.1f}c" + if mo else "") + + +if __name__ == "__main__": + main()