Real-time pulse of Polymarket — an order book feed that never freezes.
polypulse keeps a live, in-memory Polymarket order book over WebSocket, so reading
the best bid/ask is instant — with no per-read network round-trip. REST /book polling
pays its latency on every read (≈185 ms from a typical host, ≈19 ms warm when
colocated); polypulse pays a one-time subscribe, then updates are pushed.
It adds the production reliability the official tooling lacks: heartbeat, a
PONG-aware watchdog that detects the silent WS freeze (issue #292),
exponential-backoff reconnect, and an optional REST fallback.
pip install polypulseimport asyncio
from polypulse import BookFeed
async def main():
feed = BookFeed(["<token_id>"])
asyncio.create_task(feed.run()) # connects, reconnects, self-heals
await asyncio.sleep(2)
print(feed.best_bid("<token_id>"), feed.mid("<token_id>")) # 0 ms, in-memory
feed.stop()
asyncio.run(main())No token_id yet? Find active markets and their tokens via the Gamma API:
from polypulse import list_markets, tokens_for_slug, BookFeed
markets = list_markets(tag="weather") # active markets (tag is optional)
tokens = tokens_for_slug(markets, markets[0].slug) # the token ids for one market
feed = BookFeed(tokens) # ...now stream themOr from the terminal:
polypulse markets --tag weatherREST /book polling pays per-read latency and serves a book that is ~1 s stale.
Polymarket's WebSocket can also silently freeze — the connection stays open but
events stop. polypulse pushes updates as the book changes (no per-read latency) and
guarantees liveness with a watchdog that reconnects the moment the socket goes quiet.
BookFeed(token_ids, on_update=None, *, ping_interval=10, watchdog_timeout=30, rest_fallback=True, max_backoff=30, rest_poll_interval=1.0, logger=None)
best_bid / best_ask / mid / spread (token_id)— sync, no networkbook(token_id)— full-depthOrderBooksnapshotstaleness(token_id),source(token_id)— freshness introspectionawait run()/stop()
- Reads are synchronous and never hit the network — they return whatever the
background
run()task has most recently applied. source(token_id)is"ws"when the latest update came from the live socket, or"rest"when it came from the REST fallback (used only while the WS is down).staleness(token_id)is seconds since that token last updated.on_updatefires on WebSocket events only. While the socket is down, the REST fallback keeps the book fresh for readers (best_bidetc.) but does not invoke the callback; on reconnect you get a freshbooksnapshot (which does fire it).stop()signals shutdown and closes the active connection sorun()returns promptly.
python -m polypulse benchmarkIt picks a live market and compares REST /book time-to-first-byte against the
WebSocket feed. Example run (from a non-colocated host — your absolute numbers depend
on where you run it):
market: highest-temperature-in-karachi-on-june-29-2026 (11 tokens)
REST /book TTFB: median 184.5ms min 124.4 max 238.3 (n=8)
WS subscribe → first book: 220.6ms
WS updates in 30s: 130 (4.3/s)
=== verdict ===
REST pays ~185ms EVERY read; WS pays 221ms ONCE, then updates are PUSHED (no per-read latency).
Absolute latency drops sharply when colocated (a eu-west-2 host measured ~19 ms warm REST GETs), but the structural win holds everywhere: REST pays its round-trip on every read; the WS feed pays once.
polypulse watch <token_id>Prints top-of-book once a second — a quick sanity check that the feed is live:
3414098972... bid=0.012 ask=0.024 mid=0.018 src=ws
3414098972... bid=0.012 ask=0.024 mid=0.018 src=ws
Values tick as the market moves; src shows ws or rest (REST fallback). An
animated GIF reads even better here — record one to drop in.
polypulse was extracted from a live Polymarket trading bot. The trading edge didn't
pan out, but the low-latency feed is solid and battle-tested — so here it is. Out of
scope (for now): generic multi-CLOB support, book integrity hashing, indicators.
MIT.