Files
jaxperro a8c5db88b1 research: markout_flow corrected to chain truth (payouts_for) — v0 verdict retracted, scalp killed properly
v0 (res_tok only) said 'hold wins everywhere, +$43/fill' — that was
resolution-timing survivorship (round 3). Chain-graded, 1,146 forward
fills: hold -$5.92/fill and EVERY exit horizon negative too (best -$4.18
at +30m). Cohort split: tape-resolved winners drift to +$44 held; the
hidden-loss cohort bleeds monotonically from minute one (-$6@60s ->
-$44@2h). No scalp, no rescue — surge moments are symmetric information
events; net of fees + worst-print entry the taker case is closed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 19:01:38 -04:00

117 lines
4.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""EXPLORATORY (2026-07-22, user ask; CORRECTED same night) — markout-exit
curve for the surge signal: given the round-3 corrected verdict (surge
holds LOSE $6/fill under chain truth, #16 KILL met), does exiting at a
fixed horizon beat holding — i.e. was there a scalp hiding inside a dead
hold-to-resolution strategy?
v0 of this script used res_tok only and concluded "hold wins everywhere"
(+$43/fill holds) — that conclusion was resolution-timing survivorship
(FINDINGS round 3): the resolved cohort IS the winners. This version
scores every fill with forward.payouts_for() (tape proxy + mandatory CTF
chain overlay, refunds as scratches) and splits cohorts explicitly.
Still prints-based on the EXIT leg (last print <= t+H ≈ optimistic vs the
real bid; the harnesses' markout re-reads at +60/300/1800s accrue the real
bid marks to haircut this). Exit fee charged same as entry. NOT
pre-registered — shapes (or kills) a possible A3-scalp hypothesis only."""
import json
import os
import time
import tape
import sim as simmod
import study_flow as sf
import forward as fwd
HERE = os.path.dirname(os.path.abspath(__file__))
HORIZONS = (60, 300, 1800, 7200)
FEE = simmod.FEE_RATE
def day_bounds(d):
lo = time.mktime(time.strptime(d, "%Y-%m-%d")) - time.timezone
return lo, lo + 86400
def main():
db = tape.connect()
cal = json.load(open(os.path.join(HERE, "params", "sim_calibration.json")))
fz = json.load(open(os.path.join(HERE, "params", "study_flow.json")))["frozen"]
t_min, t_max = db.execute("SELECT min(ts), max(ts) FROM trades").fetchone()
days = []
t = t_min
while t < t_max:
days.append(time.strftime("%Y-%m-%d", time.gmtime(t)))
t += 86400
tape.build_resolved(db)
tape_resolved = {a for (a,) in db.execute(
"SELECT asset FROM res_tok").fetchall()}
sim = simmod.Sim(db, lag_s=simmod.LAG_P50, hold_s=cal["hold_s"],
fill="worst")
fills = []
for d in days:
lo, hi = day_bounds(d)
hi = min(hi, t_max)
S = sf.informed_set(db, lo, fz["top_n"])
trig = sf.signals(db, S, lo, hi, fz["window_s"], fz["flow_usd"])
for t_ in trig:
r = sim.try_buy(t_["asset"], t_["ts"], t_["p_ref"],
stake_usd=sf.STAKE)
if r["filled"]:
fills.append({"day": d, "fwd": d >= "2026-07-21",
"asset": t_["asset"], **r})
print(f"{d}: {len(trig)} triggers")
pays = fwd.payouts_for(db, [f["asset"] for f in fills])
rows = []
for f in fills:
pay = pays.get(f["asset"])
if pay is None:
continue # truly unresolved even on chain
row = {"day": f["day"], "fwd": f["fwd"], "px": f["price"],
"cohort": "tape" if f["asset"] in tape_resolved else "chain",
"hold_pnl": f["shares"] * (pay - f["price"]) - f["fee"],
"win": pay == 1.0, "refund": pay == 0.5, "mo": {}}
for H in HORIZONS:
m = sim.markout(f["asset"], f["fill_ts"], H)
if m is None:
continue
xfee = FEE * f["shares"] * min(m, 1 - m)
row["mo"][H] = f["shares"] * (m - f["price"]) - f["fee"] - xfee
rows.append(row)
def report(tag, rs):
if not rs:
return
n = len(rs)
hold = sum(r["hold_pnl"] for r in rs)
print(f"\n== {tag}{n} chain-graded fills · HOLD EV/fill "
f"{hold/n:+.2f} · hit {sum(r['win'] for r in rs)/n:.2f}"
+ (f" · {sum(r['refund'] for r in rs)} refunds"
if any(r["refund"] for r in rs) else ""))
for H in HORIZONS:
sub = [r for r in rs if H in r["mo"]]
if not sub:
continue
mo = sum(r["mo"][H] for r in sub)
hold_sub = sum(r["hold_pnl"] for r in sub)
print(f" exit +{H:>5}s: EV/fill {mo/len(sub):+7.2f} vs hold "
f"{hold_sub/len(sub):+7.2f} on same {len(sub)} "
f"({100*len(sub)/n:.0f}% coverage)")
fwd_rows = [r for r in rows if r["fwd"]]
report("ALL days", rows)
report("FORWARD days (>= 07-21)", fwd_rows)
report("FORWARD · tape-resolved cohort (the old scorer's sample)",
[r for r in fwd_rows if r["cohort"] == "tape"])
report("FORWARD · chain-only cohort (the hidden losses)",
[r for r in fwd_rows if r["cohort"] == "chain"])
for lo_, hi_, tag in [(0, .3, "entry 0-30c"), (.3, .5, "entry 30-50c"),
(.5, .7, "entry 50-70c"), (.7, .95, "entry 70-95c")]:
report(f"FORWARD · {tag}",
[r for r in fwd_rows if lo_ <= r["px"] < hi_])
if __name__ == "__main__":
main()