diff --git a/FINDINGS.md b/FINDINGS.md new file mode 100644 index 00000000..7738ba5f --- /dev/null +++ b/FINDINGS.md @@ -0,0 +1,77 @@ +# Findings — what works and what doesn't on Polymarket + +A research log of an honest attempt to find a systematic, automatable edge on +Polymarket using public data. The short version: **almost nothing works** — the +market is efficient — and the one thing that does isn't a money-printer, it's a +detection signal. + +## The goal + +Find a repeatable way to make money on Polymarket: identify "smart money" +wallets, copy them, farm rewards, or arbitrage — anything systematic and +automatable from public data. + +## Scorecard + +| Approach | Verdict | Why | +|----------|---------|-----| +| **Copy high-win-rate wallets** | ❌ dead | Win rate was an illusion (see below). True rates ~50%. Flat-size copying backtested **−48%** over a week. | +| **Rank by leaderboard / PnL** | ❌ dead | Raw PnL is variance; top wallets win ~50% and profit via sizing/timing you can't copy. | +| **LP reward farming** | ❌ dead | The fat "thin-book" APRs are illusory — Polymarket **refunds unearned pool to the sponsor** when liquidity is low. Real yield is modest and adverse-selection-dominated. | +| **Binary YES+NO arbitrage** | ❌ dead | Efficient — min observed sum was 1.001 (the spread). Closed instantly by the engine. | +| **Multi-outcome logical arb** | ❌ dead | True partitions priced efficiently (min sum 0.999). Apparent "arbs" were non-exclusive market groupings. | +| **Cross-venue arb (Polymarket↔Kalshi)** | ❌ dead | Venues agree to ~1¢; locking both legs costs **>$1 after fees**. Real gaps last ~seconds and are taken by bots. | +| **Insider / sharp detection** | ✅ **works** | Statistical improbability (z-score of wins vs. odds) is a real, hard-to-fake edge signal. See `insider.py`. | + +## The big technical findings + +**1. Win rate on Polymarket is survivorship-biased — badly.** +The platform only redeems *winning* shares; losing shares are worth $0 and sit +unredeemed in `/positions` at `curPrice 0` forever, never entering +`/closed-positions`. Measuring win rate over `/closed-positions` alone counts +almost only winners. We saw a wallet read **90.6%** that was truly **48.3%**. +A correct win rate must union both endpoints. *Lesson: a high reported win rate +is a red flag for a measurement bug, not a sharp.* + +**2. Win rate ≠ profit, and PnL ≠ reliability.** +A wallet winning 54% made millions; the all-time #1 wallet (43% win) was −$3.8M +over 90 days. Profit comes from sizing and entry prices, not hit rate. + +**3. The market is efficient.** Six systematic public-data edges, all closed or +illusory. There is no turnkey retail edge sitting in public data in 2026 — +durable edge requires *speed/infrastructure* (arb bots), *private information*, +or *getting paid to provide liquidity* (modest, adverse-selection-dominated). + +**4. The one real signal: statistical improbability (z-score).** +Each bet entered at price `p` has an odds-implied win probability `p`. A wallet +winning far more than `Σp` is beating the market's own pricing — measured as a +z-score and one-sided p-value. This is the rigorous version of the edge metric +the whole project was chasing. It distinguishes: +- **Sharps** — high z, normal entry timing (skill over many bets). +- **Insiders** — high z **+** late (pre-resolution) entry **+** fresh wallet. + +Plus **funding-cluster linking** (à la Bubblemaps / the 2026 *60 Minutes* +investigation): trace each wallet's USDC funders on Polygon and link wallets +that share a *personal* funding hub — judged by the funder's own outbound degree +so shared exchanges don't false-link everyone. (See `insider.py`.) + +## Practical conclusion + +- **Don't** fund copy-trading, LP farming, or arb based on this work — we tested + them and they don't clear. +- **Do** use `insider.py`'s z-score as a rigorous "who actually has edge" filter, + far better than leaderboard or win rate. +- A genuine money-making edge has to come from *you* — a niche you understand + better than the market — with tooling built around it, not from a public-data + scanner. +- **Legal note:** *detecting* suspected insider trading is fine; *trading on* + material nonpublic information is illegal, and blindly following a suspected + insider is not a safe strategy. + +## Repo layout + +- `insider.py` — the keeper: z-score/p-value detection, timing/freshness/sizing + signals, and Alchemy funding-cluster ring detection. +- `smart_money.py` — data foundation + dashboard (true-win-rate scanner). +- `archive/` — the strategies that didn't work, kept for reference. See + `archive/README.md`. diff --git a/README.md b/README.md index 653058d2..39c6f594 100644 --- a/README.md +++ b/README.md @@ -11,18 +11,14 @@ live), and backtest the strategy. Zero dependencies — Python 3 stdlib only ## Tools +**Read [`FINDINGS.md`](FINDINGS.md) first** — it's the honest scorecard of what +worked (almost nothing) and what does (`insider.py`). + | File | What it does | |------|--------------| -| `smart_money.py` | Dashboard + scanner. Ranks leaderboard wallets by **true** win rate. | -| `edge_research.py` | Scans up to ~2000 wallets for a reliable, copyable weekly edge (consistency metrics + copyability). | -| `lookback.py` | Deep-dive a short list over a long window, split into halves for out-of-sample reads. | -| `table_77.py` | Aggregate a filtered wallet set into one CSV (ROI, total staked, consistency). | -| `copytrade.py` | Copy-trade engine — mirror a watchlist (paper by default, live gated). | -| `backtest.py` | Replay a watchlist over a recent window and mark outcomes. | -| `lp_screener.py` | Rank reward-eligible markets by risk-adjusted LP yield (pool ÷ competition, penalized by volatility). | -| `lp_paper.py` | Paper liquidity-provision loop — simulate quoting on the live book, track **net = rewards − adverse selection**. | -| `xarb.py` | Cross-venue scanner — match the same event on Polymarket vs Kalshi and flag price gaps. | -| `insider.py` | Insider/sharp detector — flag wallets winning *above their entry odds* (z-score / p-value), with timing, freshness, and sizing signals. | +| `insider.py` | **The keeper.** Insider/sharp detector — z-score/p-value of wins vs. entry odds, pre-resolution timing, fresh-wallet & sizing signals, and Alchemy funding-cluster ring detection. | +| `smart_money.py` | Data foundation + dashboard. Ranks leaderboard wallets by **true** (survivorship-corrected) win rate. | +| `archive/` | Eight strategy tools that didn't clear (copy-trade, LP farming, cross-venue arb, wallet-consistency research). Kept for reference — see [`archive/README.md`](archive/README.md). | ## Run the dashboard diff --git a/archive/README.md b/archive/README.md new file mode 100644 index 00000000..5e84a974 --- /dev/null +++ b/archive/README.md @@ -0,0 +1,21 @@ +# Archive — strategies that didn't work + +These tools were built and tested during the research in +[`../FINDINGS.md`](../FINDINGS.md). They all proved to be dead ends (the market +is efficient / the metric was biased), so they're archived here for reference +rather than deleted. Each one *works* as written — it's the *strategy* that +didn't clear. They import `smart_money`/`copytrade` from the repo root, so to +run one you'd adjust the import path. + +| File | What it did | Why it's here | +|------|-------------|---------------| +| `copytrade.py` | Paper/live copy-trade engine — mirror a watchlist's entries/exits, % -of-bankroll sizing, price guard, per-position cap, Discord alerts. | Copying entries is −EV; followed wallets win ~50%. Backtested −48%. | +| `backtest.py` | Replay a watchlist over a window, mark outcomes from resolution. | The tool that proved copy-trading loses. | +| `edge_research.py` | Scan ~2000 wallets for reliable weekly consistency (% green weeks, profit factor, Sharpe). | "Consistent" wallets were mostly young accounts (survivorship); no durable edge. | +| `lookback.py` | Deep-dive a wallet list over a long window, split into halves for out-of-sample reads. | Showed the "best" wallets had <90 days of history. | +| `table_77.py` | Aggregate a wallet set to CSV (ROI, total staked, consistency). | Supported the above; ROI inversely related to size. | +| `lp_screener.py` | Rank reward-eligible markets by risk-adjusted LP yield. | The high APRs were illusory — see `lp_paper`. | +| `lp_paper.py` | Paper liquidity-provision loop: simulate quoting, track net = rewards − adverse selection. | Polymarket refunds unearned reward pool; thin-book "jackpots" don't pay. | +| `xarb.py` | Cross-venue scanner: match the same event on Polymarket vs Kalshi, flag price gaps. | Venues priced efficiently (~1¢); both legs cost >$1 after fees. | + +The keeper that came out of all this lives at the repo root: `insider.py`. diff --git a/backtest.py b/archive/backtest.py similarity index 100% rename from backtest.py rename to archive/backtest.py diff --git a/copytrade.py b/archive/copytrade.py similarity index 100% rename from copytrade.py rename to archive/copytrade.py diff --git a/edge_research.py b/archive/edge_research.py similarity index 100% rename from edge_research.py rename to archive/edge_research.py diff --git a/lookback.py b/archive/lookback.py similarity index 100% rename from lookback.py rename to archive/lookback.py diff --git a/lp_paper.py b/archive/lp_paper.py similarity index 100% rename from lp_paper.py rename to archive/lp_paper.py diff --git a/lp_screener.py b/archive/lp_screener.py similarity index 100% rename from lp_screener.py rename to archive/lp_screener.py diff --git a/table_77.py b/archive/table_77.py similarity index 100% rename from table_77.py rename to archive/table_77.py diff --git a/xarb.py b/archive/xarb.py similarity index 100% rename from xarb.py rename to archive/xarb.py diff --git a/insider.py b/insider.py index edaa30bd..b7f96c4f 100644 --- a/insider.py +++ b/insider.py @@ -358,8 +358,8 @@ def main(): def sm_load_key(): try: - from copytrade import load_json - return load_json("config.json", {}).get("alchemy_key", "") + with open("config.json") as f: + return json.load(f).get("alchemy_key", "") except Exception: return ""