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/.surge*.pull.*
|
||||||
research/.oracle*.pull.*
|
research/.oracle*.pull.*
|
||||||
research/replay_out/
|
research/replay_out/
|
||||||
|
research/.maker_lean_triggers.json
|
||||||
|
|||||||
@@ -180,6 +180,56 @@ def score_oracle(db, P, d, hold_s):
|
|||||||
return row
|
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():
|
def main():
|
||||||
db = tape.connect()
|
db = tape.connect()
|
||||||
cal = json.load(open(os.path.join(HERE, "params", "sim_calibration.json")))
|
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']} "
|
print(f"sub5c {d}: trig {r3['triggers']} "
|
||||||
f"worst {r3['worst'].get('ev_per_fill')} "
|
f"worst {r3['worst'].get('ev_per_fill')} "
|
||||||
f"({r3['worst']['fills']} fills, {r3['worst']['pending']} pend)")
|
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__":
|
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
|
price lean-side last print in [0.05, 0.95] at trigger
|
||||||
score $100 at trigger print -> chain payout; follow-EV and fade-EV
|
score $100 at trigger print -> chain payout; follow-EV and fade-EV
|
||||||
Kill bar: BOTH directions EV <= 0 at n>=100 leans."""
|
Kill bar: BOTH directions EV <= 0 at n>=100 leans."""
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@@ -63,6 +64,43 @@ def screen_asof(db, t_cut):
|
|||||||
return out
|
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():
|
def main():
|
||||||
db = tape.connect()
|
db = tape.connect()
|
||||||
t_lo, t_hi = db.execute(
|
t_lo, t_hi = db.execute(
|
||||||
@@ -79,43 +117,17 @@ def main():
|
|||||||
if not sharps:
|
if not sharps:
|
||||||
print(f"{d_str}: 0 screened wallets", flush=True)
|
print(f"{d_str}: 0 screened wallets", flush=True)
|
||||||
continue
|
continue
|
||||||
rows = db.execute("""
|
found = day_leans(db, lo, hi, sharps)
|
||||||
SELECT lower(json_extract_string(payload,'$.proxyWallet')) w,
|
for t in found:
|
||||||
json_extract_string(payload,'$.asset') a,
|
t["day"] = d_str
|
||||||
json_extract_string(payload,'$.side') s,
|
triggers.extend(found)
|
||||||
cast(json_extract(payload,'$.price') AS DOUBLE) p,
|
n_day = len(found)
|
||||||
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})
|
|
||||||
print(f"{d_str}: {len(sharps)} screened · {n_day} leans", flush=True)
|
print(f"{d_str}: {len(sharps)} screened · {n_day} leans", flush=True)
|
||||||
print(f"total leans: {len(triggers)}", 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])
|
pays = fwd.payouts_for(db, [t["a"] for t in triggers])
|
||||||
graded = [(t, pays.get(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]
|
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