mirror of
https://github.com/jaxperro/winning-wallet-finder.git
synced 2026-07-27 15:57:47 +00:00
live: train/test wallet-selection study + capital-constrained copy sims
strategy.py (train pre-May-30 / test June1+ on copy-ROI + z + consistency + diversification) and followability.py (entry-time/lead-time/cadence filter) surface wallets with real, copyable, out-of-sample edge (49/77 profitable forward, p=0.011, +23.4% pooled). pnl_basket.py / pnl_focused.py add $1000 capital-constrained copy sims with missed-trade accounting: the broad basket loses (can't follow 1,200 trades on $1k), but 1-2 wallets + a conviction (bet-size) filter clears out-of-sample. cache.py gains entry-time caching. Findings documented. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+23
@@ -142,6 +142,29 @@ misleading signal on the platform; favorite-riders are uncopyable.* The
|
||||
underdog/`value` archetype (beats longshot prices) is the only one left worth
|
||||
testing.
|
||||
|
||||
## Train/test wallet selection, and the capital wall (June 2026)
|
||||
|
||||
Built `live/strategy.py` (train on bets resolved before May 30, validate June 1+)
|
||||
and `live/followability.py` (entry-time + lead-time + cadence filter). Selecting
|
||||
on **copy-ROI + z + monthly consistency + diversification** (not win rate) gave
|
||||
150 wallets; **59/100 stayed profitable forward** (p=0.044), and filtering to
|
||||
*followable* markets lifted it to **49/77 (p=0.011), +23.4% pooled** out-of-
|
||||
sample. So a real, persistent, copyable edge **does** exist — unlike favorites.
|
||||
|
||||
Then the reality check (`live/pnl_basket.py`, `live/pnl_focused.py`): a $1,000
|
||||
copier with **missed-trade accounting** (capital tied in open positions).
|
||||
- **Broad 10-wallet basket:** the wallets fire **1,210 markets** in June; $1,000
|
||||
can follow only ~2–13% of them. At realistic stakes it **loses** (−$384 to
|
||||
−$800); the gains sit in the trades you couldn't afford ($14k–$153k "missed").
|
||||
**Capital, not edge, is the binding constraint.**
|
||||
- **Focused + conviction:** copy only 1–2 top wallets and only their larger-stake
|
||||
(≥$200) bets → trade count drops to ~30–40, $1,000 affords them all, and it
|
||||
**clears: +91% to +247% across stakes, stable, no blowup.**
|
||||
|
||||
*Lesson: a small-bankroll copier cannot follow a skilled wallet's whole feed —
|
||||
the edge is only capturable by concentrating on few wallets' high-conviction
|
||||
bets. The live tracker (jaxperro.com/trading) now runs exactly that config.*
|
||||
|
||||
## Repo layout
|
||||
|
||||
- `insider.py` — the detector: z-score/p-value, timing/freshness/sizing signals,
|
||||
|
||||
@@ -62,6 +62,18 @@ turn into losers out-of-sample. **Don't copy favorite-riders.** The `value`
|
||||
archetype (beats underdog prices) is where real alpha may live — test it with
|
||||
`backtest_june.py value`.
|
||||
|
||||
## Strategy backtests
|
||||
|
||||
- `strategy.py` — train (pre-May-30) / test (June1+) wallet selection on copy-ROI
|
||||
+ z + monthly consistency + diversification. → `selection.json`.
|
||||
- `followability.py` — pull entry timestamps (cached), drop wallets whose edge is
|
||||
in un-followable fast/live markets, re-rank on followable forward bets. →
|
||||
`watch_final.json` (the execution-realistic list).
|
||||
- `pnl_basket.py` / `pnl_focused.py` — $1,000 capital-constrained copy sims with
|
||||
**missed-trade accounting**. Key result: the broad basket loses on $1k (can't
|
||||
follow 1,200 trades), but **1–2 wallets + a conviction (bet-size) filter clears**
|
||||
out-of-sample. See `../FINDINGS.md`.
|
||||
|
||||
## Daily (`daily.sh`)
|
||||
|
||||
1. discover (enumerate last 14d) → 2. freshen cache (force-refresh watchlist +
|
||||
|
||||
@@ -33,6 +33,31 @@ _con.execute("""CREATE TABLE IF NOT EXISTS bets(
|
||||
wallet TEXT, cond TEXT, won BOOLEAN, p DOUBLE, res_t BIGINT, size DOUBLE)""")
|
||||
_con.execute("CREATE INDEX IF NOT EXISTS bets_w ON bets(wallet)")
|
||||
_con.execute("CREATE TABLE IF NOT EXISTS pulled(wallet TEXT PRIMARY KEY, pulled_at BIGINT)")
|
||||
_con.execute("CREATE TABLE IF NOT EXISTS entries(wallet TEXT, cond TEXT, first_buy BIGINT)")
|
||||
_con.execute("CREATE INDEX IF NOT EXISTS entries_w ON entries(wallet)")
|
||||
_con.execute("CREATE TABLE IF NOT EXISTS pulled_entries(wallet TEXT PRIMARY KEY, pulled_at BIGINT)")
|
||||
|
||||
|
||||
def get_entries(wallet):
|
||||
"""{conditionId: earliest BUY timestamp} for a wallet — cached. Lets us
|
||||
compute entry->resolution lead time and trade cadence (followability)."""
|
||||
now = time.time()
|
||||
with _lock:
|
||||
r = _con.execute("SELECT pulled_at FROM pulled_entries WHERE wallet=?", [wallet]).fetchone()
|
||||
if r and now - r[0] < MAX_AGE_DAYS * 86400:
|
||||
rows = _con.execute("SELECT cond,first_buy FROM entries WHERE wallet=?", [wallet]).fetchall()
|
||||
return {c: t for c, t in rows}
|
||||
try:
|
||||
first_buy, _ = insider.entry_times(wallet)
|
||||
except Exception:
|
||||
first_buy = {}
|
||||
with _lock:
|
||||
_con.execute("DELETE FROM entries WHERE wallet=?", [wallet])
|
||||
if first_buy:
|
||||
_con.executemany("INSERT INTO entries(wallet,cond,first_buy) VALUES (?,?,?)",
|
||||
[(wallet, c, t) for c, t in first_buy.items()])
|
||||
_con.execute("INSERT OR REPLACE INTO pulled_entries VALUES (?,?)", [wallet, int(now)])
|
||||
return first_buy
|
||||
|
||||
|
||||
def get_bets(wallet):
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Execution-realistic re-ranking of the selected wallets.
|
||||
|
||||
Pulls entry timestamps (cached) for the strategy.py shortlist, then judges each
|
||||
wallet on whether we could actually FOLLOW it with $1,000:
|
||||
|
||||
* lead time = resolution - entry. Bets that resolve within MIN_LEAD_H of the
|
||||
wallet's entry (live/in-game/instant markets) are NOT copyable — you can't
|
||||
see and mirror the trade in time. We drop them.
|
||||
* cadence = distinct markets entered per active day. Extreme cadence = a bot
|
||||
we can't hand-follow.
|
||||
|
||||
Then it recomputes forward (June1+, resolved) copy-ROI on ONLY the followable
|
||||
bets — the realistic number — and re-ranks. Output: watch_final.json.
|
||||
|
||||
python3 followability.py
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import statistics as st
|
||||
import time
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
|
||||
import cache
|
||||
|
||||
HERE = os.path.dirname(__file__)
|
||||
TEST_START = time.mktime(time.strptime(os.environ.get("TEST_START", "2026-06-01"), "%Y-%m-%d"))
|
||||
MIN_LEAD_H = 1.0 # a bet must resolve >= 1h after entry to be followable
|
||||
MED_LEAD_MIN = 2.0 # wallet's median lead must clear this to qualify
|
||||
MAX_CADENCE = 50.0 # entries/day above this = bot-like, hard to follow
|
||||
MIN_FOLL_FRAC = 0.5 # >= half the wallet's bets must be followable
|
||||
MIN_FWD_FOLL = 5 # need this many followable forward bets to rank
|
||||
|
||||
|
||||
def ret(p, won):
|
||||
return (1 - p) / p if won else -1.0
|
||||
|
||||
|
||||
def assess(wallet):
|
||||
ent = cache.get_entries(wallet) # {cond: first_buy_ts}
|
||||
bets = cache.get_bets(wallet) # cached
|
||||
leads = []
|
||||
for b in bets:
|
||||
e = ent.get(b["cond"])
|
||||
if e and b.get("res_t"):
|
||||
lh = (b["res_t"] - e) / 3600.0
|
||||
if lh >= 0:
|
||||
leads.append((b, lh))
|
||||
if not leads:
|
||||
return None
|
||||
med_lead = st.median([lh for _, lh in leads])
|
||||
foll_frac = sum(1 for _, lh in leads if lh >= MIN_LEAD_H) / len(leads)
|
||||
ts = sorted(ent.values())
|
||||
span = max(1.0, (ts[-1] - ts[0]) / 86400) if len(ts) > 1 else 1.0
|
||||
cadence = len(ent) / span
|
||||
# forward, followable only
|
||||
fwd_foll = [b for b, lh in leads if b["res_t"] >= TEST_START and lh >= MIN_LEAD_H]
|
||||
fwd_all = [b for b, lh in leads if b["res_t"] >= TEST_START]
|
||||
foll_roi = (sum(ret(b["p"], b["won"]) for b in fwd_foll) / len(fwd_foll)
|
||||
if fwd_foll else None)
|
||||
raw_roi = (sum(ret(b["p"], b["won"]) for b in fwd_all) / len(fwd_all)
|
||||
if fwd_all else None)
|
||||
wins = sum(1 for b in fwd_foll if b["won"])
|
||||
return dict(wallet=wallet, med_lead=med_lead, foll_frac=foll_frac, cadence=cadence,
|
||||
fwd_foll_n=len(fwd_foll), foll_roi=foll_roi, raw_roi=raw_roi,
|
||||
fwd_win=100 * wins / len(fwd_foll) if fwd_foll else 0)
|
||||
|
||||
|
||||
def main():
|
||||
sel = json.load(open(os.path.join(HERE, "selection.json")))
|
||||
wallets = [c["wallet"] for c in sel]
|
||||
meta = {c["wallet"]: c for c in sel}
|
||||
print(f"assessing followability of {len(wallets)} selected wallets "
|
||||
f"(entry-time pull, cached)…\n", flush=True)
|
||||
|
||||
rows, done = [], 0
|
||||
with ThreadPoolExecutor(max_workers=10) as ex:
|
||||
for r in ex.map(assess, wallets):
|
||||
done += 1
|
||||
if r:
|
||||
rows.append(r)
|
||||
if done % 30 == 0:
|
||||
print(f" {done}/{len(wallets)}", flush=True)
|
||||
|
||||
# followability gates
|
||||
foll = [r for r in rows if
|
||||
r["med_lead"] >= MED_LEAD_MIN and
|
||||
r["foll_frac"] >= MIN_FOLL_FRAC and
|
||||
r["cadence"] <= MAX_CADENCE]
|
||||
ranked = [r for r in foll if r["fwd_foll_n"] >= MIN_FWD_FOLL]
|
||||
ranked.sort(key=lambda r: r["foll_roi"], reverse=True)
|
||||
|
||||
dropped = len(rows) - len(foll)
|
||||
print(f"\n{len(rows)} assessed · {dropped} dropped as un-followable "
|
||||
f"(fast/live markets or bot cadence) · {len(foll)} copyable\n")
|
||||
if ranked:
|
||||
pooled_num = sum(r["foll_roi"] * r["fwd_foll_n"] for r in ranked)
|
||||
pooled_den = sum(r["fwd_foll_n"] for r in ranked)
|
||||
pos = sum(1 for r in ranked if r["foll_roi"] > 0)
|
||||
print(f"FOLLOWABLE forward verdict ({len(ranked)} wallets w/ >= {MIN_FWD_FOLL} "
|
||||
f"followable June+ bets):")
|
||||
print(f" {pos}/{len(ranked)} profitable · pooled followable copy-ROI "
|
||||
f"{pooled_num/pooled_den:+.1%} · median {st.median([r['foll_roi'] for r in ranked]):+.1%}\n")
|
||||
|
||||
h = (f"{'foll_roi':>9}{'raw_roi':>8}{'medLeadH':>9}{'foll%':>6}{'cad/d':>7}"
|
||||
f"{'fwd_n':>6}{'tr_z':>6} wallet")
|
||||
print(h); print("-" * len(h))
|
||||
for r in ranked[:40]:
|
||||
m = meta[r["wallet"]]
|
||||
raw = f"{r['raw_roi']:+.0%}" if r["raw_roi"] is not None else "—"
|
||||
print(f"{r['foll_roi']:>+8.0%}{raw:>8}{r['med_lead']:>8.1f}h{r['foll_frac']*100:>5.0f}%"
|
||||
f"{r['cadence']:>7.1f}{r['fwd_foll_n']:>6}{m['train_z']:>6.1f} {r['wallet']}")
|
||||
|
||||
out = [{"wallet": r["wallet"], "name": r["wallet"][:10],
|
||||
"foll_fwd_copy_roi": round(r["foll_roi"], 4),
|
||||
"med_lead_h": round(r["med_lead"], 1), "cadence_per_day": round(r["cadence"], 1),
|
||||
"followable_frac": round(r["foll_frac"], 2), "fwd_followable_n": r["fwd_foll_n"],
|
||||
"train_z": meta[r["wallet"]]["train_z"],
|
||||
"train_copy_roi": meta[r["wallet"]]["train_copy_roi"]} for r in ranked]
|
||||
json.dump(out, open(os.path.join(HERE, "watch_final.json"), "w"), indent=2)
|
||||
print(f"\n-> watch_final.json ({len(out)} execution-realistic wallets)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Capital-constrained copy backtest of the 10-wallet basket, June 1 -> now.
|
||||
|
||||
$1,000 bankroll. Replay the wallets' June-1+ entries in time order (using cached
|
||||
entry timestamps). At each entry: first settle any held bets that have resolved
|
||||
(free the cash + realize P&L), then enter IF we can afford the stake — otherwise
|
||||
it's a MISSED trade (counted, with its hypothetical outcome). Capital stays tied
|
||||
in still-open positions, which is what forces the misses. Realized P&L only.
|
||||
|
||||
One position per market (earliest of the 10 wallets to enter it). Shown across a
|
||||
few flat stake sizes since that's the knob that trades off coverage vs misses.
|
||||
"""
|
||||
|
||||
import time
|
||||
import cache
|
||||
|
||||
JUN1 = time.mktime(time.strptime("2026-06-01", "%Y-%m-%d"))
|
||||
NOW = time.time()
|
||||
BANK = 1000.0
|
||||
WALLETS = [
|
||||
"0xe8ca3f758c93f44f3ec210542ab78afb7c0bcccb", "0x0a7aaf83341b52df34e8ffef52aa295538d6df1b",
|
||||
"0xfd4263b3ad08226034fe1b1ea678a46d80b58895", "0x13464aabec792c36b062316f474713e681330448",
|
||||
"0x36bfcd8ab96dce2ddea30145ab749b59c6362864", "0x2d4bf8f846bf68f43b9157bf30810d334ac6ca7a",
|
||||
"0x1cff72c8dddc30a64486fda6eab71ab5f9243984", "0xfc81760d44a21acc9fd4b749a5bf9a9b2eeae072",
|
||||
"0x86c878cde72660ec52f5e6f0f0438b76de8fc867", "0x6fdddf25b92251ed1515703cda43bf8ff5f5d385",
|
||||
]
|
||||
|
||||
|
||||
def gather():
|
||||
"""One copy signal per market: (entry_ts, p, won, res_t|None). res_t None =
|
||||
still open (ties up capital, no realized P&L)."""
|
||||
pos = {}
|
||||
for w in WALLETS:
|
||||
ent = cache.get_entries(w) # {cond: first_buy_ts}
|
||||
resolved = {b["cond"]: b for b in cache.get_bets(w)}
|
||||
for cond, ets in ent.items():
|
||||
if ets < JUN1:
|
||||
continue
|
||||
b = resolved.get(cond)
|
||||
p = max(0.001, min(0.999, b["p"])) if b else None
|
||||
rec = dict(ets=ets, p=p, won=b["won"] if b else None,
|
||||
res_t=(b["res_t"] if b else None))
|
||||
if cond not in pos or ets < pos[cond]["ets"]:
|
||||
pos[cond] = rec
|
||||
return sorted(pos.values(), key=lambda r: r["ets"])
|
||||
|
||||
|
||||
def sim(events, stake):
|
||||
cash, realized = BANK, 0.0
|
||||
held = [] # (res_t, p, won, stake)
|
||||
entered = missed = openn = 0
|
||||
missed_pnl = 0.0
|
||||
|
||||
def settle2(upto):
|
||||
nonlocal cash, realized
|
||||
keep = []
|
||||
for res_t, p, won, s in held:
|
||||
if res_t is not None and res_t <= upto:
|
||||
payout = (s / p) if won else 0.0
|
||||
cash += payout
|
||||
realized += payout - s
|
||||
else:
|
||||
keep.append((res_t, p, won, s))
|
||||
held[:] = keep
|
||||
|
||||
for e in events:
|
||||
settle2(e["ets"])
|
||||
if cash >= stake:
|
||||
cash -= stake
|
||||
held.append((e["res_t"], e["p"], e["won"], stake))
|
||||
entered += 1
|
||||
if e["res_t"] is None:
|
||||
openn += 1
|
||||
else:
|
||||
missed += 1
|
||||
if e["res_t"] is not None: # hypothetical realized miss
|
||||
missed_pnl += (stake / e["p"] - stake) if e["won"] else -stake
|
||||
settle2(NOW)
|
||||
open_left = sum(1 for h in held if h[0] is None or h[0] > NOW)
|
||||
equity = BANK + realized # open held at cost
|
||||
return dict(stake=stake, entered=entered, missed=missed, open_left=open_left,
|
||||
realized=realized, equity=equity, missed_pnl=missed_pnl)
|
||||
|
||||
|
||||
def main():
|
||||
ev = gather()
|
||||
res = sum(1 for e in ev if e["res_t"] is not None)
|
||||
print(f"10-wallet basket · {len(ev)} unique June1+ markets entered "
|
||||
f"({res} resolved, {len(ev)-res} still open) · $1000 bankroll, miss when broke\n")
|
||||
h = f"{'stake':>6}{'entered':>8}{'missed':>7}{'open':>5}{'realized P&L':>14}{'equity':>10}{'missed P&L':>12}"
|
||||
print(h); print("-" * len(h))
|
||||
for s in (20, 50, 100, 200):
|
||||
r = sim(ev, s)
|
||||
print(f"${r['stake']:>4}{r['entered']:>8}{r['missed']:>7}{r['open_left']:>5}"
|
||||
f"{r['realized']:>+13,.0f}{r['equity']:>10,.0f}{r['missed_pnl']:>+12,.0f}")
|
||||
print("\nrealized P&L = settled bets only · equity = $1000 + realized (open held at cost)")
|
||||
print("missed P&L = hypothetical resolved P&L of trades skipped for lack of cash")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,66 @@
|
||||
#!/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, size_min=None):
|
||||
"""One signal per market. size_min filters to the wallet's larger-stake
|
||||
(higher-conviction) bets; 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)
|
||||
resolved = {b["cond"]: b for b in cache.get_bets(w)}
|
||||
for cond, ets in ent.items():
|
||||
if ets < JUN1:
|
||||
continue
|
||||
b = resolved.get(cond)
|
||||
if b:
|
||||
if size_min and (b["size"] or 0) < size_min:
|
||||
continue
|
||||
rec = dict(ets=ets, p=max(0.001, min(0.999, b["p"])),
|
||||
won=b["won"], res_t=b["res_t"])
|
||||
else:
|
||||
if size_min:
|
||||
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, size_min=None):
|
||||
ev = gather(wallets, size_min)
|
||||
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 (their bets >= $200)", [E8], size_min=200)
|
||||
run("0xe8 only — conviction (their bets >= $1000)", [E8], size_min=1000)
|
||||
run("0xe8 + 0x0a — all June+ entries", [E8, A0])
|
||||
run("0xe8 + 0x0a — conviction (>= $200)", [E8, A0], size_min=200)
|
||||
print("\nrealized = settled-bet P&L · equity = $1000 + realized (open at cost)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+1502
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Train/test wallet-selection study, entirely from the local cache.
|
||||
|
||||
TRAIN = bets resolved before --train-end (default 2026-05-30): pick wallets.
|
||||
TEST = bets resolved on/after --test-start (default 2026-06-01), resolved only:
|
||||
validate which picks were actually profitable to follow forward.
|
||||
|
||||
Lens: we have $1,000 and copy flat-size, so the key metric is COPY-ROI — the
|
||||
mean per-bet return if we mirror each entry with the same stake:
|
||||
win -> (1-p)/p per $1 (entry at price p pays out at 1)
|
||||
loss -> -1
|
||||
A wallet with positive copy-ROI would have made us money (before lag/fees).
|
||||
We also compute z (beats entry prices) and the wallet's own $ ROI.
|
||||
|
||||
Selection gates (all on TRAIN):
|
||||
* n >= MIN_N resolved bets
|
||||
* z significant (Benjamini-Hochberg FDR)
|
||||
* copy-ROI > 0 (copying them actually paid)
|
||||
* consistent: positive copy-ROI in >= CONSISTENCY of monthly buckets
|
||||
* copyable proxies: median bet size in [$5,$5000] (not dust, not whale),
|
||||
not at the ~2000-bet HFT cap, not one-market-dependent
|
||||
|
||||
python3 strategy.py
|
||||
"""
|
||||
|
||||
import math
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from collections import defaultdict
|
||||
|
||||
import duckdb
|
||||
|
||||
HERE = os.path.dirname(__file__)
|
||||
DB = os.path.join(HERE, "cache.duckdb")
|
||||
TRAIN_END = time.mktime(time.strptime(os.environ.get("TRAIN_END", "2026-05-30"), "%Y-%m-%d"))
|
||||
TEST_START = time.mktime(time.strptime(os.environ.get("TEST_START", "2026-06-01"), "%Y-%m-%d"))
|
||||
MIN_N = 30 # train bets needed to judge a wallet
|
||||
MIN_N_TEST = 5 # forward bets needed to report a forward number
|
||||
CAP = 1990 # >= this looks API-capped (HFT/truncated) -> deprioritize
|
||||
SIZE_LO, SIZE_HI = 5.0, 5000.0 # copyable median bet size ($)
|
||||
CONSISTENCY = 0.6 # fraction of monthly buckets that must be profitable
|
||||
FDR_Q = 0.05
|
||||
|
||||
|
||||
def ret(p, won):
|
||||
return (1 - p) / p if won else -1.0 # copy return per $1 staked
|
||||
|
||||
|
||||
def metrics(bets):
|
||||
n = len(bets)
|
||||
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)
|
||||
copy_roi = sum(ret(b["p"], b["won"]) for b in bets) / n
|
||||
staked = sum(b["size"] for b in bets) or 1e-9
|
||||
dollars = sum((b["size"] * (1 - b["p"]) / b["p"] if b["won"] else -b["size"]) for b in bets)
|
||||
return dict(n=n, wins=wins, win_rate=100 * wins / n, z=z, copy_roi=copy_roi,
|
||||
own_roi=dollars / staked, exp=exp)
|
||||
|
||||
|
||||
def consistency(bets):
|
||||
"""fraction of calendar-month buckets (by res_t) with positive copy-ROI."""
|
||||
buck = defaultdict(list)
|
||||
for b in bets:
|
||||
buck[time.strftime("%Y-%m", time.localtime(b["res_t"] or 0))].append(b)
|
||||
months = [m for m in buck.values() if len(m) >= 5]
|
||||
if not months:
|
||||
return 0.0, 0
|
||||
good = sum(1 for m in months if sum(ret(b["p"], b["won"]) for b in m) > 0)
|
||||
return good / len(months), len(months)
|
||||
|
||||
|
||||
def concentration(bets):
|
||||
"""share of total copy-return coming from the single best market."""
|
||||
by = defaultdict(float)
|
||||
for b in bets:
|
||||
by[b["cond"]] += ret(b["p"], b["won"])
|
||||
tot = sum(v for v in by.values() if v > 0) or 1e-9
|
||||
return max(by.values()) / tot if by else 1.0
|
||||
|
||||
|
||||
def norm_sf(z):
|
||||
return 0.5 * math.erfc(z / math.sqrt(2))
|
||||
|
||||
|
||||
def main():
|
||||
con = duckdb.connect(DB, read_only=True)
|
||||
wallets = [r[0] for r in con.execute("SELECT DISTINCT wallet FROM bets").fetchall()]
|
||||
print(f"loaded {len(wallets):,} wallets; train<{time.strftime('%F', time.localtime(TRAIN_END))}"
|
||||
f" test>={time.strftime('%F', time.localtime(TEST_START))}\n", flush=True)
|
||||
|
||||
cand = []
|
||||
for w in wallets:
|
||||
rows = con.execute(
|
||||
"SELECT won,p,res_t,size,cond FROM bets WHERE wallet=?", [w]).fetchall()
|
||||
bets = [dict(won=x[0], p=max(0.001, min(0.999, x[1] or 0)),
|
||||
res_t=x[2], size=x[3] or 0, cond=x[4]) for x in rows]
|
||||
train = [b for b in bets if (b["res_t"] or 0) < TRAIN_END]
|
||||
if len(train) < MIN_N:
|
||||
continue
|
||||
m = metrics(train)
|
||||
med = sorted(b["size"] for b in train)[len(train) // 2]
|
||||
cons, nmonths = consistency(train)
|
||||
conc = concentration(train)
|
||||
test = [b for b in bets if (b["res_t"] or 0) >= TEST_START]
|
||||
tm = metrics(test) if len(test) >= MIN_N_TEST else None
|
||||
cand.append(dict(w=w, m=m, med=med, cons=cons, nmonths=nmonths, conc=conc,
|
||||
capped=len(train) >= CAP, tm=tm, ntest=len(test)))
|
||||
|
||||
# FDR over the candidate edge p-values
|
||||
pvals = sorted(norm_sf(c["m"]["z"]) for c in cand)
|
||||
k = 0
|
||||
for i, p in enumerate(pvals, 1):
|
||||
if p <= FDR_Q * i / len(pvals):
|
||||
k = i
|
||||
thr = pvals[k - 1] if k else 0.0
|
||||
|
||||
# selection gates (all on TRAIN)
|
||||
sel = [c for c in cand if
|
||||
norm_sf(c["m"]["z"]) <= thr and thr > 0 and
|
||||
c["m"]["copy_roi"] > 0 and
|
||||
c["cons"] >= CONSISTENCY and
|
||||
SIZE_LO <= c["med"] <= SIZE_HI and
|
||||
not c["capped"] and
|
||||
c["conc"] < 0.5]
|
||||
sel.sort(key=lambda c: c["m"]["copy_roi"], reverse=True)
|
||||
|
||||
print(f"{len(cand):,} wallets with >= {MIN_N} train bets · BH thr p<= {thr:.1e}")
|
||||
print(f"SELECTED (skilled + consistent + copyable on TRAIN): {len(sel)}\n")
|
||||
|
||||
# how did the SELECTED set do FORWARD?
|
||||
fwd = [c for c in sel if c["tm"]]
|
||||
if fwd:
|
||||
avg_fwd = sum(c["tm"]["copy_roi"] for c in fwd) / len(fwd)
|
||||
win_fwd = sum(1 for c in fwd if c["tm"]["copy_roi"] > 0)
|
||||
print(f"FORWARD (June1+, resolved): {len(fwd)} selected wallets had test bets · "
|
||||
f"{win_fwd}/{len(fwd)} stayed profitable · mean fwd copy-ROI {avg_fwd:+.1%}\n")
|
||||
|
||||
h = (f"{'train_roi':>10}{'fwd_roi':>9}{'tr_z':>6}{'tr_wr':>6}{'cons':>6}"
|
||||
f"{'medSz':>7}{'tr_n':>6}{'fwd_n':>6} wallet")
|
||||
print(h); print("-" * len(h))
|
||||
for c in sel[:40]:
|
||||
t = c["tm"]
|
||||
fr = f"{t['copy_roi']:+.0%}" if t else " —"
|
||||
fn = c["ntest"] if t else 0
|
||||
print(f"{c['m']['copy_roi']:>+9.0%}{fr:>9}{c['m']['z']:>6.1f}{c['m']['win_rate']:>5.0f}%"
|
||||
f"{c['cons']:>6.0%}{c['med']:>7.0f}{c['m']['n']:>6}{fn:>6} {c['w']}")
|
||||
# persist the selection for the followability pull + watchlist
|
||||
import json
|
||||
json.dump([{"wallet": c["w"], "train_copy_roi": round(c["m"]["copy_roi"], 4),
|
||||
"train_z": round(c["m"]["z"], 2), "train_n": c["m"]["n"],
|
||||
"fwd_copy_roi": round(c["tm"]["copy_roi"], 4) if c["tm"] else None,
|
||||
"fwd_n": c["ntest"], "med_size": round(c["med"], 1),
|
||||
"consistency": round(c["cons"], 2)} for c in sel],
|
||||
open(os.path.join(HERE, "selection.json"), "w"), indent=2)
|
||||
print(f"\n-> selection.json ({len(sel)} wallets)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,849 @@
|
||||
[
|
||||
{
|
||||
"wallet": "0xe8ca3f758c93f44f3ec210542ab78afb7c0bcccb",
|
||||
"name": "0xe8ca3f75",
|
||||
"foll_fwd_copy_roi": 2.7036,
|
||||
"med_lead_h": 95.6,
|
||||
"cadence_per_day": 8.7,
|
||||
"followable_frac": 0.99,
|
||||
"fwd_followable_n": 93,
|
||||
"train_z": 18.86,
|
||||
"train_copy_roi": 2.8782
|
||||
},
|
||||
{
|
||||
"wallet": "0x0a7aaf83341b52df34e8ffef52aa295538d6df1b",
|
||||
"name": "0x0a7aaf83",
|
||||
"foll_fwd_copy_roi": 2.134,
|
||||
"med_lead_h": 248.8,
|
||||
"cadence_per_day": 9.8,
|
||||
"followable_frac": 0.99,
|
||||
"fwd_followable_n": 138,
|
||||
"train_z": 7.21,
|
||||
"train_copy_roi": 0.5841
|
||||
},
|
||||
{
|
||||
"wallet": "0xfd4263b3ad08226034fe1b1ea678a46d80b58895",
|
||||
"name": "0xfd4263b3",
|
||||
"foll_fwd_copy_roi": 0.9877,
|
||||
"med_lead_h": 256.3,
|
||||
"cadence_per_day": 5.8,
|
||||
"followable_frac": 0.98,
|
||||
"fwd_followable_n": 39,
|
||||
"train_z": 15.53,
|
||||
"train_copy_roi": 2.1616
|
||||
},
|
||||
{
|
||||
"wallet": "0x13464aabec792c36b062316f474713e681330448",
|
||||
"name": "0x13464aab",
|
||||
"foll_fwd_copy_roi": 0.9692,
|
||||
"med_lead_h": 158.6,
|
||||
"cadence_per_day": 5.8,
|
||||
"followable_frac": 0.96,
|
||||
"fwd_followable_n": 89,
|
||||
"train_z": 7.33,
|
||||
"train_copy_roi": 0.512
|
||||
},
|
||||
{
|
||||
"wallet": "0xad703ba9fa7af1447bfcfe22522d052df64f4ccf",
|
||||
"name": "0xad703ba9",
|
||||
"foll_fwd_copy_roi": 0.9587,
|
||||
"med_lead_h": 39.6,
|
||||
"cadence_per_day": 11.0,
|
||||
"followable_frac": 0.99,
|
||||
"fwd_followable_n": 163,
|
||||
"train_z": 3.98,
|
||||
"train_copy_roi": 0.3063
|
||||
},
|
||||
{
|
||||
"wallet": "0x36bfcd8ab96dce2ddea30145ab749b59c6362864",
|
||||
"name": "0x36bfcd8a",
|
||||
"foll_fwd_copy_roi": 0.8856,
|
||||
"med_lead_h": 157.7,
|
||||
"cadence_per_day": 16.9,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 96,
|
||||
"train_z": 7.03,
|
||||
"train_copy_roi": 0.2044
|
||||
},
|
||||
{
|
||||
"wallet": "0x2d4bf8f846bf68f43b9157bf30810d334ac6ca7a",
|
||||
"name": "0x2d4bf8f8",
|
||||
"foll_fwd_copy_roi": 0.6857,
|
||||
"med_lead_h": 364.3,
|
||||
"cadence_per_day": 6.8,
|
||||
"followable_frac": 0.99,
|
||||
"fwd_followable_n": 110,
|
||||
"train_z": 19.72,
|
||||
"train_copy_roi": 0.8859
|
||||
},
|
||||
{
|
||||
"wallet": "0xade74a23c444d0eebee00034459fbc269fab58af",
|
||||
"name": "0xade74a23",
|
||||
"foll_fwd_copy_roi": 0.6597,
|
||||
"med_lead_h": 161.4,
|
||||
"cadence_per_day": 1.5,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 18,
|
||||
"train_z": 6.43,
|
||||
"train_copy_roi": 0.3886
|
||||
},
|
||||
{
|
||||
"wallet": "0xab2067f2bfe4a5bce93cda6f418cde1515d2d9e2",
|
||||
"name": "0xab2067f2",
|
||||
"foll_fwd_copy_roi": 0.5481,
|
||||
"med_lead_h": 161.4,
|
||||
"cadence_per_day": 3.8,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 19,
|
||||
"train_z": 5.6,
|
||||
"train_copy_roi": 0.2669
|
||||
},
|
||||
{
|
||||
"wallet": "0x1cff72c8dddc30a64486fda6eab71ab5f9243984",
|
||||
"name": "0x1cff72c8",
|
||||
"foll_fwd_copy_roi": 0.4498,
|
||||
"med_lead_h": 14.8,
|
||||
"cadence_per_day": 3.5,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 31,
|
||||
"train_z": 5.5,
|
||||
"train_copy_roi": 0.1861
|
||||
},
|
||||
{
|
||||
"wallet": "0x68c24bf4a8ad4d79a6fe4b8eec6f93a02dfd1711",
|
||||
"name": "0x68c24bf4",
|
||||
"foll_fwd_copy_roi": 0.4469,
|
||||
"med_lead_h": 401.2,
|
||||
"cadence_per_day": 4.2,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 30,
|
||||
"train_z": 4.23,
|
||||
"train_copy_roi": 0.3288
|
||||
},
|
||||
{
|
||||
"wallet": "0xfc81760d44a21acc9fd4b749a5bf9a9b2eeae072",
|
||||
"name": "0xfc81760d",
|
||||
"foll_fwd_copy_roi": 0.409,
|
||||
"med_lead_h": 161.5,
|
||||
"cadence_per_day": 5.7,
|
||||
"followable_frac": 0.99,
|
||||
"fwd_followable_n": 142,
|
||||
"train_z": 7.92,
|
||||
"train_copy_roi": 0.2013
|
||||
},
|
||||
{
|
||||
"wallet": "0x2f385bfefacbf73173f9cb81f46fe7a53b2c8adc",
|
||||
"name": "0x2f385bfe",
|
||||
"foll_fwd_copy_roi": 0.3809,
|
||||
"med_lead_h": 173.0,
|
||||
"cadence_per_day": 0.3,
|
||||
"followable_frac": 0.99,
|
||||
"fwd_followable_n": 25,
|
||||
"train_z": 3.75,
|
||||
"train_copy_roi": 0.2828
|
||||
},
|
||||
{
|
||||
"wallet": "0x7ed0a33693a19378318f160064e4f9c1c27a9c4f",
|
||||
"name": "0x7ed0a336",
|
||||
"foll_fwd_copy_roi": 0.361,
|
||||
"med_lead_h": 154.6,
|
||||
"cadence_per_day": 10.5,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 250,
|
||||
"train_z": 3.9,
|
||||
"train_copy_roi": 0.1949
|
||||
},
|
||||
{
|
||||
"wallet": "0x64795fe43b184571d5eb25ca44fc9ba9e1295e64",
|
||||
"name": "0x64795fe4",
|
||||
"foll_fwd_copy_roi": 0.3407,
|
||||
"med_lead_h": 17.9,
|
||||
"cadence_per_day": 2.8,
|
||||
"followable_frac": 0.96,
|
||||
"fwd_followable_n": 7,
|
||||
"train_z": 7.29,
|
||||
"train_copy_roi": 0.2879
|
||||
},
|
||||
{
|
||||
"wallet": "0x312d268ab4d1823684d6838f24a3c96da7d66814",
|
||||
"name": "0x312d268a",
|
||||
"foll_fwd_copy_roi": 0.327,
|
||||
"med_lead_h": 5.5,
|
||||
"cadence_per_day": 16.5,
|
||||
"followable_frac": 0.87,
|
||||
"fwd_followable_n": 30,
|
||||
"train_z": 3.48,
|
||||
"train_copy_roi": 0.0428
|
||||
},
|
||||
{
|
||||
"wallet": "0x86c878cde72660ec52f5e6f0f0438b76de8fc867",
|
||||
"name": "0x86c878cd",
|
||||
"foll_fwd_copy_roi": 0.3054,
|
||||
"med_lead_h": 156.9,
|
||||
"cadence_per_day": 11.0,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 97,
|
||||
"train_z": 7.81,
|
||||
"train_copy_roi": 1.2334
|
||||
},
|
||||
{
|
||||
"wallet": "0x48270d81cfe598ae0379ca535a26dc41e3e9080d",
|
||||
"name": "0x48270d81",
|
||||
"foll_fwd_copy_roi": 0.2759,
|
||||
"med_lead_h": 150.9,
|
||||
"cadence_per_day": 16.8,
|
||||
"followable_frac": 0.92,
|
||||
"fwd_followable_n": 170,
|
||||
"train_z": 3.12,
|
||||
"train_copy_roi": 0.1267
|
||||
},
|
||||
{
|
||||
"wallet": "0x12f93b2a5cd5d370e2e2772246c3c7ceed7774ba",
|
||||
"name": "0x12f93b2a",
|
||||
"foll_fwd_copy_roi": 0.2733,
|
||||
"med_lead_h": 2.5,
|
||||
"cadence_per_day": 9.6,
|
||||
"followable_frac": 0.87,
|
||||
"fwd_followable_n": 8,
|
||||
"train_z": 11.58,
|
||||
"train_copy_roi": 0.3433
|
||||
},
|
||||
{
|
||||
"wallet": "0xc904211fd4412d5caa0b51f923304bf5e1821e9a",
|
||||
"name": "0xc904211f",
|
||||
"foll_fwd_copy_roi": 0.2391,
|
||||
"med_lead_h": 10.5,
|
||||
"cadence_per_day": 5.2,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 21,
|
||||
"train_z": 4.14,
|
||||
"train_copy_roi": 0.2324
|
||||
},
|
||||
{
|
||||
"wallet": "0xb8f6c79e452d7247d0cf47d16eaf7911953c4f7f",
|
||||
"name": "0xb8f6c79e",
|
||||
"foll_fwd_copy_roi": 0.2062,
|
||||
"med_lead_h": 136.4,
|
||||
"cadence_per_day": 16.8,
|
||||
"followable_frac": 0.99,
|
||||
"fwd_followable_n": 154,
|
||||
"train_z": 3.31,
|
||||
"train_copy_roi": 0.082
|
||||
},
|
||||
{
|
||||
"wallet": "0x6fdddf25b92251ed1515703cda43bf8ff5f5d385",
|
||||
"name": "0x6fdddf25",
|
||||
"foll_fwd_copy_roi": 0.2044,
|
||||
"med_lead_h": 10.1,
|
||||
"cadence_per_day": 25.7,
|
||||
"followable_frac": 0.98,
|
||||
"fwd_followable_n": 103,
|
||||
"train_z": 7.59,
|
||||
"train_copy_roi": 0.4085
|
||||
},
|
||||
{
|
||||
"wallet": "0xe1a607ef9d2bf9db6a8ebc99c612743827c8391d",
|
||||
"name": "0xe1a607ef",
|
||||
"foll_fwd_copy_roi": 0.1693,
|
||||
"med_lead_h": 171.3,
|
||||
"cadence_per_day": 0.4,
|
||||
"followable_frac": 0.99,
|
||||
"fwd_followable_n": 31,
|
||||
"train_z": 5.35,
|
||||
"train_copy_roi": 0.36
|
||||
},
|
||||
{
|
||||
"wallet": "0x13a12ebadc50f6fa42c8f2595997d8adf329d9bc",
|
||||
"name": "0x13a12eba",
|
||||
"foll_fwd_copy_roi": 0.1595,
|
||||
"med_lead_h": 2.1,
|
||||
"cadence_per_day": 10.8,
|
||||
"followable_frac": 0.87,
|
||||
"fwd_followable_n": 28,
|
||||
"train_z": 4.43,
|
||||
"train_copy_roi": 0.082
|
||||
},
|
||||
{
|
||||
"wallet": "0x5912794596cd3cc2f36605710fc1fcd6e5886f45",
|
||||
"name": "0x59127945",
|
||||
"foll_fwd_copy_roi": 0.1589,
|
||||
"med_lead_h": 157.6,
|
||||
"cadence_per_day": 6.8,
|
||||
"followable_frac": 0.99,
|
||||
"fwd_followable_n": 150,
|
||||
"train_z": 6.6,
|
||||
"train_copy_roi": 0.0691
|
||||
},
|
||||
{
|
||||
"wallet": "0x4269450ac9f1927fc1fd462678606d3c7656e056",
|
||||
"name": "0x4269450a",
|
||||
"foll_fwd_copy_roi": 0.1512,
|
||||
"med_lead_h": 3.2,
|
||||
"cadence_per_day": 6.2,
|
||||
"followable_frac": 0.85,
|
||||
"fwd_followable_n": 12,
|
||||
"train_z": 5.47,
|
||||
"train_copy_roi": 0.1799
|
||||
},
|
||||
{
|
||||
"wallet": "0x96be2d4496f4c547e6c0e7765f15d7c83c5069a9",
|
||||
"name": "0x96be2d44",
|
||||
"foll_fwd_copy_roi": 0.1354,
|
||||
"med_lead_h": 3.2,
|
||||
"cadence_per_day": 39.8,
|
||||
"followable_frac": 0.8,
|
||||
"fwd_followable_n": 172,
|
||||
"train_z": 5.4,
|
||||
"train_copy_roi": 0.0536
|
||||
},
|
||||
{
|
||||
"wallet": "0x75acf1aa88a3f5c613f2214486b91fa9fc1f33d7",
|
||||
"name": "0x75acf1aa",
|
||||
"foll_fwd_copy_roi": 0.1346,
|
||||
"med_lead_h": 67.7,
|
||||
"cadence_per_day": 7.1,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 132,
|
||||
"train_z": 7.61,
|
||||
"train_copy_roi": 0.1037
|
||||
},
|
||||
{
|
||||
"wallet": "0x2f633efb75256a2f2445110c8978684ab8936643",
|
||||
"name": "0x2f633efb",
|
||||
"foll_fwd_copy_roi": 0.1322,
|
||||
"med_lead_h": 253.6,
|
||||
"cadence_per_day": 1.7,
|
||||
"followable_frac": 0.97,
|
||||
"fwd_followable_n": 36,
|
||||
"train_z": 7.54,
|
||||
"train_copy_roi": 0.1757
|
||||
},
|
||||
{
|
||||
"wallet": "0x8428101d6979dcc97de6c7474b0535ceb558b41f",
|
||||
"name": "0x8428101d",
|
||||
"foll_fwd_copy_roi": 0.1305,
|
||||
"med_lead_h": 2.4,
|
||||
"cadence_per_day": 33.2,
|
||||
"followable_frac": 0.82,
|
||||
"fwd_followable_n": 112,
|
||||
"train_z": 3.69,
|
||||
"train_copy_roi": 0.0588
|
||||
},
|
||||
{
|
||||
"wallet": "0xc308447bc9ef6e72018a3f3914005bd24c207b09",
|
||||
"name": "0xc308447b",
|
||||
"foll_fwd_copy_roi": 0.1274,
|
||||
"med_lead_h": 2.1,
|
||||
"cadence_per_day": 15.9,
|
||||
"followable_frac": 0.82,
|
||||
"fwd_followable_n": 194,
|
||||
"train_z": 5.54,
|
||||
"train_copy_roi": 0.5171
|
||||
},
|
||||
{
|
||||
"wallet": "0x2b7b2173a5f89300e93625805871565ed82e8539",
|
||||
"name": "0x2b7b2173",
|
||||
"foll_fwd_copy_roi": 0.1127,
|
||||
"med_lead_h": 2.4,
|
||||
"cadence_per_day": 45.6,
|
||||
"followable_frac": 0.81,
|
||||
"fwd_followable_n": 63,
|
||||
"train_z": 13.85,
|
||||
"train_copy_roi": 0.3276
|
||||
},
|
||||
{
|
||||
"wallet": "0x143844ade2eb7d1aa86c2dee71dc65eb28396d40",
|
||||
"name": "0x143844ad",
|
||||
"foll_fwd_copy_roi": 0.1065,
|
||||
"med_lead_h": 2.7,
|
||||
"cadence_per_day": 40.8,
|
||||
"followable_frac": 0.8,
|
||||
"fwd_followable_n": 105,
|
||||
"train_z": 4.1,
|
||||
"train_copy_roi": 0.1253
|
||||
},
|
||||
{
|
||||
"wallet": "0x5f5945ea1a0be6c3ca7c841769ef892be48ae61d",
|
||||
"name": "0x5f5945ea",
|
||||
"foll_fwd_copy_roi": 0.1056,
|
||||
"med_lead_h": 2.3,
|
||||
"cadence_per_day": 11.4,
|
||||
"followable_frac": 0.77,
|
||||
"fwd_followable_n": 27,
|
||||
"train_z": 4.14,
|
||||
"train_copy_roi": 0.0393
|
||||
},
|
||||
{
|
||||
"wallet": "0x5e23595f0d698f29832a5cf19e94c24fb1c5a3d7",
|
||||
"name": "0x5e23595f",
|
||||
"foll_fwd_copy_roi": 0.0972,
|
||||
"med_lead_h": 2.2,
|
||||
"cadence_per_day": 20.8,
|
||||
"followable_frac": 0.79,
|
||||
"fwd_followable_n": 63,
|
||||
"train_z": 7.59,
|
||||
"train_copy_roi": 0.0746
|
||||
},
|
||||
{
|
||||
"wallet": "0x1e55408f217f58facdf1d663c74cfa7f55e9e3e2",
|
||||
"name": "0x1e55408f",
|
||||
"foll_fwd_copy_roi": 0.0959,
|
||||
"med_lead_h": 322.6,
|
||||
"cadence_per_day": 1.4,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 77,
|
||||
"train_z": 4.12,
|
||||
"train_copy_roi": 0.4696
|
||||
},
|
||||
{
|
||||
"wallet": "0xb03b826a4fc9893b35d3ddf4f11be824525b6ca1",
|
||||
"name": "0xb03b826a",
|
||||
"foll_fwd_copy_roi": 0.0878,
|
||||
"med_lead_h": 322.5,
|
||||
"cadence_per_day": 2.6,
|
||||
"followable_frac": 0.98,
|
||||
"fwd_followable_n": 39,
|
||||
"train_z": 4.1,
|
||||
"train_copy_roi": 0.081
|
||||
},
|
||||
{
|
||||
"wallet": "0xf2bbd4a5a02780c14b7ec16a52a3e21a744cae21",
|
||||
"name": "0xf2bbd4a5",
|
||||
"foll_fwd_copy_roi": 0.0854,
|
||||
"med_lead_h": 27.8,
|
||||
"cadence_per_day": 16.3,
|
||||
"followable_frac": 0.94,
|
||||
"fwd_followable_n": 87,
|
||||
"train_z": 3.01,
|
||||
"train_copy_roi": 0.1332
|
||||
},
|
||||
{
|
||||
"wallet": "0xffb0b9b292e406fd250854a35a0c9bd5612afa37",
|
||||
"name": "0xffb0b9b2",
|
||||
"foll_fwd_copy_roi": 0.0786,
|
||||
"med_lead_h": 495.6,
|
||||
"cadence_per_day": 2.4,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 42,
|
||||
"train_z": 4.63,
|
||||
"train_copy_roi": 0.1617
|
||||
},
|
||||
{
|
||||
"wallet": "0xff4288c9d0cf320e494174554a752fe9f9ca1548",
|
||||
"name": "0xff4288c9",
|
||||
"foll_fwd_copy_roi": 0.0696,
|
||||
"med_lead_h": 2.9,
|
||||
"cadence_per_day": 35.6,
|
||||
"followable_frac": 0.85,
|
||||
"fwd_followable_n": 48,
|
||||
"train_z": 3.17,
|
||||
"train_copy_roi": 0.04
|
||||
},
|
||||
{
|
||||
"wallet": "0xb2b4ec88c02de44d6ab61eb6c4141fe8170e512d",
|
||||
"name": "0xb2b4ec88",
|
||||
"foll_fwd_copy_roi": 0.0671,
|
||||
"med_lead_h": 2.6,
|
||||
"cadence_per_day": 46.3,
|
||||
"followable_frac": 0.83,
|
||||
"fwd_followable_n": 49,
|
||||
"train_z": 3.9,
|
||||
"train_copy_roi": 0.0674
|
||||
},
|
||||
{
|
||||
"wallet": "0xed61f86bb5298d2f27c21c433ce58d80b88a9aa3",
|
||||
"name": "0xed61f86b",
|
||||
"foll_fwd_copy_roi": 0.0439,
|
||||
"med_lead_h": 3.2,
|
||||
"cadence_per_day": 3.6,
|
||||
"followable_frac": 0.91,
|
||||
"fwd_followable_n": 13,
|
||||
"train_z": 10.52,
|
||||
"train_copy_roi": 0.35
|
||||
},
|
||||
{
|
||||
"wallet": "0xc39319fc46cb229eeacf3763cce5977766b3b18f",
|
||||
"name": "0xc39319fc",
|
||||
"foll_fwd_copy_roi": 0.0436,
|
||||
"med_lead_h": 2.1,
|
||||
"cadence_per_day": 14.8,
|
||||
"followable_frac": 0.74,
|
||||
"fwd_followable_n": 66,
|
||||
"train_z": 5.06,
|
||||
"train_copy_roi": 0.3394
|
||||
},
|
||||
{
|
||||
"wallet": "0x7ca56b03105371839e4a3d98f4c1059d10d784bc",
|
||||
"name": "0x7ca56b03",
|
||||
"foll_fwd_copy_roi": 0.0222,
|
||||
"med_lead_h": 156.3,
|
||||
"cadence_per_day": 38.0,
|
||||
"followable_frac": 0.98,
|
||||
"fwd_followable_n": 194,
|
||||
"train_z": 4.57,
|
||||
"train_copy_roi": 0.0063
|
||||
},
|
||||
{
|
||||
"wallet": "0x8c1026f774fe33016fb36d5f18f5e791d3e0d7b3",
|
||||
"name": "0x8c1026f7",
|
||||
"foll_fwd_copy_roi": 0.0205,
|
||||
"med_lead_h": 404.8,
|
||||
"cadence_per_day": 9.8,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 242,
|
||||
"train_z": 3.16,
|
||||
"train_copy_roi": 0.0215
|
||||
},
|
||||
{
|
||||
"wallet": "0x70831c34434486ffb8e33270642604d9c5731937",
|
||||
"name": "0x70831c34",
|
||||
"foll_fwd_copy_roi": 0.0166,
|
||||
"med_lead_h": 131.0,
|
||||
"cadence_per_day": 4.0,
|
||||
"followable_frac": 0.83,
|
||||
"fwd_followable_n": 10,
|
||||
"train_z": 5.38,
|
||||
"train_copy_roi": 0.7969
|
||||
},
|
||||
{
|
||||
"wallet": "0x85d57ae07c1c0cae93f1ed6d05166eff4233bbf0",
|
||||
"name": "0x85d57ae0",
|
||||
"foll_fwd_copy_roi": 0.0155,
|
||||
"med_lead_h": 159.4,
|
||||
"cadence_per_day": 5.8,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 97,
|
||||
"train_z": 5.67,
|
||||
"train_copy_roi": 0.1268
|
||||
},
|
||||
{
|
||||
"wallet": "0x5a05e30ef2ae848927c7a724b93292bf8cd14c5a",
|
||||
"name": "0x5a05e30e",
|
||||
"foll_fwd_copy_roi": 0.0136,
|
||||
"med_lead_h": 6.5,
|
||||
"cadence_per_day": 25.6,
|
||||
"followable_frac": 0.99,
|
||||
"fwd_followable_n": 48,
|
||||
"train_z": 7.26,
|
||||
"train_copy_roi": 0.1578
|
||||
},
|
||||
{
|
||||
"wallet": "0x875e974594985283c999765461bf2e15b4dee6b5",
|
||||
"name": "0x875e9745",
|
||||
"foll_fwd_copy_roi": 0.0047,
|
||||
"med_lead_h": 5.7,
|
||||
"cadence_per_day": 16.3,
|
||||
"followable_frac": 0.94,
|
||||
"fwd_followable_n": 14,
|
||||
"train_z": 4.25,
|
||||
"train_copy_roi": 0.0102
|
||||
},
|
||||
{
|
||||
"wallet": "0x587bcff09b7e887186a4e2b3086653f10dcd2622",
|
||||
"name": "0x587bcff0",
|
||||
"foll_fwd_copy_roi": -0.002,
|
||||
"med_lead_h": 35.9,
|
||||
"cadence_per_day": 17.2,
|
||||
"followable_frac": 0.99,
|
||||
"fwd_followable_n": 52,
|
||||
"train_z": 3.48,
|
||||
"train_copy_roi": 0.1476
|
||||
},
|
||||
{
|
||||
"wallet": "0xa75f077c6e2510b020967c6230bac2bf342300f0",
|
||||
"name": "0xa75f077c",
|
||||
"foll_fwd_copy_roi": -0.007,
|
||||
"med_lead_h": 2.8,
|
||||
"cadence_per_day": 21.7,
|
||||
"followable_frac": 0.8,
|
||||
"fwd_followable_n": 21,
|
||||
"train_z": 5.54,
|
||||
"train_copy_roi": 0.135
|
||||
},
|
||||
{
|
||||
"wallet": "0xb5e987c2027879646587f060f7d25793d011c62a",
|
||||
"name": "0xb5e987c2",
|
||||
"foll_fwd_copy_roi": -0.0136,
|
||||
"med_lead_h": 2.0,
|
||||
"cadence_per_day": 39.0,
|
||||
"followable_frac": 0.78,
|
||||
"fwd_followable_n": 48,
|
||||
"train_z": 9.81,
|
||||
"train_copy_roi": 0.074
|
||||
},
|
||||
{
|
||||
"wallet": "0x8548f0fae7636fc17ca6bb2cbae39cbd4fbce4c1",
|
||||
"name": "0x8548f0fa",
|
||||
"foll_fwd_copy_roi": -0.026,
|
||||
"med_lead_h": 3.2,
|
||||
"cadence_per_day": 21.5,
|
||||
"followable_frac": 0.94,
|
||||
"fwd_followable_n": 35,
|
||||
"train_z": 4.34,
|
||||
"train_copy_roi": 1.2923
|
||||
},
|
||||
{
|
||||
"wallet": "0xd84d970b0d4ec9bfc28d011306eba298b339cc32",
|
||||
"name": "0xd84d970b",
|
||||
"foll_fwd_copy_roi": -0.0384,
|
||||
"med_lead_h": 6.9,
|
||||
"cadence_per_day": 8.4,
|
||||
"followable_frac": 0.97,
|
||||
"fwd_followable_n": 44,
|
||||
"train_z": 8.73,
|
||||
"train_copy_roi": 1.7671
|
||||
},
|
||||
{
|
||||
"wallet": "0xf3d54ccedcd08c9a203d28e332275e50770fdde9",
|
||||
"name": "0xf3d54cce",
|
||||
"foll_fwd_copy_roi": -0.0386,
|
||||
"med_lead_h": 2.8,
|
||||
"cadence_per_day": 22.9,
|
||||
"followable_frac": 0.79,
|
||||
"fwd_followable_n": 21,
|
||||
"train_z": 4.66,
|
||||
"train_copy_roi": 0.095
|
||||
},
|
||||
{
|
||||
"wallet": "0xc52fead8edac49825f5c52aff6e63cd331980981",
|
||||
"name": "0xc52fead8",
|
||||
"foll_fwd_copy_roi": -0.0394,
|
||||
"med_lead_h": 57.1,
|
||||
"cadence_per_day": 11.2,
|
||||
"followable_frac": 0.99,
|
||||
"fwd_followable_n": 73,
|
||||
"train_z": 4.15,
|
||||
"train_copy_roi": 0.0657
|
||||
},
|
||||
{
|
||||
"wallet": "0x4b284723fa3c53a46d5217394840ec3b70c615df",
|
||||
"name": "0x4b284723",
|
||||
"foll_fwd_copy_roi": -0.0434,
|
||||
"med_lead_h": 535.7,
|
||||
"cadence_per_day": 3.6,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 82,
|
||||
"train_z": 3.58,
|
||||
"train_copy_roi": 0.3997
|
||||
},
|
||||
{
|
||||
"wallet": "0xc0f1388fdb14503c3bdf7c244346c98b57208680",
|
||||
"name": "0xc0f1388f",
|
||||
"foll_fwd_copy_roi": -0.0588,
|
||||
"med_lead_h": 9.3,
|
||||
"cadence_per_day": 20.4,
|
||||
"followable_frac": 0.99,
|
||||
"fwd_followable_n": 82,
|
||||
"train_z": 4.52,
|
||||
"train_copy_roi": 0.4433
|
||||
},
|
||||
{
|
||||
"wallet": "0xc5d521074e88279556836998fb2a5d2e2c1c6caa",
|
||||
"name": "0xc5d52107",
|
||||
"foll_fwd_copy_roi": -0.0598,
|
||||
"med_lead_h": 3.2,
|
||||
"cadence_per_day": 37.2,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 21,
|
||||
"train_z": 5.39,
|
||||
"train_copy_roi": 0.051
|
||||
},
|
||||
{
|
||||
"wallet": "0x9e8ecc4cb3c4e48f544cba2fbbb252a6a65e8db8",
|
||||
"name": "0x9e8ecc4c",
|
||||
"foll_fwd_copy_roi": -0.0798,
|
||||
"med_lead_h": 46.1,
|
||||
"cadence_per_day": 47.0,
|
||||
"followable_frac": 0.99,
|
||||
"fwd_followable_n": 512,
|
||||
"train_z": 10.17,
|
||||
"train_copy_roi": 0.0761
|
||||
},
|
||||
{
|
||||
"wallet": "0xbbeacf98b7affb6ac2abf44b6577f5a54f931bb3",
|
||||
"name": "0xbbeacf98",
|
||||
"foll_fwd_copy_roi": -0.1034,
|
||||
"med_lead_h": 3.1,
|
||||
"cadence_per_day": 8.7,
|
||||
"followable_frac": 0.88,
|
||||
"fwd_followable_n": 25,
|
||||
"train_z": 3.42,
|
||||
"train_copy_roi": 0.1141
|
||||
},
|
||||
{
|
||||
"wallet": "0xd9001f915cf59cbd013f57ed380372329496d9d6",
|
||||
"name": "0xd9001f91",
|
||||
"foll_fwd_copy_roi": -0.1374,
|
||||
"med_lead_h": 3.3,
|
||||
"cadence_per_day": 9.8,
|
||||
"followable_frac": 0.85,
|
||||
"fwd_followable_n": 23,
|
||||
"train_z": 5.87,
|
||||
"train_copy_roi": 0.0809
|
||||
},
|
||||
{
|
||||
"wallet": "0x3298488d0f4af79aa44634e95f03f4ba8669b714",
|
||||
"name": "0x3298488d",
|
||||
"foll_fwd_copy_roi": -0.1394,
|
||||
"med_lead_h": 155.9,
|
||||
"cadence_per_day": 12.6,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 7,
|
||||
"train_z": 7.8,
|
||||
"train_copy_roi": 0.5191
|
||||
},
|
||||
{
|
||||
"wallet": "0xbafa197f7eecfc2fd2fe348cb995bba6812402e0",
|
||||
"name": "0xbafa197f",
|
||||
"foll_fwd_copy_roi": -0.152,
|
||||
"med_lead_h": 6.3,
|
||||
"cadence_per_day": 4.2,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 24,
|
||||
"train_z": 3.99,
|
||||
"train_copy_roi": 0.1195
|
||||
},
|
||||
{
|
||||
"wallet": "0x215adbb63b47d0ca92f849fe2c2dc1adb0f6254c",
|
||||
"name": "0x215adbb6",
|
||||
"foll_fwd_copy_roi": -0.1533,
|
||||
"med_lead_h": 364.9,
|
||||
"cadence_per_day": 27.6,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 98,
|
||||
"train_z": 4.71,
|
||||
"train_copy_roi": 0.3785
|
||||
},
|
||||
{
|
||||
"wallet": "0x51f7c3d9fa8cc71818aede2db6e4496968ecae1f",
|
||||
"name": "0x51f7c3d9",
|
||||
"foll_fwd_copy_roi": -0.1669,
|
||||
"med_lead_h": 105.2,
|
||||
"cadence_per_day": 15.5,
|
||||
"followable_frac": 0.99,
|
||||
"fwd_followable_n": 231,
|
||||
"train_z": 3.31,
|
||||
"train_copy_roi": 0.6247
|
||||
},
|
||||
{
|
||||
"wallet": "0xa6214292fba769fc1c0a11c3191cefe197bf6e29",
|
||||
"name": "0xa6214292",
|
||||
"foll_fwd_copy_roi": -0.2162,
|
||||
"med_lead_h": 3.4,
|
||||
"cadence_per_day": 15.9,
|
||||
"followable_frac": 0.89,
|
||||
"fwd_followable_n": 10,
|
||||
"train_z": 5.0,
|
||||
"train_copy_roi": 0.0241
|
||||
},
|
||||
{
|
||||
"wallet": "0x128485a5431d5cc091e0aac21299a819fc370323",
|
||||
"name": "0x128485a5",
|
||||
"foll_fwd_copy_roi": -0.2585,
|
||||
"med_lead_h": 2.5,
|
||||
"cadence_per_day": 7.3,
|
||||
"followable_frac": 0.91,
|
||||
"fwd_followable_n": 5,
|
||||
"train_z": 7.05,
|
||||
"train_copy_roi": 0.1592
|
||||
},
|
||||
{
|
||||
"wallet": "0x31de246d1502779e316a991fb85d3627a34303ff",
|
||||
"name": "0x31de246d",
|
||||
"foll_fwd_copy_roi": -0.3087,
|
||||
"med_lead_h": 47.2,
|
||||
"cadence_per_day": 6.2,
|
||||
"followable_frac": 0.96,
|
||||
"fwd_followable_n": 46,
|
||||
"train_z": 2.98,
|
||||
"train_copy_roi": 0.1141
|
||||
},
|
||||
{
|
||||
"wallet": "0xba0229758a95f7e1f906a7b9101bf2c195cb6b23",
|
||||
"name": "0xba022975",
|
||||
"foll_fwd_copy_roi": -0.3561,
|
||||
"med_lead_h": 95.4,
|
||||
"cadence_per_day": 2.3,
|
||||
"followable_frac": 0.99,
|
||||
"fwd_followable_n": 37,
|
||||
"train_z": 3.25,
|
||||
"train_copy_roi": 0.0936
|
||||
},
|
||||
{
|
||||
"wallet": "0x1a6df901e63422055a1658b0ef2b2a871507cf4a",
|
||||
"name": "0x1a6df901",
|
||||
"foll_fwd_copy_roi": -0.3636,
|
||||
"med_lead_h": 8.6,
|
||||
"cadence_per_day": 7.6,
|
||||
"followable_frac": 0.8,
|
||||
"fwd_followable_n": 13,
|
||||
"train_z": 11.16,
|
||||
"train_copy_roi": 2.1573
|
||||
},
|
||||
{
|
||||
"wallet": "0x34f4c3118569f32ef02441326305bca0ff5816bd",
|
||||
"name": "0x34f4c311",
|
||||
"foll_fwd_copy_roi": -0.3772,
|
||||
"med_lead_h": 2.3,
|
||||
"cadence_per_day": 32.3,
|
||||
"followable_frac": 0.81,
|
||||
"fwd_followable_n": 34,
|
||||
"train_z": 3.96,
|
||||
"train_copy_roi": 0.0336
|
||||
},
|
||||
{
|
||||
"wallet": "0xc850cf70d9da621ff0c219f625c9623f88b78c51",
|
||||
"name": "0xc850cf70",
|
||||
"foll_fwd_copy_roi": -0.3856,
|
||||
"med_lead_h": 3.8,
|
||||
"cadence_per_day": 13.7,
|
||||
"followable_frac": 1.0,
|
||||
"fwd_followable_n": 6,
|
||||
"train_z": 6.06,
|
||||
"train_copy_roi": 0.1196
|
||||
},
|
||||
{
|
||||
"wallet": "0xbd934e2889bef964f6b2e396f769eda6b2ef13fc",
|
||||
"name": "0xbd934e28",
|
||||
"foll_fwd_copy_roi": -0.3913,
|
||||
"med_lead_h": 2.5,
|
||||
"cadence_per_day": 9.1,
|
||||
"followable_frac": 0.8,
|
||||
"fwd_followable_n": 33,
|
||||
"train_z": 6.04,
|
||||
"train_copy_roi": 0.1456
|
||||
},
|
||||
{
|
||||
"wallet": "0xddcd8e90d139f6d60042b4a14cb2cd00a3a8725f",
|
||||
"name": "0xddcd8e90",
|
||||
"foll_fwd_copy_roi": -0.8613,
|
||||
"med_lead_h": 4.0,
|
||||
"cadence_per_day": 9.8,
|
||||
"followable_frac": 0.8,
|
||||
"fwd_followable_n": 29,
|
||||
"train_z": 4.94,
|
||||
"train_copy_roi": 0.5462
|
||||
},
|
||||
{
|
||||
"wallet": "0x93d9f537708ccb6e701a4ebd495e29b95798639f",
|
||||
"name": "0x93d9f537",
|
||||
"foll_fwd_copy_roi": -1.0,
|
||||
"med_lead_h": 3.6,
|
||||
"cadence_per_day": 10.1,
|
||||
"followable_frac": 0.97,
|
||||
"fwd_followable_n": 9,
|
||||
"train_z": 3.3,
|
||||
"train_copy_roi": 0.3581
|
||||
},
|
||||
{
|
||||
"wallet": "0x02730eb22c927008de1dd5b5df1c493ee67661e4",
|
||||
"name": "0x02730eb2",
|
||||
"foll_fwd_copy_roi": -1.0,
|
||||
"med_lead_h": 2.7,
|
||||
"cadence_per_day": 23.8,
|
||||
"followable_frac": 0.77,
|
||||
"fwd_followable_n": 5,
|
||||
"train_z": 3.4,
|
||||
"train_copy_roi": 0.1823
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user