mirror of
https://github.com/jaxperro/winning-wallet-finder.git
synced 2026-07-27 15:57:47 +00:00
research: Study C FREEZE — maker inventory-lean pre-registration (follow arm verdict; fade failed its concentration gate)
score_lean wired into the nightly (walk-forward as-of screening, frozen trigger, chain truth); params/study_lean.json frozen; forward window = ledger rows dated after this commit. Fade $2k+ arm excluded by the pre-declared gate (top event 32%, tail net-negative) — tracked report-only. Follow $150-500: robust across 869 events (top 14%). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -54,3 +54,4 @@ research/meta/
|
||||
research/.surge*.pull.*
|
||||
research/.oracle*.pull.*
|
||||
research/replay_out/
|
||||
research/.maker_lean_triggers.json
|
||||
|
||||
@@ -180,6 +180,56 @@ def score_oracle(db, P, d, hold_s):
|
||||
return row
|
||||
|
||||
|
||||
def score_lean(db, d):
|
||||
"""Study C (maker inventory-lean, pre-registered): walk-forward day row.
|
||||
Screen as-of day start (maker_lean.screen_asof — tape strictly before
|
||||
the day), frozen trigger (maker_lean.day_leans), chain truth via
|
||||
payouts_for. Arms: follow_small ($150-500) · fade_whale ($2k+) · mid
|
||||
bucket report-only. Scored at last-print entry (stated optimism — a
|
||||
PASS graduates to a real-execution paper arm, never to money)."""
|
||||
import maker_lean as ml
|
||||
lo, hi = day_bounds(d)
|
||||
t_max = db.execute(
|
||||
"SELECT max(ts) FROM aux WHERE type='orders_matched'").fetchone()[0]
|
||||
hi = min(hi, t_max or 0)
|
||||
if hi <= lo:
|
||||
return {"skipped": "no maker-stream coverage"}
|
||||
tape.build_resolved(db)
|
||||
sharps = ml.screen_asof(db, lo)
|
||||
if not sharps:
|
||||
return {"skipped": "no screened wallets as-of day"}
|
||||
leans = ml.day_leans(db, lo, hi, sharps)
|
||||
pays = payouts_for(db, [t["a"] for t in leans])
|
||||
row = {"screened": len(sharps), "leans": len(leans)}
|
||||
arms = {"follow_small": ("follow", lambda u: u < 500),
|
||||
"mid_report": ("follow", lambda u: 500 <= u < 2000),
|
||||
"fade_whale": ("fade", lambda u: u >= 2000)}
|
||||
for name, (direction, sel) in arms.items():
|
||||
n = pend = wins = 0
|
||||
pnl = 0.0
|
||||
for t in leans:
|
||||
if not sel(t["lean_usd"]):
|
||||
continue
|
||||
p = pays.get(t["a"])
|
||||
if p is None:
|
||||
pend += 1
|
||||
continue
|
||||
if p == 0.5:
|
||||
continue
|
||||
lean_pay = p if t["side"] > 0 else 1 - p
|
||||
px, pay = ((t["lean_px"], lean_pay) if direction == "follow"
|
||||
else (1 - t["lean_px"], 1 - lean_pay))
|
||||
if not (0.05 <= px <= 0.95):
|
||||
continue
|
||||
n += 1
|
||||
pnl += 100.0 / px * (pay - px)
|
||||
wins += pay == 1.0
|
||||
row[name] = {"n": n, "pending": pend, "pnl": round(pnl, 2),
|
||||
"ev_per_lean": round(pnl / n, 2) if n else None,
|
||||
"hit": round(wins / n, 3) if n else None}
|
||||
return row
|
||||
|
||||
|
||||
def main():
|
||||
db = tape.connect()
|
||||
cal = json.load(open(os.path.join(HERE, "params", "sim_calibration.json")))
|
||||
@@ -248,6 +298,16 @@ def main():
|
||||
print(f"sub5c {d}: trig {r3['triggers']} "
|
||||
f"worst {r3['worst'].get('ev_per_fill')} "
|
||||
f"({r3['worst']['fills']} fills, {r3['worst']['pending']} pend)")
|
||||
r5 = score_lean(db, d)
|
||||
fh.write(json.dumps({"study": "lean", "day": d,
|
||||
"computed_at": now, **r5},
|
||||
default=float) + "\n")
|
||||
print(f"lean {d}: " + (r5.get("skipped") or
|
||||
f"{r5['leans']} leans · follow_small "
|
||||
f"{r5['follow_small'].get('ev_per_lean')} "
|
||||
f"({r5['follow_small']['n']}n) · fade_whale "
|
||||
f"{r5['fade_whale'].get('ev_per_lean')} "
|
||||
f"({r5['fade_whale']['n']}n)"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
+47
-35
@@ -17,6 +17,7 @@ FROZEN v0 params (declared before the run, not tuned after):
|
||||
price lean-side last print in [0.05, 0.95] at trigger
|
||||
score $100 at trigger print -> chain payout; follow-EV and fade-EV
|
||||
Kill bar: BOTH directions EV <= 0 at n>=100 leans."""
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
@@ -63,6 +64,43 @@ def screen_asof(db, t_cut):
|
||||
return out
|
||||
|
||||
|
||||
def day_leans(db, lo, hi, sharps):
|
||||
"""First lean crossings for screened wallets in [lo,hi) — the frozen
|
||||
trigger (used by the exploration AND forward.py's nightly scoring)."""
|
||||
rows = db.execute("""
|
||||
SELECT lower(json_extract_string(payload,'$.proxyWallet')) w,
|
||||
json_extract_string(payload,'$.asset') a,
|
||||
json_extract_string(payload,'$.side') s,
|
||||
cast(json_extract(payload,'$.price') AS DOUBLE) p,
|
||||
cast(json_extract(payload,'$.size') AS DOUBLE) z, ts
|
||||
FROM aux WHERE type='orders_matched' AND ts >= ? AND ts < ?
|
||||
ORDER BY ts""", [lo, hi]).fetchall()
|
||||
book, fired, out = {}, set(), []
|
||||
for w, a, s_, p, z, ts in rows:
|
||||
if w not in sharps or (w, a) in fired:
|
||||
continue
|
||||
st = book.setdefault((w, a), [0.0, 0.0])
|
||||
st[0] += z if s_ == "BUY" else -z
|
||||
st[1] += z
|
||||
net, gross = st
|
||||
if gross < 1e-9:
|
||||
continue
|
||||
px = db.execute("""SELECT price FROM trades WHERE asset=?
|
||||
AND ts<=? ORDER BY ts DESC LIMIT 1""", [a, ts]).fetchone()
|
||||
if px is None:
|
||||
continue
|
||||
px = float(px[0])
|
||||
lean_px = px if net > 0 else 1 - px
|
||||
if (abs(net) * px >= LEAN_USD and abs(net) / gross >= NET_GROSS
|
||||
and BAND[0] <= lean_px <= BAND[1]):
|
||||
fired.add((w, a))
|
||||
out.append({"w": w, "a": a, "ts": ts,
|
||||
"side": 1 if net > 0 else -1,
|
||||
"lean_usd": abs(net) * px,
|
||||
"px": px, "lean_px": lean_px})
|
||||
return out
|
||||
|
||||
|
||||
def main():
|
||||
db = tape.connect()
|
||||
t_lo, t_hi = db.execute(
|
||||
@@ -79,43 +117,17 @@ def main():
|
||||
if not sharps:
|
||||
print(f"{d_str}: 0 screened wallets", flush=True)
|
||||
continue
|
||||
rows = db.execute("""
|
||||
SELECT lower(json_extract_string(payload,'$.proxyWallet')) w,
|
||||
json_extract_string(payload,'$.asset') a,
|
||||
json_extract_string(payload,'$.side') s,
|
||||
cast(json_extract(payload,'$.price') AS DOUBLE) p,
|
||||
cast(json_extract(payload,'$.size') AS DOUBLE) z, ts
|
||||
FROM aux WHERE type='orders_matched' AND ts >= ? AND ts < ?
|
||||
ORDER BY ts""", [lo, hi]).fetchall()
|
||||
book = {} # (w,a) -> [net, gross, vwap$]
|
||||
fired = set()
|
||||
n_day = 0
|
||||
for w, a, s, p, z, ts in rows:
|
||||
if w not in sharps or (w, a) in fired:
|
||||
continue
|
||||
st = book.setdefault((w, a), [0.0, 0.0])
|
||||
st[0] += z if s == "BUY" else -z
|
||||
st[1] += z
|
||||
net, gross = st
|
||||
if gross < 1e-9:
|
||||
continue
|
||||
px = db.execute("""SELECT price FROM trades WHERE asset=?
|
||||
AND ts<=? ORDER BY ts DESC LIMIT 1""", [a, ts]).fetchone()
|
||||
if px is None:
|
||||
continue
|
||||
px = float(px[0])
|
||||
lean_px = px if net > 0 else 1 - px # lean-side price
|
||||
if (abs(net) * px >= LEAN_USD
|
||||
and abs(net) / gross >= NET_GROSS
|
||||
and BAND[0] <= lean_px <= BAND[1]):
|
||||
fired.add((w, a))
|
||||
n_day += 1
|
||||
triggers.append({"w": w, "a": a, "ts": ts, "day": d_str,
|
||||
"side": 1 if net > 0 else -1,
|
||||
"lean_usd": abs(net) * px,
|
||||
"px": px, "lean_px": lean_px})
|
||||
found = day_leans(db, lo, hi, sharps)
|
||||
for t in found:
|
||||
t["day"] = d_str
|
||||
triggers.extend(found)
|
||||
n_day = len(found)
|
||||
print(f"{d_str}: {len(sharps)} screened · {n_day} leans", flush=True)
|
||||
print(f"total leans: {len(triggers)}", flush=True)
|
||||
import json as _json
|
||||
_json.dump(triggers, open(os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
".maker_lean_triggers.json"), "w"))
|
||||
pays = fwd.payouts_for(db, [t["a"] for t in triggers])
|
||||
graded = [(t, pays.get(t["a"])) for t in triggers]
|
||||
graded = [(t, p) for t, p in graded if p is not None and p != 0.5]
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"frozen_at": "2026-07-23 21:55 UTC",
|
||||
"study": "C — maker inventory-lean (follow absorbed flow)",
|
||||
"screen": {"source": "orders_matched maker fills, as-of day start (strictly prior tape)",
|
||||
"min_z": 2.5, "min_bets": 6, "pnl_positive": true},
|
||||
"trigger": {"lean_usd_min": 150.0, "net_gross_min": 0.6,
|
||||
"first_crossing_per_wallet_asset_day": true,
|
||||
"lean_px_band": [0.05, 0.95]},
|
||||
"arms": {
|
||||
"follow_small": {"role": "VERDICT", "range_usd": [150, 500], "direction": "follow",
|
||||
"pass": "pooled forward EV >= +$2/lean AND hit >= 0.56 at n >= 1500 across >= 5 forward days",
|
||||
"kill": "pooled forward EV <= 0 at n >= 1000"},
|
||||
"mid_report": {"role": "report-only", "range_usd": [500, 2000], "direction": "follow"},
|
||||
"fade_whale": {"role": "report-only — FAILED pre-declared concentration gate 2026-07-23",
|
||||
"range_usd": [2000, null], "direction": "fade",
|
||||
"gate_result": "top-event share 32% (>30% line); top-5 events +$7,799 vs +$5,911 total (tail net-negative); 87/224 events positive"}
|
||||
},
|
||||
"scoring": "last-print entry (STATED OPTIMISM) -> chain truth via payouts_for; nightly rows study='lean' in forward_ledger.jsonl (forward.score_lean)",
|
||||
"graduation": "PASS graduates to a real-execution paper arm (honest instrument), never directly to money",
|
||||
"exploration": "research/maker_lean.py walk-forward 07-21..23: follow_small +$2.90-4.39/lean, 59% hit, positive all 3 days; concentration follow 14% top-event / 869 events"
|
||||
}
|
||||
Reference in New Issue
Block a user