Use case: models and backtesting
Historical odds data for betting models and backtesting
A model needs three things from a feed: how prices moved, where they closed, and what actually happened. The feed records the first two for every Australian book it reads and grades the third on every finished event.
Start date, up front. Price history recording began on 14 August 2026. If you need several past seasons to backtest today, this archive is too young for that. If you are building something that will run from here on, the archive grows with every game and starts working for you immediately.
What is recorded
Every change, one event at a time
/v1/odds/history (Pro) returns each recorded change for one event, oldest first, over a window of up to 24 hours. Every change names the bookmaker, the market and the outcome, when it was seen, and what kind of change it was:
- opened
- The first price seen for that book and outcome.
- changed
- The price moved.
- withdrawn
- The price was taken down, so its
decimal_oddsis null.
Each change carries the decimal price, the implied probability and the line, with the market's period and subject (the player, for props), so it reads on its own. Each line is its own market, so a line move shows as the old line withdrawn and the new one opened. Narrow requests with markets and bookmakers: a busy NFL game can record tens of thousands of changes in a day.
Read it honestly
Gaps mean unrecorded, not unchanged
No collector catches every change on every bookmaker, and the history says so rather than smoothing it over. Treat a gap between changes as a period nobody saw, not proof the price sat still. A busy window comes back in pages: follow links.next until it is null.
For a quick summary, ask one event's odds with snapshots=opening,closing (Pro) and every outcome gains its first and last recorded price at each book.
Results stay. /v1/results grades finished games outcome by outcome (won, lost, void or dead heat) on the same outcome IDs as the prices, and /v1/events with a starts_after and starts_before window lists older games. Those verdicts become your labels.
import os
import requests
def open_and_close(event_id: str, markets: str = "winner") -> dict:
"""First and last recorded price at each bookmaker, per outcome, for one event (Pro)."""
r = requests.get(
f"https://api.sockodds.com/v1/events/{event_id}/odds",
params={"markets": markets, "snapshots": "opening,closing"},
headers={"Authorization": f"Bearer {os.environ['SOCKODDS_KEY']}"},
timeout=30,
)
r.raise_for_status()
prices = {}
for book in r.json()["data"]["bookmakers"]:
for market in book["markets"]:
for o in market["outcomes"]:
first, last = o.get("opening"), o.get("closing")
if first and last:
prices[(book["key"], o["name"], o["line"])] = (first["decimal_odds"], last["decimal_odds"])
return prices
# {("sportsbet", "Carlton", None): (1.70, 1.62), ...}
Closing line value
The test that matters
The closing price is the market's last and best-informed view before the game. Measuring the price you took against it is the standard check on whether a model finds real value:
CLV = price taken ÷ fair closing price − 1
Take the closing quotes from a sharp book or the exchange, remove the margin (how), and compare. A model that beats the close over hundreds of bets is usually finding something; one that does not is usually finding noise, whatever its short-run profit says.
Questions
History and modelling
How far back does the odds history go?
To 14 August 2026, when recording started. Each history request covers up to 24 hours of one event, so step through a longer span a day at a time.
Which plans include history?
Pro. Results and finished events are on every plan, so you can collect outcomes and your own price snapshots from the start.
Can I use fair odds as a training label?
Yes, and it is a good one: the closing Pinnacle or Betfair Exchange price with the margin removed is a sharp, margin-free estimate, which makes a sensible calibration target alongside the actual result.
Is every price change captured?
No, and the API does not pretend otherwise. Gaps are unrecorded periods, not proof the price sat still.
Start now
Your first Australian price is one request away.
Free key, no card, AFL and NRL included. Keys are issued on sockodds.com.