diff --git a/.gitignore b/.gitignore index 0253e479..81928454 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,6 @@ research/.nightly.lock.d research/__pycache__/ live/parquet/ live/tape_sync.log +research/meta/ +research/.surge*.pull.* +research/.oracle*.pull.* diff --git a/research/forward.py b/research/forward.py index 85b7d077..ca040057 100644 --- a/research/forward.py +++ b/research/forward.py @@ -186,9 +186,30 @@ def main(): flow_p = json.load(open(os.path.join(HERE, "params", "study_flow.json"))) fz = flow_p["frozen"] frozen_at = flow_p["frozen_at"] - t_max = db.execute("SELECT max(ts) FROM trades").fetchone()[0] - days = [time.strftime("%Y-%m-%d", time.gmtime(t_max - i * 86400)) - for i in range(RESCORE_DAYS)] + t_min, t_max = db.execute("SELECT min(ts), max(ts) FROM trades").fetchone() + days = {time.strftime("%Y-%m-%d", time.gmtime(t_max - i * 86400)) + for i in range(RESCORE_DAYS)} + # offline-proofing (2026-07-22): a Mac gap > RESCORE_DAYS must not leave + # permanent holes in the verdict evidence — also score any tape-covered + # day the ledger has never seen (additive; scoring method unchanged) + have = set() + try: + for ln in open(LEDGER): + try: + r_ = json.loads(ln) + if r_.get("study") == "flow": + have.add(r_["day"]) + except Exception: + pass + except FileNotFoundError: + pass + t = t_min + while t < t_max: + d_ = time.strftime("%Y-%m-%d", time.gmtime(t)) + if d_ not in have: + days.add(d_) + t += 86400 + days = sorted(days) now = time.strftime("%Y-%m-%d %H:%M UTC", time.gmtime()) with open(LEDGER, "a") as fh: for d in days: diff --git a/research/grade_oracle.py b/research/grade_oracle.py index a2289fb8..c036fa55 100644 --- a/research/grade_oracle.py +++ b/research/grade_oracle.py @@ -43,6 +43,8 @@ def main(): os.path.join(HERE, ".oracle_attempts.pull.jsonl")) sftp("/data/oracle_markouts.jsonl", os.path.join(HERE, ".oracle_markouts.pull.jsonl")) + sftp("/data/oracle_settles.jsonl", + os.path.join(HERE, ".oracle_settles.pull.jsonl")) if not os.path.exists(TMP) or os.path.getsize(TMP) == 0: print("[grade_oracle] box unreachable or no state yet — skip") return 0 diff --git a/research/grade_surge.py b/research/grade_surge.py index d854b86f..cfb596f1 100644 --- a/research/grade_surge.py +++ b/research/grade_surge.py @@ -42,6 +42,8 @@ def main(): sftp("/data/surge_attempts.jsonl", ATT_PULL) sftp("/data/surge_markouts.jsonl", os.path.join(HERE, ".surge_markouts.pull.jsonl")) + sftp("/data/surge_settles.jsonl", + os.path.join(HERE, ".surge_settles.pull.jsonl")) if not ok: print("[grade_surge] box unreachable or no state yet — skip") return 0 diff --git a/research/meta_snap.py b/research/meta_snap.py new file mode 100644 index 00000000..e7c5d9cd --- /dev/null +++ b/research/meta_snap.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +"""Nightly market-metadata snapshot — the tape records prints and ticks but +not what markets ARE. This closes that gap additively: one gzipped JSONL +per UTC day under research/meta/ (LOCAL-only, gitignored — re-fetchable, +so repo stays lean) with every active market's cond, question, slug, +end date, tags, tokens/outcomes and neg-risk flag. + +Why (2026-07-22 data-moat pass): end dates make τ knowable AT TRIGGER for +every tape trigger (not just harness fills); tags replace title-heuristic +niches for future studies; token->outcome maps kill the label-gap class of +scorer artifact (FINDINGS round 3 disclosure 2). Append-only by +construction: a day file is written once and never rewritten (rerun same +day = idempotent overwrite of today only).""" +import gzip +import json +import os +import ssl +import time +import urllib.request + +HERE = os.path.dirname(os.path.abspath(__file__)) +OUT_DIR = os.path.join(HERE, "meta") +GAMMA = "https://gamma-api.polymarket.com/markets" +PAGE = 100 # gamma hard-caps limit at 100 +SSL_CTX = ssl._create_unverified_context() +KEEP = ("id", "conditionId", "question", "slug", "endDate", "endDateIso", + "category", "tags", "clobTokenIds", "outcomes", "negRisk", + "closed", "active", "volumeNum", "liquidityNum", "startDate") + + +def fetch(url): + req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"}) + with urllib.request.urlopen(req, timeout=30, context=SSL_CTX) as r: + return json.loads(r.read().decode()) + + +def iso(t): + return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(t)) + + +def main(): + os.makedirs(OUT_DIR, exist_ok=True) + day = time.strftime("%Y%m%d", time.gmtime()) + out = os.path.join(OUT_DIR, f"meta_{day}.jsonl.gz") + # gamma 422s past offset ~2100, so page inside end-date windows instead + now = time.time() + D = 86400 + edges = [now - 30 * D, now, now + 2 * D, now + 7 * D, now + 30 * D, + now + 120 * D, now + 730 * D, now + 3650 * D] + seen, rows = set(), [] + for dmin, dmax in zip(edges, edges[1:]): + offset = 0 + while True: + try: + page = fetch(f"{GAMMA}?active=true&closed=false&limit={PAGE}" + f"&offset={offset}&end_date_min={iso(dmin)}" + f"&end_date_max={iso(dmax)}") + except Exception as e: + print(f"[meta_snap] window {iso(dmin)[:10]}: fetch failed at " + f"offset {offset}: {e} — moving on") + break + if not page: + break + for m in page: + if m.get("id") in seen: + continue + seen.add(m.get("id")) + rows.append({k: m.get(k) for k in KEEP}) + offset += len(page) + if len(page) < PAGE or offset >= 2000: # stay under the 422 wall + break + if not rows: + print("[meta_snap] nothing fetched — keeping yesterday's file") + return 0 + fetched_at = int(time.time()) + tmp = out + ".tmp" + with gzip.open(tmp, "wt") as fh: + for r in rows: + r["fetched_at"] = fetched_at + fh.write(json.dumps(r) + "\n") + os.replace(tmp, out) + print(f"[meta_snap] {len(rows)} active markets -> {os.path.basename(out)} " + f"({os.path.getsize(out) // 1024}KB)") + return 0 + + +if __name__ == "__main__": + main() diff --git a/research/nightly.sh b/research/nightly.sh index caea829e..9c9bc624 100755 --- a/research/nightly.sh +++ b/research/nightly.sh @@ -55,6 +55,7 @@ done "$PY" grade_surge.py >> forward.log 2>&1 || true # A2 measurement -> chain truth "$PY" surge_book_replay.py >> forward.log 2>&1 || true # virtual $100/5% book "$PY" grade_oracle.py >> forward.log 2>&1 || true # oracle paper -> chain truth +"$PY" meta_snap.py >> forward.log 2>&1 || true # market metadata (local gz) cd .. git add research/forward_ledger.jsonl research/params/informed_set.json \ diff --git a/research/oraclebot.py b/research/oraclebot.py index 3a13f74f..a220f4e6 100644 --- a/research/oraclebot.py +++ b/research/oraclebot.py @@ -65,6 +65,7 @@ CLOB = "https://clob.polymarket.com" STATE = os.environ.get("ORACLE_STATE", "/data/oracle_state.json") ATTEMPTS = os.environ.get("ORACLE_ATTEMPTS", "/data/oracle_attempts.jsonl") MARKOUTS = os.environ.get("ORACLE_MARKOUTS", "/data/oracle_markouts.jsonl") +SETTLES = os.environ.get("ORACLE_SETTLES", "/data/oracle_settles.jsonl") DEBUG = bool(os.environ.get("ORACLE_DEBUG")) SEM_VER = "b1" # bump on ANY semantics-altering change MARKOUT_OFFSETS = (60, 300, 1800) # observational re-reads per fill @@ -669,11 +670,16 @@ class OracleBot: c = self.state["counters"] c["settled_total"] += 1 c["settle_tick" if source == "tick" else "settle_clob"] += 1 - self.state["settled"].append( - {**lot, "payout": pay, "source": source, "provisional": True, - "settled_ts": int(time.time()), "pnl": pnl}) + rec = {**lot, "payout": pay, "source": source, "provisional": True, + "settled_ts": int(time.time()), "pnl": pnl} + self.state["settled"].append(rec) del self.state["settled"][:-SETTLED_TRIM] del self.state["open"][lid] + try: # durable append-log: SETTLED_TRIM can + with open(SETTLES, "a") as fh: # never rotate a settle away + fh.write(json.dumps(rec) + "\n") + except Exception as e: + log(f"⚠ settles log write failed: {e}") word = "WON" if pay == 1.0 else "refund" if pay == 0.5 else "lost" log(f"SETTLE[{source}] {word} {lot['title'][:36]} {pnl:+.2f} · " f"realized {self.state['pnl_realized']:+.2f}") diff --git a/research/replay_out/replay_1784652375.json b/research/replay_out/replay_1784652375.json new file mode 100644 index 00000000..87a44cd3 --- /dev/null +++ b/research/replay_out/replay_1784652375.json @@ -0,0 +1,375 @@ +{ + "ran_at": 1784652368, + "tape": [ + 1784307337.0, + 1784649573.0 + ], + "lag_s": 6.7, + "results": { + "current@500": { + "bankroll": 500.0, + "copies": 488, + "realized": 63.27, + "open_mark": 36.17, + "end_equity": 599.43, + "misses": { + "crater": 48, + "entry_band": 17, + "capital": 463 + }, + "capital_miss_hypo": -64.6, + "peak_deploy_pct": 97.2, + "mean_deploy": 290.51, + "per_wallet": { + "0x921433c93558b9a4ba807ec824d02aad7ea2ddbf": 6.63, + "0xa1d57d329227c75b12b09f927fb3d6d6ef8f1343": 30.6, + "0xbadaf319415c17f28824a43ae0cd912b9d84d874": 19.69, + "0xd7d36345c4aab150e59577e360696b01d01d698b": 6.34 + } + }, + "current@1000": { + "bankroll": 1000.0, + "copies": 488, + "realized": 137.05, + "open_mark": 76.01, + "end_equity": 1213.07, + "misses": { + "crater": 49, + "entry_band": 17, + "capital": 463 + }, + "capital_miss_hypo": -133.03, + "peak_deploy_pct": 97.5, + "mean_deploy": 586.57, + "per_wallet": { + "0x921433c93558b9a4ba807ec824d02aad7ea2ddbf": 19.94, + "0xa1d57d329227c75b12b09f927fb3d6d6ef8f1343": 62.58, + "0xbadaf319415c17f28824a43ae0cd912b9d84d874": 39.7, + "0xd7d36345c4aab150e59577e360696b01d01d698b": 14.83 + } + }, + "current@2000": { + "bankroll": 2000.0, + "copies": 493, + "realized": 206.5, + "open_mark": 147.21, + "end_equity": 2353.71, + "misses": { + "crater": 50, + "entry_band": 17, + "capital": 459 + }, + "capital_miss_hypo": -191.6, + "peak_deploy_pct": 99.9, + "mean_deploy": 1193.53, + "per_wallet": { + "0x921433c93558b9a4ba807ec824d02aad7ea2ddbf": 40.61, + "0xa1d57d329227c75b12b09f927fb3d6d6ef8f1343": 74.12, + "0xbadaf319415c17f28824a43ae0cd912b9d84d874": 57.65, + "0xd7d36345c4aab150e59577e360696b01d01d698b": 34.11 + } + }, + "current@5000": { + "bankroll": 5000.0, + "copies": 579, + "realized": 270.42, + "open_mark": 200.29, + "end_equity": 5470.72, + "misses": { + "crater": 57, + "entry_band": 17, + "capital": 429 + }, + "capital_miss_hypo": -481.29, + "peak_deploy_pct": 99.7, + "mean_deploy": 2960.77, + "per_wallet": { + "0x921433c93558b9a4ba807ec824d02aad7ea2ddbf": 99.43, + "0xa1d57d329227c75b12b09f927fb3d6d6ef8f1343": 28.35, + "0xbadaf319415c17f28824a43ae0cd912b9d84d874": 57.65, + "0xd7d36345c4aab150e59577e360696b01d01d698b": 84.99 + } + }, + "current_plus_bench5@500": { + "bankroll": 500.0, + "copies": 388, + "realized": 94.71, + "open_mark": -24.08, + "end_equity": 570.63, + "misses": { + "crater": 81, + "capital": 1385, + "entry_band": 20 + }, + "capital_miss_hypo": 385.23, + "peak_deploy_pct": 99.8, + "mean_deploy": 352.7, + "per_wallet": { + "0x40ce68f1564f3c751b12d88a393d8cc0651dbf90": 53.64, + "0x73afc8160c17830c0c7281a7bf570c871455b880": -0.85, + "0x82d2e4dbb0a849ff8e2f5380719769145648beea": -4.03, + "0x921433c93558b9a4ba807ec824d02aad7ea2ddbf": 22.07, + "0xa1d57d329227c75b12b09f927fb3d6d6ef8f1343": 56.98, + "0xbadaf319415c17f28824a43ae0cd912b9d84d874": 0.11, + "0xc684828f6b03487759ced2ebdd975f91f3532228": -18.96, + "0xd7d36345c4aab150e59577e360696b01d01d698b": 6.42, + "0xe542afd3881c4c330ba0ebbb603bb470b2ba0a37": -20.66 + } + }, + "current_plus_bench5@1000": { + "bankroll": 1000.0, + "copies": 396, + "realized": 249.83, + "open_mark": -17.13, + "end_equity": 1232.7, + "misses": { + "crater": 87, + "capital": 1379, + "entry_band": 20 + }, + "capital_miss_hypo": 430.94, + "peak_deploy_pct": 99.3, + "mean_deploy": 726.02, + "per_wallet": { + "0x40ce68f1564f3c751b12d88a393d8cc0651dbf90": 107.67, + "0x73afc8160c17830c0c7281a7bf570c871455b880": -1.71, + "0x82d2e4dbb0a849ff8e2f5380719769145648beea": 33.73, + "0x921433c93558b9a4ba807ec824d02aad7ea2ddbf": 50.51, + "0xa1d57d329227c75b12b09f927fb3d6d6ef8f1343": 129.56, + "0xbadaf319415c17f28824a43ae0cd912b9d84d874": 0.21, + "0xc684828f6b03487759ced2ebdd975f91f3532228": -37.92, + "0xd7d36345c4aab150e59577e360696b01d01d698b": 9.13, + "0xe542afd3881c4c330ba0ebbb603bb470b2ba0a37": -41.36 + } + }, + "current_plus_bench5@2000": { + "bankroll": 2000.0, + "copies": 400, + "realized": 565.54, + "open_mark": -44.98, + "end_equity": 2520.56, + "misses": { + "crater": 94, + "capital": 1374, + "entry_band": 20 + }, + "capital_miss_hypo": 994.23, + "peak_deploy_pct": 99.9, + "mean_deploy": 1479.45, + "per_wallet": { + "0x40ce68f1564f3c751b12d88a393d8cc0651dbf90": 215.29, + "0x73afc8160c17830c0c7281a7bf570c871455b880": -3.41, + "0x82d2e4dbb0a849ff8e2f5380719769145648beea": 67.35, + "0x921433c93558b9a4ba807ec824d02aad7ea2ddbf": 101.75, + "0xa1d57d329227c75b12b09f927fb3d6d6ef8f1343": 260.48, + "0xbadaf319415c17f28824a43ae0cd912b9d84d874": 57.65, + "0xc684828f6b03487759ced2ebdd975f91f3532228": -73.98, + "0xd7d36345c4aab150e59577e360696b01d01d698b": 23.11, + "0xe542afd3881c4c330ba0ebbb603bb470b2ba0a37": -82.7 + } + }, + "current_plus_bench5@5000": { + "bankroll": 5000.0, + "copies": 306, + "realized": -294.03, + "open_mark": -557.2, + "end_equity": 4148.77, + "misses": { + "crater": 77, + "capital": 1451, + "entry_band": 20 + }, + "capital_miss_hypo": 7826.46, + "peak_deploy_pct": 100.0, + "mean_deploy": 2849.91, + "per_wallet": { + "0x40ce68f1564f3c751b12d88a393d8cc0651dbf90": 385.26, + "0x73afc8160c17830c0c7281a7bf570c871455b880": -8.31, + "0x82d2e4dbb0a849ff8e2f5380719769145648beea": -203.48, + "0x921433c93558b9a4ba807ec824d02aad7ea2ddbf": -170.65, + "0xa1d57d329227c75b12b09f927fb3d6d6ef8f1343": 29.92, + "0xbadaf319415c17f28824a43ae0cd912b9d84d874": 56.62, + "0xc684828f6b03487759ced2ebdd975f91f3532228": -185.87, + "0xd7d36345c4aab150e59577e360696b01d01d698b": 6.61, + "0xe542afd3881c4c330ba0ebbb603bb470b2ba0a37": -204.14 + } + }, + "bench5_only@500": { + "bankroll": 500.0, + "copies": 96, + "realized": 163.71, + "open_mark": -91.34, + "end_equity": 572.37, + "misses": { + "crater": 108, + "entry_band": 3, + "capital": 576 + }, + "capital_miss_hypo": 45.23, + "peak_deploy_pct": 99.9, + "mean_deploy": 349.25, + "per_wallet": { + "0x40ce68f1564f3c751b12d88a393d8cc0651dbf90": 35.11, + "0x73afc8160c17830c0c7281a7bf570c871455b880": -0.9, + "0x82d2e4dbb0a849ff8e2f5380719769145648beea": 142.64, + "0xc684828f6b03487759ced2ebdd975f91f3532228": 16.11, + "0xe542afd3881c4c330ba0ebbb603bb470b2ba0a37": -29.24 + } + }, + "bench5_only@1000": { + "bankroll": 1000.0, + "copies": 96, + "realized": 327.41, + "open_mark": -182.68, + "end_equity": 1144.73, + "misses": { + "crater": 108, + "entry_band": 3, + "capital": 578 + }, + "capital_miss_hypo": 79.55, + "peak_deploy_pct": 99.9, + "mean_deploy": 698.5, + "per_wallet": { + "0x40ce68f1564f3c751b12d88a393d8cc0651dbf90": 70.22, + "0x73afc8160c17830c0c7281a7bf570c871455b880": -1.81, + "0x82d2e4dbb0a849ff8e2f5380719769145648beea": 285.27, + "0xc684828f6b03487759ced2ebdd975f91f3532228": 32.22, + "0xe542afd3881c4c330ba0ebbb603bb470b2ba0a37": -58.49 + } + }, + "bench5_only@2000": { + "bankroll": 2000.0, + "copies": 100, + "realized": 663.55, + "open_mark": -365.32, + "end_equity": 2298.23, + "misses": { + "crater": 118, + "entry_band": 3, + "capital": 576 + }, + "capital_miss_hypo": 146.74, + "peak_deploy_pct": 99.5, + "mean_deploy": 1416.72, + "per_wallet": { + "0x40ce68f1564f3c751b12d88a393d8cc0651dbf90": 140.11, + "0x73afc8160c17830c0c7281a7bf570c871455b880": -3.61, + "0x82d2e4dbb0a849ff8e2f5380719769145648beea": 573.81, + "0xc684828f6b03487759ced2ebdd975f91f3532228": 66.27, + "0xe542afd3881c4c330ba0ebbb603bb470b2ba0a37": -113.03 + } + }, + "bench5_only@5000": { + "bankroll": 5000.0, + "copies": 108, + "realized": 1686.63, + "open_mark": -905.76, + "end_equity": 5780.87, + "misses": { + "crater": 126, + "entry_band": 3, + "capital": 579 + }, + "capital_miss_hypo": 281.19, + "peak_deploy_pct": 100.0, + "mean_deploy": 3776.85, + "per_wallet": { + "0x40ce68f1564f3c751b12d88a393d8cc0651dbf90": 345.54, + "0x73afc8160c17830c0c7281a7bf570c871455b880": -8.9, + "0x82d2e4dbb0a849ff8e2f5380719769145648beea": 1428.46, + "0xc684828f6b03487759ced2ebdd975f91f3532228": 162.79, + "0xe542afd3881c4c330ba0ebbb603bb470b2ba0a37": -241.27 + } + }, + "tape_top8@500": { + "bankroll": 500.0, + "copies": 24, + "realized": 234.06, + "open_mark": -34.09, + "end_equity": 699.97, + "misses": { + "crater": 56, + "capital": 1899, + "entry_band": 4 + }, + "capital_miss_hypo": 10255.45, + "peak_deploy_pct": 98.6, + "mean_deploy": 256.68, + "per_wallet": { + "0x717990979ff84a32d47205a7eede94317aab7d79": 92.14, + "0x7547479d43f4b52d892a6f2254050eea50edd158": 21.95, + "0x80d8dddcfdc075eb70f6d2d774a27bfb255ab703": 40.93, + "0x81a994924efdbed20c3d360bbea3913b0b6bdf08": 17.91, + "0x9ab303a355bf22a29e485d98fb88d140abb43044": 61.13 + } + }, + "tape_top8@1000": { + "bankroll": 1000.0, + "copies": 24, + "realized": 468.11, + "open_mark": -68.18, + "end_equity": 1399.94, + "misses": { + "crater": 56, + "capital": 1899, + "entry_band": 4 + }, + "capital_miss_hypo": 20493.44, + "peak_deploy_pct": 98.6, + "mean_deploy": 513.36, + "per_wallet": { + "0x717990979ff84a32d47205a7eede94317aab7d79": 184.28, + "0x7547479d43f4b52d892a6f2254050eea50edd158": 43.91, + "0x80d8dddcfdc075eb70f6d2d774a27bfb255ab703": 81.86, + "0x81a994924efdbed20c3d360bbea3913b0b6bdf08": 35.82, + "0x9ab303a355bf22a29e485d98fb88d140abb43044": 122.25 + } + }, + "tape_top8@2000": { + "bankroll": 2000.0, + "copies": 24, + "realized": 936.23, + "open_mark": -136.35, + "end_equity": 2799.87, + "misses": { + "crater": 56, + "capital": 1899, + "entry_band": 4 + }, + "capital_miss_hypo": 39961.13, + "peak_deploy_pct": 98.6, + "mean_deploy": 1026.72, + "per_wallet": { + "0x717990979ff84a32d47205a7eede94317aab7d79": 368.56, + "0x7547479d43f4b52d892a6f2254050eea50edd158": 87.81, + "0x80d8dddcfdc075eb70f6d2d774a27bfb255ab703": 163.72, + "0x81a994924efdbed20c3d360bbea3913b0b6bdf08": 71.63, + "0x9ab303a355bf22a29e485d98fb88d140abb43044": 244.5 + } + }, + "tape_top8@5000": { + "bankroll": 5000.0, + "copies": 32, + "realized": 1986.34, + "open_mark": -603.02, + "end_equity": 6383.32, + "misses": { + "crater": 68, + "capital": 1884, + "entry_band": 4 + }, + "capital_miss_hypo": 82755.52, + "peak_deploy_pct": 99.5, + "mean_deploy": 2630.6, + "per_wallet": { + "0x00093a689df7fb09a137f9db7102d9e967c85497": 17.26, + "0x717990979ff84a32d47205a7eede94317aab7d79": 667.1, + "0x7547479d43f4b52d892a6f2254050eea50edd158": 90.09, + "0x80d8dddcfdc075eb70f6d2d774a27bfb255ab703": 421.55, + "0x81a994924efdbed20c3d360bbea3913b0b6bdf08": 179.08, + "0x9ab303a355bf22a29e485d98fb88d140abb43044": 611.26 + } + } + } +} \ No newline at end of file diff --git a/research/replay_out/replay_1784652901.json b/research/replay_out/replay_1784652901.json new file mode 100644 index 00000000..63392056 --- /dev/null +++ b/research/replay_out/replay_1784652901.json @@ -0,0 +1,375 @@ +{ + "ran_at": 1784652878, + "tape": [ + 1784307337.0, + 1784649573.0 + ], + "lag_s": 6.7, + "results": { + "current@500": { + "bankroll": 500.0, + "copies": 109, + "realized": 69.65, + "open_mark": 2.56, + "end_equity": 572.22, + "misses": { + "crater": 45, + "entry_band": 10 + }, + "capital_miss_hypo": 0.0, + "peak_deploy_pct": 61.9, + "mean_deploy": 148.42, + "per_wallet": { + "0x921433c93558b9a4ba807ec824d02aad7ea2ddbf": 20.64, + "0xbadaf319415c17f28824a43ae0cd912b9d84d874": 31.14, + "0xd7d36345c4aab150e59577e360696b01d01d698b": 16.34, + "0xe8ca3f758c93f44f3ec210542ab78afb7c0bcccb": 1.53 + } + }, + "current@1000": { + "bankroll": 1000.0, + "copies": 109, + "realized": 139.31, + "open_mark": 5.11, + "end_equity": 1144.42, + "misses": { + "crater": 45, + "entry_band": 10 + }, + "capital_miss_hypo": 0.0, + "peak_deploy_pct": 61.9, + "mean_deploy": 296.79, + "per_wallet": { + "0x921433c93558b9a4ba807ec824d02aad7ea2ddbf": 41.28, + "0xbadaf319415c17f28824a43ae0cd912b9d84d874": 62.28, + "0xd7d36345c4aab150e59577e360696b01d01d698b": 32.68, + "0xe8ca3f758c93f44f3ec210542ab78afb7c0bcccb": 3.07 + } + }, + "current@2000": { + "bankroll": 2000.0, + "copies": 111, + "realized": 260.97, + "open_mark": 8.54, + "end_equity": 2269.51, + "misses": { + "crater": 45, + "entry_band": 10 + }, + "capital_miss_hypo": 0.0, + "peak_deploy_pct": 59.9, + "mean_deploy": 583.65, + "per_wallet": { + "0x921433c93558b9a4ba807ec824d02aad7ea2ddbf": 82.56, + "0xbadaf319415c17f28824a43ae0cd912b9d84d874": 107.15, + "0xd7d36345c4aab150e59577e360696b01d01d698b": 65.13, + "0xe8ca3f758c93f44f3ec210542ab78afb7c0bcccb": 6.13 + } + }, + "current@5000": { + "bankroll": 5000.0, + "copies": 113, + "realized": 593.04, + "open_mark": 13.2, + "end_equity": 5606.23, + "misses": { + "crater": 47, + "entry_band": 10 + }, + "capital_miss_hypo": 0.0, + "peak_deploy_pct": 55.0, + "mean_deploy": 1337.55, + "per_wallet": { + "0x921433c93558b9a4ba807ec824d02aad7ea2ddbf": 206.38, + "0xbadaf319415c17f28824a43ae0cd912b9d84d874": 209.69, + "0xd7d36345c4aab150e59577e360696b01d01d698b": 162.0, + "0xe8ca3f758c93f44f3ec210542ab78afb7c0bcccb": 14.97 + } + }, + "current_plus_bench5@500": { + "bankroll": 500.0, + "copies": 434, + "realized": 96.51, + "open_mark": -48.9, + "end_equity": 547.61, + "misses": { + "crater": 85, + "entry_band": 15, + "capital": 681 + }, + "capital_miss_hypo": -780.99, + "peak_deploy_pct": 99.0, + "mean_deploy": 318.8, + "per_wallet": { + "0x40ce68f1564f3c751b12d88a393d8cc0651dbf90": 11.83, + "0x73afc8160c17830c0c7281a7bf570c871455b880": 2.28, + "0x82d2e4dbb0a849ff8e2f5380719769145648beea": 29.37, + "0x921433c93558b9a4ba807ec824d02aad7ea2ddbf": -37.18, + "0xa1d57d329227c75b12b09f927fb3d6d6ef8f1343": 25.9, + "0xbadaf319415c17f28824a43ae0cd912b9d84d874": 39.23, + "0xc684828f6b03487759ced2ebdd975f91f3532228": 4.29, + "0xd7d36345c4aab150e59577e360696b01d01d698b": 9.12, + "0xe542afd3881c4c330ba0ebbb603bb470b2ba0a37": 11.67 + } + }, + "current_plus_bench5@1000": { + "bankroll": 1000.0, + "copies": 435, + "realized": 186.95, + "open_mark": -92.66, + "end_equity": 1094.3, + "misses": { + "crater": 92, + "entry_band": 15, + "capital": 674 + }, + "capital_miss_hypo": -1544.3, + "peak_deploy_pct": 99.8, + "mean_deploy": 645.43, + "per_wallet": { + "0x40ce68f1564f3c751b12d88a393d8cc0651dbf90": 23.68, + "0x73afc8160c17830c0c7281a7bf570c871455b880": 4.56, + "0x82d2e4dbb0a849ff8e2f5380719769145648beea": 58.75, + "0x921433c93558b9a4ba807ec824d02aad7ea2ddbf": -74.43, + "0xa1d57d329227c75b12b09f927fb3d6d6ef8f1343": 52.89, + "0xbadaf319415c17f28824a43ae0cd912b9d84d874": 78.53, + "0xc684828f6b03487759ced2ebdd975f91f3532228": 8.58, + "0xd7d36345c4aab150e59577e360696b01d01d698b": 18.25, + "0xe542afd3881c4c330ba0ebbb603bb470b2ba0a37": 16.14 + } + }, + "current_plus_bench5@2000": { + "bankroll": 2000.0, + "copies": 470, + "realized": 356.86, + "open_mark": -190.71, + "end_equity": 2166.15, + "misses": { + "crater": 96, + "entry_band": 15, + "capital": 669 + }, + "capital_miss_hypo": -3901.46, + "peak_deploy_pct": 99.9, + "mean_deploy": 1340.49, + "per_wallet": { + "0x40ce68f1564f3c751b12d88a393d8cc0651dbf90": 47.1, + "0x73afc8160c17830c0c7281a7bf570c871455b880": 9.07, + "0x82d2e4dbb0a849ff8e2f5380719769145648beea": 117.37, + "0x921433c93558b9a4ba807ec824d02aad7ea2ddbf": -148.01, + "0xa1d57d329227c75b12b09f927fb3d6d6ef8f1343": 46.58, + "0xbadaf319415c17f28824a43ae0cd912b9d84d874": 181.56, + "0xc684828f6b03487759ced2ebdd975f91f3532228": 17.06, + "0xd7d36345c4aab150e59577e360696b01d01d698b": 36.29, + "0xe542afd3881c4c330ba0ebbb603bb470b2ba0a37": 49.86 + } + }, + "current_plus_bench5@5000": { + "bankroll": 5000.0, + "copies": 580, + "realized": 602.28, + "open_mark": -449.4, + "end_equity": 5152.89, + "misses": { + "crater": 103, + "entry_band": 15, + "capital": 565 + }, + "capital_miss_hypo": -6685.68, + "peak_deploy_pct": 100.0, + "mean_deploy": 3566.07, + "per_wallet": { + "0x40ce68f1564f3c751b12d88a393d8cc0651dbf90": 115.41, + "0x73afc8160c17830c0c7281a7bf570c871455b880": 22.16, + "0x82d2e4dbb0a849ff8e2f5380719769145648beea": 294.84, + "0x921433c93558b9a4ba807ec824d02aad7ea2ddbf": -361.39, + "0xa1d57d329227c75b12b09f927fb3d6d6ef8f1343": 244.07, + "0xbadaf319415c17f28824a43ae0cd912b9d84d874": 118.04, + "0xc684828f6b03487759ced2ebdd975f91f3532228": 41.88, + "0xd7d36345c4aab150e59577e360696b01d01d698b": 89.05, + "0xe542afd3881c4c330ba0ebbb603bb470b2ba0a37": 38.22 + } + }, + "bench5_only@500": { + "bankroll": 500.0, + "copies": 127, + "realized": 48.5, + "open_mark": -94.98, + "end_equity": 453.52, + "misses": { + "crater": 93, + "entry_band": 2, + "capital": 210 + }, + "capital_miss_hypo": 184.83, + "peak_deploy_pct": 97.1, + "mean_deploy": 325.49, + "per_wallet": { + "0x40ce68f1564f3c751b12d88a393d8cc0651dbf90": -16.3, + "0x73afc8160c17830c0c7281a7bf570c871455b880": 2.13, + "0x82d2e4dbb0a849ff8e2f5380719769145648beea": 69.79, + "0xc684828f6b03487759ced2ebdd975f91f3532228": -23.15, + "0xe542afd3881c4c330ba0ebbb603bb470b2ba0a37": 16.03 + } + }, + "bench5_only@1000": { + "bankroll": 1000.0, + "copies": 127, + "realized": 99.87, + "open_mark": -189.92, + "end_equity": 909.95, + "misses": { + "crater": 98, + "entry_band": 2, + "capital": 209 + }, + "capital_miss_hypo": 369.7, + "peak_deploy_pct": 97.8, + "mean_deploy": 662.35, + "per_wallet": { + "0x40ce68f1564f3c751b12d88a393d8cc0651dbf90": -32.59, + "0x73afc8160c17830c0c7281a7bf570c871455b880": 4.25, + "0x82d2e4dbb0a849ff8e2f5380719769145648beea": 139.58, + "0xc684828f6b03487759ced2ebdd975f91f3532228": -43.23, + "0xe542afd3881c4c330ba0ebbb603bb470b2ba0a37": 31.85 + } + }, + "bench5_only@2000": { + "bankroll": 2000.0, + "copies": 127, + "realized": 197.83, + "open_mark": -379.72, + "end_equity": 1818.11, + "misses": { + "crater": 97, + "entry_band": 2, + "capital": 210 + }, + "capital_miss_hypo": 738.84, + "peak_deploy_pct": 97.7, + "mean_deploy": 1323.77, + "per_wallet": { + "0x40ce68f1564f3c751b12d88a393d8cc0651dbf90": -65.12, + "0x73afc8160c17830c0c7281a7bf570c871455b880": 8.51, + "0x82d2e4dbb0a849ff8e2f5380719769145648beea": 279.15, + "0xc684828f6b03487759ced2ebdd975f91f3532228": -87.06, + "0xe542afd3881c4c330ba0ebbb603bb470b2ba0a37": 62.35 + } + }, + "bench5_only@5000": { + "bankroll": 5000.0, + "copies": 134, + "realized": 407.96, + "open_mark": -947.69, + "end_equity": 4460.27, + "misses": { + "crater": 102, + "entry_band": 2, + "capital": 223 + }, + "capital_miss_hypo": 1823.59, + "peak_deploy_pct": 100.0, + "mean_deploy": 3502.73, + "per_wallet": { + "0x40ce68f1564f3c751b12d88a393d8cc0651dbf90": -160.06, + "0x73afc8160c17830c0c7281a7bf570c871455b880": 21.28, + "0x82d2e4dbb0a849ff8e2f5380719769145648beea": 697.03, + "0xc684828f6b03487759ced2ebdd975f91f3532228": -241.8, + "0xe542afd3881c4c330ba0ebbb603bb470b2ba0a37": 91.51 + } + }, + "tape_top8@500": { + "bankroll": 500.0, + "copies": 24, + "realized": 214.57, + "open_mark": -50.93, + "end_equity": 663.64, + "misses": { + "crater": 36, + "capital": 1090, + "entry_band": 4 + }, + "capital_miss_hypo": 5677.4, + "peak_deploy_pct": 98.4, + "mean_deploy": 256.45, + "per_wallet": { + "0x00093a689df7fb09a137f9db7102d9e967c85497": 11.06, + "0x717990979ff84a32d47205a7eede94317aab7d79": 67.99, + "0x7547479d43f4b52d892a6f2254050eea50edd158": 21.95, + "0x80d8dddcfdc075eb70f6d2d774a27bfb255ab703": 6.42, + "0x81a994924efdbed20c3d360bbea3913b0b6bdf08": 17.91, + "0x9ab303a355bf22a29e485d98fb88d140abb43044": 89.24 + } + }, + "tape_top8@1000": { + "bankroll": 1000.0, + "copies": 24, + "realized": 429.14, + "open_mark": -101.87, + "end_equity": 1327.27, + "misses": { + "crater": 36, + "capital": 1090, + "entry_band": 4 + }, + "capital_miss_hypo": 11311.08, + "peak_deploy_pct": 98.4, + "mean_deploy": 512.88, + "per_wallet": { + "0x00093a689df7fb09a137f9db7102d9e967c85497": 22.11, + "0x717990979ff84a32d47205a7eede94317aab7d79": 135.98, + "0x7547479d43f4b52d892a6f2254050eea50edd158": 43.91, + "0x80d8dddcfdc075eb70f6d2d774a27bfb255ab703": 12.85, + "0x81a994924efdbed20c3d360bbea3913b0b6bdf08": 35.82, + "0x9ab303a355bf22a29e485d98fb88d140abb43044": 178.48 + } + }, + "tape_top8@2000": { + "bankroll": 2000.0, + "copies": 26, + "realized": 890.73, + "open_mark": -209.48, + "end_equity": 2681.24, + "misses": { + "crater": 39, + "capital": 1086, + "entry_band": 4 + }, + "capital_miss_hypo": 21847.33, + "peak_deploy_pct": 100.0, + "mean_deploy": 1086.46, + "per_wallet": { + "0x00093a689df7fb09a137f9db7102d9e967c85497": 29.1, + "0x717990979ff84a32d47205a7eede94317aab7d79": 271.96, + "0x7547479d43f4b52d892a6f2254050eea50edd158": 87.81, + "0x80d8dddcfdc075eb70f6d2d774a27bfb255ab703": 25.7, + "0x81a994924efdbed20c3d360bbea3913b0b6bdf08": 71.63, + "0x9ab303a355bf22a29e485d98fb88d140abb43044": 404.53 + } + }, + "tape_top8@5000": { + "bankroll": 5000.0, + "copies": 31, + "realized": 2047.62, + "open_mark": -790.63, + "end_equity": 6256.99, + "misses": { + "crater": 45, + "capital": 1077, + "entry_band": 4 + }, + "capital_miss_hypo": 47556.82, + "peak_deploy_pct": 99.7, + "mean_deploy": 2581.86, + "per_wallet": { + "0x00093a689df7fb09a137f9db7102d9e967c85497": 29.1, + "0x3d3bbf5d4855ea12fbc610b4c2b49438ace728bd": 202.16, + "0x717990979ff84a32d47205a7eede94317aab7d79": 497.19, + "0x7547479d43f4b52d892a6f2254050eea50edd158": 90.09, + "0x80d8dddcfdc075eb70f6d2d774a27bfb255ab703": 64.24, + "0x81a994924efdbed20c3d360bbea3913b0b6bdf08": 179.08, + "0x9ab303a355bf22a29e485d98fb88d140abb43044": 985.76 + } + } + } +} \ No newline at end of file diff --git a/research/surge_book.json b/research/surge_book.json new file mode 100644 index 00000000..909118ba --- /dev/null +++ b/research/surge_book.json @@ -0,0 +1,39 @@ +{ + "computed_at": "2026-07-22 22:29 UTC", + "spec": { + "bank": 100.0, + "stake_pct": 0.05, + "stake_floor": 1.0, + "event_cap": 2, + "fee_rate": 0.03, + "slip_cap": 0.05 + }, + "sem_ver_source": "a2 attempts stream", + "equity": 98.32, + "cash": 13.32, + "open_n": 17, + "settled": 0, + "wins": 0, + "losses": 0, + "pnl_realized": 0.0, + "chain_graded_settles": 0, + "counters": { + "attempts_seen": 20, + "taken": 17, + "cash_skip": 0, + "event_skip": 0, + "open_skip": 0, + "crater": 3, + "open_unresolved": 17 + }, + "curve": [ + [ + 1784759179, + 100.0 + ], + [ + 1784759375, + 98.32 + ] + ] +} \ No newline at end of file diff --git a/research/surgebot.py b/research/surgebot.py index bf40abeb..63934869 100644 --- a/research/surgebot.py +++ b/research/surgebot.py @@ -61,6 +61,7 @@ SET_URL = ("https://raw.githubusercontent.com/jaxperro/winning-wallet-finder/" STATE = os.environ.get("SURGE_STATE", "/data/surge2_state.json") ATTEMPTS = os.environ.get("SURGE_ATTEMPTS", "/data/surge_attempts.jsonl") MARKOUTS = os.environ.get("SURGE_MARKOUTS", "/data/surge_markouts.jsonl") +SETTLES = os.environ.get("SURGE_SETTLES", "/data/surge_settles.jsonl") SEM_VER = "a2" # bump on ANY semantics-altering change MARKOUT_OFFSETS = (60, 300, 1800) # observational re-reads per fill BID_LEVELS = 3 @@ -410,11 +411,16 @@ class Surge: c = self.state["counters"] c["settled_total"] += 1 c["settle_clob"] += 1 - self.state["settled"].append( - {**lot, "payout": pay, "provisional": True, - "settled_ts": int(time.time()), "pnl": pnl}) + rec = {**lot, "payout": pay, "provisional": True, + "settled_ts": int(time.time()), "pnl": pnl} + self.state["settled"].append(rec) del self.state["settled"][:-SETTLED_TRIM] del self.state["open"][lid] + try: # durable append-log: SETTLED_TRIM can + with open(SETTLES, "a") as fh: # never rotate a settle away + fh.write(json.dumps(rec) + "\n") + except Exception as e: + log(f"⚠ settles log write failed: {e}") word = "WON" if pay == 1.0 else "refund" if pay == 0.5 else "lost" log(f"SETTLE {word} {lot['title'][:36]} {pnl:+.2f} · " f"realized {self.state['pnl_realized']:+.2f}")