Date: 2026-05-28 Status: Complete — Phase 2 not justified
No. Copy-trading Polymarket's most consistently profitable wallets does not produce excess returns after realistic lag and slippage. The strategy fails the pre-set bar on every dimension of the sensitivity sweep.
A "yes, build Phase 2" decision required:
- Positive risk-adjusted return after realistic slippage, and
- Sharpe > 0 with tolerable max drawdown, and
- The result holds across ≥3 of 4 sensitivity buckets under walk-forward.
Single backtest (24 months, lag 15m, $1k per position, strict filter, watchlist top 100):
| Metric | Value |
|---|---|
| Eval window | 2024-06-01 → 2026-05-01 |
| Signals | 1,402 (1,384 resolved) |
| Capital deployed | $1,402,000 |
| Total P&L | −$8,706 |
| ROI | −0.62% |
| Sharpe | −0.13 |
| Max drawdown | 3.9% |
| Win rate | 54.8% |
Sensitivity sweep (108-cell grid, 4 dimensions):
| Dimension | Levels (mean ROI) | Holds? |
|---|---|---|
| Lag | 5m: −0.8% · 15m: −0.8% · 30m: −0.9% · 60m: −1.8% | fails |
| Size | $250: −0.3% · $1k: −1.4% · $5k: −1.4% | fails |
| Watchlist N | 20: −1.0% · 100: −1.1% · 500: −1.1% | fails (degenerate) |
| MM filter | strict: −0.9% · loose: +0.6% · off: −2.9% | fails |
Buckets held: 0 / 4 → not robust.
-
An edge exists, but it doesn't survive costs. The best cells (short lag + smallest size + loose filter) reach ~+1.5% over 23 months — roughly 0.8%/year, only at the smallest position size where slippage is least punishing. Every other corner of the grid is negative. The cost wall is binding.
-
The classifier earns its keep.
mmFilter off(copying everyone on the leaderboard) is consistently the worst — about −2.9% mean ROI. Filtering to smart-money matters; it's just that the filtered subset still doesn't beat costs at any realistic size. -
Win rate > 50% is not enough. The 54.8% win rate means the classifier did pick wallets that are right more often than not. P&L is still negative because losses are larger than wins (asymmetric payoffs). Being directionally right > 50% of the time ≠ being profitable to copy with lag and flat sizing.
-
Category split shows where the edge is and isn't.
- Sports: +$40,409 (919 bets) — a real signal
- Other: −$50,273 (456 bets) — wipes the sports edge out and then some
- Politics: +$789 · Crypto: +$369
-
Concentration risk. One wallet contributed +$20,708; several lost $6k–$9k each. The aggregate result hinges on a handful of wallets and bets, not a broad edge.
-
Universe selection bias. The 10
smart_moneywallets were sifted out of today's top-50 profit leaderboard — wallets selected on present-day prominence. The walk-forward ranking at each historical T is leak-free, but the candidate pool is not. If anything, this should make the result look better than reality; it didn't. -
Reconstructed leaderboards use realized-only profit, diverging from Polymarket's live realized+unrealized metric. Snapshots are tagged
source = 'reconstructed'vs'live'. -
Watchlist is thin. Only 0–4 wallets qualified as
smart_moneyat any given T (10 total in the universe, further narrowed by the 60-day-history requirement and as-of-T classification). The watchlist-size sweep dimension is therefore degenerate — there were never 20+ qualifying wallets, so the N=20/100/500 cells are identical. Inherent low-N noise. -
2024 was nearly empty — the universe's history doesn't sustain enough smart-money wallets in the back half of the eval window for the early-T watchlists to be populated.
-
Category breakdown is a keyword heuristic (no stored category column); approximate. By-wallet is the firmer concentration check.
-
MM/arb classifier rule ordering is a non-spec resolution (structural MM → arb → generic MM → smart) so all labels stay reachable; documented in
lib/backtest/filters.ts.
Phase 2 (live alerts, hosted infra, real-time integration) was conditional on a positive Phase 1 result. It is not justified by this data. Do not build it.
A "no" was always one of the two valid Phase 1 outcomes, and is just as informative as a "yes" would have been: a cleanly defensible answer to the question, achieved cheaply, before any capital was risked. The build worked exactly as designed — the result is the result.
- A wallet universe beyond the top-50 profit leaderboard (e.g. via
sync:tradeswith a low threshold to catch big directional bettors who don't rank). The slippage wall would likely still bind, but this would convert "no" into "definitively no." - Per-wallet position sizing weighted by historical win-rate / margin (rather than flat $1k). Could marginally tighten the edge but unlikely to break through the cost wall.
- Alternative exit logic beyond hold-to-resolution (e.g. partial exits, source-mirror with a delay). The
--source-exitflag exists; it was not the focus of the headline result. - Markets the classifier flagged as
unknown— the 24 unknowns include wallets with too little resolved history to judge. A longer collection window might surface a few more genuine smart-money wallets, but the sweep result suggests the universe-level edge is too small for that to flip the verdict.
npm install
npm run db:migrate
npm run sync:leaderboard
npm run sync:wallets -- --limit 50 # ~tens of minutes; pre-screen filters obvious bots
npm run sync:markets # Gamma at ~1 req/s; several minutes for ~30k markets
npm run classify:all
npm run backfill:leaderboard -- --from 2024-06-01 --to 2026-05-01
npm run backtest -- --from 2024-06-01 --to 2026-05-01 --lag 15 --size 1000
npm run backtest:sensitivity -- --from 2024-06-01 --to 2026-05-01See RUNBOOK.md for the full pipeline and flags.