DEV Community

Aurelix Solutions
Aurelix Solutions

Posted on

Polymarket odds as data, and a daily list of the markets that moved, in Python

Prediction markets put a number on questions people usually argue about in words: will the Fed cut in December, who wins a nomination, does a bill pass. If you write a newsletter, run a research desk or feed a dashboard, the useful part is rarely one price. It is the list of prices, every morning, and the handful that moved since yesterday.

This post pulls Polymarket's odds into flat rows in Python and turns them into a daily "what moved" list.

Disclosure: I'm Aurelix, and I built the Polymarket Odds Tracker. It's a paid tool (prices below). It is a read-only data tool: it never trades, and nothing here is betting or investment advice.

What each row holds

The source is Polymarket's official public market data, no key or login. One row per market outcome (a yes/no market is two rows):

  • event_title, question, outcome, group_item_title (the short label in a multi-market event, such as a candidate).
  • price from 0 to 1, read as an implied probability, and probability_pct; best_bid, best_ask, spread, last_trade_price, price_change_24h.
  • volume, volume_24h, liquidity in USD, start_date, end_date, status, and for finished markets resolved_outcome plus result (won / lost).
  • market_url, market_id, condition_id, token_id and a stable row_id (market_id:outcome_index).

No wallets, usernames, comments or holder lists: only market-level data.

A daily list of moves

Turn on incremental with a threshold in percentage points. Each run remembers the price it last returned for every outcome and comes back with new markets and outcomes that moved at least that much, with previous_price and price_move. Unchanged outcomes are skipped and not charged.

import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("aurelix/polymarket-odds-tracker").call(run_input={
    "tags": ["politics"],
    "status": "open",
    "minVolume": 100000,
    "maxResults": 1000,
    "incremental": True,
    "changeThreshold": 5,
    "stateKey": "politics-moves-daily",
})
rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())

moved = sorted((r for r in rows if r.get("change") == "moved"), key=lambda r: -abs(r["price_move"]))
for r in moved[:10]:
    print(f"{r['question'][:70]} | {r['outcome']}: {r['previous_price']:.0%} -> {r['price']:.0%}")
print(f"{sum(r.get('change') == 'new' for r in rows)} new outcomes, {len(moved)} moved")
Enter fullscreen mode Exit fullscreen mode

The first run returns everything that passes the filters and sets the baseline; from then on, schedule it daily in the Apify Console and you get only the changes. Add slackWebhookUrl for a short digest in a channel.

Price history for a chart

run = client.actor("aurelix/polymarket-odds-tracker").call(run_input={
    "urls": ["https://polymarket.com/event/presidential-election-winner-2028"],
    "maxResults": 40,
    "priceHistory": True,
    "historyInterval": "1m",
    "historyFidelity": 1440,
})
points = [r for r in client.dataset(run["defaultDatasetId"]).iterate_items() if r["row_type"] == "price_history"]
Enter fullscreen mode Exit fullscreen mode

Each point is one row with time (UTC), price and probability_pct, plus the outcome and market IDs, so a pivot on time x outcome is a chart. Ranges run from the last hour to the market's whole life; the step is in minutes.

Resolved markets for calibration

Set status to closed and a minimum volume: every finished market comes back with the winning outcome and won / lost on each row, enough to check how often a 70% price came true.

Limits

  • One source, Polymarket, read-only, as its public APIs report it.
  • Bid/ask and 24-hour change are quoted for the first outcome and mirrored for the second of two-outcome markets; markets with three or more outcomes leave them empty for the rest.
  • Listing depth: a tag or the top-markets list reaches its 2,100 busiest markets; add keywords, more tags or a minimum volume for more.
  • No order books, trades or wallet data. Not betting or investment advice, and it says nothing about where trading on Polymarket is available.

Cost

You pay per outcome row written, plus a small start fee; price-history points are charged separately and cost much less per row. Unchanged outcomes in the daily mode are free, so a quiet day costs about the start fee. Current prices are on the Store page; Apify's free plan includes $5 of credit a month.

Links

Top comments (0)