Polymarket has thousands of markets. Their UI is built for depth on a single market — bet slip, orderbook, charts — not for scanning across the universe. If you want to ask "what dropped 20pp overnight" or "which crypto markets are sub-20¢ with real volume," there's no built-in view.
So I built one. It's free, it's static, it rebuilds from the public Gamma API every few hours, and the source is on GitHub. This post is how it works.
The data layer
The Polymarket Gamma API (https://gamma-api.polymarket.com/markets) is paginated and unauthenticated. The "active universe" is much smaller than the lifetime market count Polymarket advertises:
import requests
def fetch_active_markets():
out, offset = [], 0
while True:
r = requests.get(
"https://gamma-api.polymarket.com/markets",
params={"closed": "false", "limit": 500, "offset": offset},
timeout=30,
).json()
if not r:
break
out.extend(r)
offset += 500
return out
That pulls ~1,200 currently-tradable markets in 3 paginated calls. The other ~12,800 indexed are resolved or expired — useful for backtesting but not for a "what's moving now" screener.
Ranking: movers vs volume
Two top-of-page lists:
Top 24h movers: sorted by abs(one_day_change) descending, filtered to volume24hr > 1000 to drop dust.
Volume leaders: sorted by volume24hr descending. Mostly the same 8-10 megamarkets day-to-day (election props, BTC year-end), which is exactly why you need the movers view.
Crash signal: one_day_change <= -0.15 — a proxy for "fell off a recent local high." Backtested on a separate dataset (5,629 events, see cross-signal-data) at 73% mean-reversion rate, but the live screener column is a proxy not the same signal — caveats are in the repo's methodology discussion.
Why static + GitHub Pages
The screener regenerates as a flat HTML file every few hours via a single Python script. No backend, no database, no auth, no costs. The whole site is docs/index.html + per-market detail pages + a small CSS file. Deploy = git push. Total hosting bill = $0.
The tradeoff: data is up to a few hours stale. For a screener that's a feature, not a bug — you're scanning for setups, not executing in microseconds.
What I'd build next (and won't, alone)
- WebSocket layer for live price ticks on top of the static base
- Open-interest column (not in Gamma; needs CLOB orderbook crawl)
- Alerts: "ping me when any crypto market crosses 20pp overnight"
- A "movers within volume" intersection view (asked about it in Discussion #5 — feedback welcome)
Try it
- Live: https://luciferforge.github.io/polyscope/?utm_source=devto&utm_medium=article&utm_campaign=polyscope-week22
- Source: https://github.com/LuciferForge/polyscope
- Underlying historical dataset (separate $9 product if you want backtest data): https://manja8.gumroad.com/l/agyjd?utm_source=devto&utm_medium=article&utm_campaign=polyscope-week22
The screener itself stays free forever. The historical SQLite dataset (10.8M snapshots, 43+ days of depth) is what funds the hosting.
Top comments (0)