mirror of
https://github.com/jaxperro/winning-wallet-finder.git
synced 2026-07-27 15:57:47 +00:00
e6287c788d
2,191 episodes (400 highest-volume event/outcome groups, name-matched semantics only): follower drift +4.12c mean in leader direction at +5m (43% >+2c vs 17% adverse; p50=0 — thin siblings often don't print). Tradable leg chain-true: n=2,028 · EV +$9.73/$100 buying the follower at its last print in the leader's direction. STATED OPTIMISM: stale-print entry (the T4 lesson — prints are not books); resting asks may have repriced without printing. Stage-2 = execution realism (live book reads or a paper scanner leg). Theme with T6: edge lives where repricing is SLOW — the far side of the requote wall. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
125 lines
5.1 KiB
Python
125 lines
5.1 KiB
Python
#!/usr/bin/env python3
|
||
"""T9 EXPLORATORY (2026-07-23) — same-event lead-lag: when an event's most
|
||
-traded market moves hard in-play, do sibling markets carrying THE SAME
|
||
OUTCOME NAME reprice with a fillable lag?
|
||
|
||
Semantic mapping problem solved narrowly: direction is only claimed where
|
||
the follower has an outcome with the exact same (lowercased) name as the
|
||
leader's moved outcome (team/player name) — moneyline vs map/set/half
|
||
winner vs series markets. No claim on O/Us or unrelated props.
|
||
|
||
v0 method: cond→event + cond→{outcome→asset} from orders_matched. Leader
|
||
per event = most prints. Burst = leader outcome's print moving >= 10c
|
||
within 120s (in-play), cooldown 600s/event. Follower read at burst t:
|
||
last print p0; drift = p(t+300s) − p0 in the leader-move direction;
|
||
tradable leg = buy follower at p0, grade to chain (payouts_for).
|
||
Kill: drift <= fees (~2c) at n>=300 episodes, or chain EV <= 0."""
|
||
import sys
|
||
import time
|
||
|
||
sys.path.insert(0, "/Users/jaxmakielski/polymarket-smart-money/research")
|
||
import tape # noqa: E402
|
||
import forward as fwd # noqa: E402
|
||
|
||
MOVE_C = 0.10
|
||
MOVE_WIN = 120
|
||
DRIFT_WIN = 300
|
||
COOLDOWN = 600
|
||
BAND = (0.05, 0.95)
|
||
|
||
|
||
def main():
|
||
db = tape.connect()
|
||
tape.build_resolved(db)
|
||
print("building event/outcome maps…", flush=True)
|
||
db.execute("""
|
||
CREATE TEMP TABLE om AS
|
||
SELECT json_extract_string(payload,'$.eventSlug') ev,
|
||
json_extract_string(payload,'$.conditionId') cond,
|
||
lower(json_extract_string(payload,'$.outcome')) outc,
|
||
json_extract_string(payload,'$.asset') asset,
|
||
count(*) n
|
||
FROM aux WHERE type='orders_matched'
|
||
AND json_extract_string(payload,'$.eventSlug') IS NOT NULL
|
||
GROUP BY 1,2,3,4""")
|
||
# events with >=2 conds sharing an outcome name (the mappable set)
|
||
pairs = db.execute("""
|
||
WITH x AS (SELECT ev, outc, count(DISTINCT cond) nc, sum(n) vol
|
||
FROM om WHERE outc NOT IN ('yes','no','over','under','')
|
||
GROUP BY 1,2 HAVING count(DISTINCT cond) >= 2)
|
||
SELECT ev, outc FROM x ORDER BY vol DESC LIMIT 400""").fetchall()
|
||
print(f"mappable (event, outcome) groups: {len(pairs)}", flush=True)
|
||
episodes = []
|
||
for gi, (ev, outc) in enumerate(pairs):
|
||
toks = db.execute("""SELECT cond, asset, n FROM om
|
||
WHERE ev=? AND outc=?""", [ev, outc]).fetchall()
|
||
if len(toks) < 2:
|
||
continue
|
||
toks.sort(key=lambda r: -r[2])
|
||
lead_asset = toks[0][1]
|
||
followers = [r[1] for r in toks[1:3]] # top-2 followers
|
||
prints = db.execute("""SELECT ts, price::DOUBLE FROM trades
|
||
WHERE asset=? ORDER BY ts""", [lead_asset]).fetchall()
|
||
last_ep = 0.0
|
||
for i in range(1, len(prints)):
|
||
ts, p = prints[i]
|
||
if ts - last_ep < COOLDOWN:
|
||
continue
|
||
j = i - 1
|
||
while j >= 0 and ts - prints[j][0] <= MOVE_WIN:
|
||
j -= 1
|
||
if j < 0 or j == i - 1:
|
||
base = prints[max(j, 0)][1]
|
||
else:
|
||
base = prints[j + 1][1]
|
||
mv = p - base
|
||
if abs(mv) < MOVE_C:
|
||
continue
|
||
last_ep = ts
|
||
for fa in followers:
|
||
r0 = db.execute("""SELECT price::DOUBLE FROM trades
|
||
WHERE asset=? AND ts<=? ORDER BY ts DESC LIMIT 1""",
|
||
[fa, ts]).fetchone()
|
||
r1 = db.execute("""SELECT price::DOUBLE FROM trades
|
||
WHERE asset=? AND ts<=? ORDER BY ts DESC LIMIT 1""",
|
||
[fa, ts + DRIFT_WIN]).fetchone()
|
||
if not r0 or not r1:
|
||
continue
|
||
p0, p1 = r0[0], r1[0]
|
||
if not (BAND[0] <= p0 <= BAND[1]):
|
||
continue
|
||
sgn = 1 if mv > 0 else -1
|
||
episodes.append({"ev": ev, "a": fa, "ts": ts, "sgn": sgn,
|
||
"p0": p0, "drift": (p1 - p0) * sgn})
|
||
if (gi + 1) % 100 == 0:
|
||
print(f" … {gi+1}/{len(pairs)} groups · "
|
||
f"{len(episodes)} episodes", flush=True)
|
||
print(f"episodes: {len(episodes)}", flush=True)
|
||
if not episodes:
|
||
return
|
||
d = sorted(e["drift"] for e in episodes)
|
||
n = len(d)
|
||
print(f"follower drift(+{DRIFT_WIN}s, leader direction): "
|
||
f"mean {sum(d)/n*100:+.2f}c · p50 {d[n//2]*100:+.2f}c · "
|
||
f"frac>+2c {sum(x > 0.02 for x in d)/n:.0%} · "
|
||
f"frac<-2c {sum(x < -0.02 for x in d)/n:.0%}", flush=True)
|
||
pays = fwd.payouts_for(db, [e["a"] for e in episodes])
|
||
graded = []
|
||
for e in episodes:
|
||
p = pays.get(e["a"])
|
||
if p is None or p == 0.5:
|
||
continue
|
||
side_px = e["p0"] if e["sgn"] > 0 else 1 - e["p0"]
|
||
side_pay = p if e["sgn"] > 0 else 1 - p
|
||
if not (BAND[0] <= side_px <= BAND[1]):
|
||
continue
|
||
graded.append(100.0 / side_px * (side_pay - side_px))
|
||
if graded:
|
||
print(f"tradable leg (buy follower in leader direction, chain): "
|
||
f"n={len(graded)} · EV/$100 "
|
||
f"{sum(graded)/len(graded):+.2f}", flush=True)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|