Files
winning-wallet-finder/oos.py
T
jaxperro cc44667b7e cache schema v2: token-keyed upsert archive, provenance, raw prices, honest failures
- bets table gains asset (token id = position identity), src/ts (endpoint
  provenance + close time), resolved (False = early-sold in an unended market;
  won is a curPrice mark). Auto-migrates v1 in place (~8s, 3,697 exact dupes
  merged); legacy rows carry NULLs until their wallet refreshes.
- refresh is now an upsert by token instead of a wallet wipe: rows sliding out
  of the rolling pull window survive, so per-wallet history accumulates into a
  permanent archive. Same-asset rows from both endpoints (partially-closed
  positions) dedupe to the larger-stake row - kills the two-endpoint
  double-count class (~35k suspect pairs found in the audit).
- p stored raw (0 = avgPrice missing), clamped on read by get_bets, so missing
  prices stay distinguishable from real 0.1c longshots; insider CLI + oos clamp
  their own direct use.
- resolved_bets(strict=True): a failed page raises instead of returning a
  silently truncated history; get_bets no longer caches or marks failed pulls
  (pre-v2 an API error cached the wallet as empty-and-fresh for 14 days -
  Kruto2027 was a live victim of this last night).

Verified: migration 18,289,320 -> 18,285,623 rows; forced refreshes of two
sharps show 0 same-asset dups, 0 legacy/new mixing, clamped reads, conviction
stats intact (Kruto conv win 73%).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 09:26:41 -04:00

156 lines
5.6 KiB
Python
Raw 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
"""Out-of-sample test of the copy-the-edge-wallets strategy.
SELECT wallets using only resolved bets in [Feb 1 - Apr 30] (z-score), with NO
knowledge of May-June. Then COPY those wallets' entries forward from May 30,
compounding. If the forward return is strong, the edge is real; if it collapses,
the in-sample +545% was selection theater.
"""
import math
import time
from collections import defaultdict
import smart_money as sm
from insider import resolved_bets, norm_sf
from copyback import entries_after, outcomes, _parse, BET_K, START_BANKROLL
SEL_T0 = _parse("2026-02-01") # selection window start (resolution time)
SEL_T1 = _parse("2026-04-30") # selection window end — nothing after this is seen
TEST_START = _parse("2026-05-30") # copy entries on/after this
Z_PICK = 4.0 # insider-grade cut, judged AS OF Apr 30
MIN_BETS = 15
def score_pre(wallet):
"""z-score over resolved bets in the selection window only."""
bets = [b for b in resolved_bets(wallet, SEL_T0 - 10 * 86400)
if SEL_T0 <= b["res_t"] <= SEL_T1]
if len(bets) < MIN_BETS:
return None
for b in bets: # v2 returns raw p — clamp for the z math
b["p"] = max(0.001, min(0.999, b["p"] or 0))
wins = sum(1 for b in bets if b["won"])
exp = sum(b["p"] for b in bets)
var = sum(b["p"] * (1 - b["p"]) for b in bets) or 1e-9
z = (wins - exp) / math.sqrt(var)
return {"wallet": wallet, "n": len(bets), "wins": wins, "z": z, "pval": norm_sf(z)}
def candidate_pool():
import csv
seen = {}
try:
for r in csv.DictReader(open("huntwide.csv")):
seen[r["wallet"]] = r["username"]
except FileNotFoundError:
pass
return seen
def main():
from concurrent.futures import ThreadPoolExecutor, as_completed
pool = candidate_pool()
print(f"candidate pool: {len(pool)} wallets · scoring on [Feb1Apr30] only...", flush=True)
selected = []
with ThreadPoolExecutor(max_workers=12) as ex:
futs = {ex.submit(score_pre, w): w for w in pool}
done = 0
for f in as_completed(futs):
done += 1
try:
r = f.result()
except Exception:
r = None
if r and r["z"] >= Z_PICK:
r["name"] = pool[r["wallet"]]
selected.append(r)
if done % 50 == 0:
print(f" {done}/{len(pool)}", flush=True)
selected.sort(key=lambda r: r["z"], reverse=True)
print(f"\nINSIDER-GRADE AS OF APR 30 (z>={Z_PICK}): {len(selected)} wallets")
for r in selected:
print(f" {r['name'][:18]:18} z={r['z']:>4.1f} p={r['pval']:.1e} "
f"{r['wins']}/{r['n']} (pre-period)")
if not selected:
print("\nNo wallets were insider-grade as of Apr 30 — the edge wallets are "
"too new to have a pre-period track record. That itself is the answer.")
return
# forward copy from May 30, z(pre)-weighted, compounding
tot_z = sum(r["z"] for r in selected)
weights = {r["wallet"]: r["z"] / tot_z for r in selected}
names = {r["wallet"]: r["name"] for r in selected}
print(f"\ncopying {len(selected)} wallets forward from 2026-05-30 "
f"(z-pre weighted, compounding)...", flush=True)
bets = []
now = time.time()
for r in selected:
w = r["wallet"]
ent = entries_after(w, TEST_START)
outc = outcomes(w)
for a, (price, ts, title) in ent.items():
if a not in outc or not (0 < price < 1):
continue
cur, end = outc[a]
bets.append({"w": w, "ts": ts, "price": price, "mark": cur,
"res_ts": end or now, "resolved": bool(end and end < now)})
print(f"forward copied bets: {len(bets)}", flush=True)
events = []
for i, b in enumerate(bets):
events.append((b["ts"], 0, i))
if b["resolved"]:
events.append((b["res_ts"], 1, i))
events.sort()
cash = START_BANKROLL
open_cost = 0.0
posn = {}
wins = losses = 0
realized = 0.0
bw = defaultdict(float)
for ts, kind, i in events:
b = bets[i]
if kind == 0:
bankroll = cash + open_cost
stake = min(weights[b["w"]] * BET_K * bankroll, cash)
if stake < 1:
continue
posn[i] = (stake / b["price"], stake)
cash -= stake
open_cost += stake
else:
if i not in posn:
continue
shares, stake = posn.pop(i)
payout = shares * (1 if b["mark"] >= 0.5 else 0)
cash += payout
open_cost -= stake
realized += payout - stake
bw[names[b["w"]]] += payout - stake
wins += b["mark"] >= 0.5
losses += b["mark"] < 0.5
open_val = sum(sh * bets[i]["mark"] for i, (sh, st) in posn.items())
equity = cash + open_val
print(f"\n{'='*64}")
print(f" OUT-OF-SAMPLE forward result (selection knew nothing past Apr 30)")
print(f" resolved: {wins+losses} ({wins}W/{losses}L"
f"{f' · {wins/(wins+losses)*100:.0f}%' if wins+losses else ''}) "
f"· open: {len(posn)}")
print(f" realized P&L: ${realized:+,.2f} ({realized/START_BANKROLL*100:+.1f}%)")
print(f" unrealized: ${open_val-open_cost:+,.2f}")
print(f" ── ending equity ${equity:,.2f} -> {(equity/START_BANKROLL-1)*100:+.1f}% "
f"on $1,000 over {(now-TEST_START)/86400:.0f}d")
print(f"{'='*64}")
for n in sorted(bw, key=lambda k: bw[k], reverse=True):
print(f" {n[:18]:18} {bw[n]:+,.2f}")
if __name__ == "__main__":
main()