mirror of
https://github.com/jaxperro/winning-wallet-finder.git
synced 2026-08-03 11:17:47 +00:00
1cbe1a67b9
Swap the flat $200 conviction cutoff for a per-wallet percentile (top 20% of each wallet's own stake sizes) everywhere it was used: - cache.py: canonical CONV_PCTILE=0.80 + conv_cutoff() helper (matches the dashboard's pctl: filter >0, sort, linear interp) - conviction_scan.py: per-wallet quantile_cont(size,0.8) in SQL, was `size >= 200` - validate_timing.py, pnl_focused.py: use cache.conv_cutoff Rationale + validation: p80 reproduces flat-$200's win-rate lift on the sharps while adapting to scale (a whale's $200 isn't conviction, a minnow's is). Re-running the pipeline under p80: scan finds 218 profile wallets (was 69), forward 62/83 profitable (p~0), +16% pooled ROI — edge persists out-of-sample. Regenerated conviction_wallets.json / watch_sharps.json; docs updated. skill.py/strategy.py/insider.py untouched (score over all bets / size as copyability heuristic only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
69 lines
2.6 KiB
Python
69 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Does a FOCUSED copy strategy clear where the broad 10-wallet basket didn't?
|
|
|
|
Same $1000 capital-constrained engine + missed-trade accounting (pnl_basket.sim),
|
|
but on narrower signal sets: fewer wallets, and/or only the wallet's higher-
|
|
conviction (larger-stake) bets — so $1000 isn't spread across 1,210 markets.
|
|
"""
|
|
|
|
import time
|
|
import cache
|
|
import pnl_basket as pb
|
|
|
|
JUN1 = time.mktime(time.strptime("2026-06-01", "%Y-%m-%d"))
|
|
E8 = "0xe8ca3f758c93f44f3ec210542ab78afb7c0bcccb"
|
|
A0 = "0x0a7aaf83341b52df34e8ffef52aa295538d6df1b"
|
|
|
|
|
|
def gather(wallets, conviction=False):
|
|
"""One signal per market. conviction=True filters to each wallet's high-
|
|
conviction bets — the top 20% of its own stake sizes (p80) — instead of a flat
|
|
dollar cutoff; in that mode we only use resolved bets (open ones have no known
|
|
stake to filter on)."""
|
|
pos = {}
|
|
for w in wallets:
|
|
ent = cache.get_entries(w)
|
|
bets = cache.get_bets(w)
|
|
resolved = {b["cond"]: b for b in bets}
|
|
cut = cache.conv_cutoff(b["size"] for b in bets) if conviction else None
|
|
for cond, ets in ent.items():
|
|
if ets < JUN1:
|
|
continue
|
|
b = resolved.get(cond)
|
|
if b:
|
|
if cut is not None and (b["size"] or 0) < cut:
|
|
continue
|
|
rec = dict(ets=ets, p=max(0.001, min(0.999, b["p"])),
|
|
won=b["won"], res_t=b["res_t"])
|
|
else:
|
|
if cut is not None:
|
|
continue
|
|
rec = dict(ets=ets, p=None, won=None, res_t=None)
|
|
if cond not in pos or ets < pos[cond]["ets"]:
|
|
pos[cond] = rec
|
|
return sorted(pos.values(), key=lambda r: r["ets"])
|
|
|
|
|
|
def run(label, wallets, conviction=False):
|
|
ev = gather(wallets, conviction)
|
|
res = sum(1 for e in ev if e["res_t"] is not None)
|
|
print(f"\n### {label} — {len(ev)} markets ({res} resolved)")
|
|
h = f"{'stake':>6}{'entered':>8}{'missed':>7}{'open':>5}{'realized':>11}{'equity':>9}"
|
|
print(h)
|
|
for s in (50, 100, 200):
|
|
r = pb.sim(ev, s)
|
|
print(f"${s:>4}{r['entered']:>8}{r['missed']:>7}{r['open_left']:>5}"
|
|
f"{r['realized']:>+10,.0f}{r['equity']:>9,.0f}")
|
|
|
|
|
|
def main():
|
|
run("0xe8 only — all June+ entries", [E8])
|
|
run("0xe8 only — conviction (top 20% by stake)", [E8], conviction=True)
|
|
run("0xe8 + 0x0a — all June+ entries", [E8, A0])
|
|
run("0xe8 + 0x0a — conviction (top 20% by stake)", [E8, A0], conviction=True)
|
|
print("\nrealized = settled-bet P&L · equity = $1000 + realized (open at cost)")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|