A Python library for fetching historical trade data from Polymarket, with built-in OHLCV + VWAP price series computation.
# With pandas
pip install "polymarket-data[pandas]"
# With polars
pip install "polymarket-data[polars]"
# Both
pip install "polymarket-data[all]"
# Chainlink Data Streams websocket support
pip install "polymarket-data[chainlink]"Requires Python 3.11+. The core package has no mandatory dependencies —
pandas and polars are optional extras loaded only when you pass
backend="pandas" or backend="polars".
from datetime import datetime, timezone
from polymarket_data import PolymarketData
pm = PolymarketData()
# Hourly OHLCV + VWAP bars for the Yes outcome
bars = pm.price_series(
slug="russia-x-ukraine-ceasefire-by-february-28-2026",
start_time=datetime(2026, 2, 17, tzinfo=timezone.utc),
end_time=datetime(2026, 2, 20, tzinfo=timezone.utc),
freq="1h",
outcome="Yes",
backend="pandas",
)
# timestamp (index) | open | high | low | close | vwap | volume | trade_countSee examples/tutorial.ipynb for a full walkthrough.
All methods accept outcome (label string, e.g. "Yes") or
outcome_index (integer, e.g. 0) to select which side of a market to
query. The default is outcome_index=0.
Resolve a market slug to its metadata.
market = pm.get_market("will-donald-trump-win-the-2024-us-presidential-election")
# market.question → "Will Donald Trump win the 2024 US Presidential Election?"
# market.outcomes → ["Yes", "No"]
# market.token_ids → ["<yes-token-id>", "<no-token-id>"]Return every filled trade for a single outcome as a DataFrame.
trades = pm.fetch_trades(
slug="...",
start_time=datetime(2024, 10, 28, tzinfo=timezone.utc),
end_time=datetime(2024, 10, 29, tzinfo=timezone.utc),
outcome="Yes", # or outcome_index=0
backend="pandas", # or "polars"
)| Column | Type | Description |
|---|---|---|
timestamp |
datetime (UTC) | Fill time |
price |
float | USDC per share [0, 1] |
size |
float | Shares traded |
side |
str | "BUY" or "SELL" |
outcome |
str | Outcome label |
Aggregate trades into OHLCV + VWAP time bars.
bars = pm.price_series(
slug="...",
start_time=...,
end_time=...,
freq="1h", # pandas-style offset string
outcome="Yes",
fill_gaps=True, # include empty bars with NaN prices, zero volume
backend="pandas",
)| Column | Description |
|---|---|
open |
First trade price in the interval |
high |
Highest trade price |
low |
Lowest trade price |
close |
Last trade price |
vwap |
Σ(price × size) / Σ(size) |
volume |
Total shares traded |
trade_count |
Number of fills |
The timestamp is the index for pandas and the first column for polars, aligned to natural UTC boundaries (e.g. full hours, midnight).
Supported frequency strings: "1h", "4h", "1d", "5min", "1w", etc.
| Source | Used for |
|---|---|
| Gamma API | Market metadata (slug → token IDs) |
| Goldsky subgraph | Historical filled trades |
Polymarket BTC Up/Down markets resolve against the Chainlink BTC/USD Data
Stream, product name BTC/USD-RefPrice-DS-Premium-Global-003.
The Chainlink stream requires Data Streams credentials and the full feed ID. Set:
export STREAMS_API_KEY="..."
export STREAMS_API_SECRET="..."
export CHAINLINK_BTC_USD_FEED_ID="0x..."Then run:
python examples/stream_chainlink_btc.pyIf your Chainlink account uses a production websocket host, set it explicitly:
export STREAMS_WS_HOST="..."The example below compares three BTC 5-minute Up/Down market makers: fixed volatility, EWMA realized volatility, and a hybrid EWMA/range-vol model that widens quotes during jumps.
python examples/volatility_btc_updown_backtest.py