2026-06-18 Β· 9f68c4a
Docs / 8 Β· CLV & Odds Data

08 β€” Closing Line Value & Odds Data

TL;DR. Closing Line Value (CLV) β€” did our number beat the line at kickoff β€” is the gold-standard measure of betting skill (see Doc 1 Β§5 and Doc 6). The math is built and tested (in the probability model), and three tools wire it up. The blocker is data: computing real CLV needs opening and closing lines, which the free archives no longer hand out automatically and which don't exist yet for a season that hasn't started. This doc records what's available, where to get it, and exactly how to run the tools once you have it.


1. Why CLV, in one paragraph

By kickoff the line has absorbed all information and the week's biggest limits, so the closing line is the most efficient public predictor of a game. If we consistently bet numbers better than the close, we extracted value before the market got sharp β€” the statistical signature of edge, independent of whether any single bet won. Over small samples, win/loss is noise; CLV is the stable signal. So the right question isn't "did we win?" β€” it's "did the line move toward us after we'd have bet it?"

To answer that we need two numbers per game: the line when we bet (β‰ˆ the opening / early line) and the line at close. One number (what spreadspoke and most free datasets give) is not enough.


2. Is the data available? (As of 2026-05)

Not for free, and not yet. Three findings from a direct investigation:

  1. It's the offseason. First 2026 kickoff is 2026-09-10, and the posted look-ahead lines are completely static (0 of 16 Week-1 lines moved over seven weeks). There is no "closing" line and no movement to measure yet.
  2. Free open/close archives are now blocked from automated download. sportsbookreviewsonline.com (historically the best free open+close archive) now redirects to an affiliate landing page, and aussportsbetting.com returns 403 to scrapers (browser download only).
  3. The free online source doesn't serve open/close for completed games β€” only a pre-match moneyline and a per-provider, undocumented, recent-only movement endpoint (.../odds/{providerId}/history/0/movement). The historical scores dataset stores a single closing-ish number.

So a historical CLV backtest needs a manual browser download of an open/close file, or a paid feed. Live CLV only accrues in-season, via snapshots.


3. Where to get open/close data

Free (manual download β€” sites block scrapers)

Source Has Notes
aussportsbetting.com Open & close line + total, results, ~2006β†’present Best free option; download the NFL .xlsx in a browser
sportsbookreviewsonline.com Historically open+close 2007–2024 Currently redirecting / effectively dead β€” check before relying on it
Kaggle (Crabtree), nflverse Single pre-game line only Not usable for CLV (no separate open/close)
Source ~Price Notes
The Odds API (Business) ~$99/mo Historical snapshots back to 2020 (5-min), includes Pinnacle; reconstruct the close from the pre-kickoff snapshot. Cheapest Pinnacle-inclusive path.
SportsGameOdds free tier / $99–499 Explicit "closing odds", incl. Pinnacle
Goalserve low indie tiers Explicit open/close columns
SportsDataIO quote Labeled open+close+all changes, NFL since 2019
OddsJam / OpticOdds / Unabated / Sportradar $500 β†’ $3,000+/mo Enterprise; overkill

Pinnacle's own API has been closed to the public since July 2025 β€” get Pinnacle (the sharpest close) only indirectly via the aggregators above.


4. The tools

The CLV math itself lives in the probability model (clv_points, clv_winprob_delta), with its own unit tests.

Forward capture (works today)

Snapshots the market near kickoff to local snapshot storage. Uses The Odds API if ODDS_API_KEY is set, else a free online source (no key).

# Run ~15-30 min before each game window, in-season:
capture closing lines --week 1
capture closing lines --week 1 --source espn   # force the free online source

The latest snapshot per week is the "close"; our weekly bets file already records the line we "took." Schedule it alongside the weekly regen (see Doc 7 / the Thursday task).

Normalize a downloaded archive

Turns a manually-downloaded open/close spreadsheet into the schema the backtest reads. Fuzzy-matches the aussportsbetting / SBR column layouts (full team names β†’ abbreviations, home line β†’ home-margin convention).

import odds archive <downloaded>.xlsx
# -> normalized open/close CSV

Output schema: season, week, date, home_team, away_team, home_score, away_score, open_home_margin, close_home_margin, open_total, close_total (home-margin: positive β‡’ home favored by that many).

The real CLV test

Bets into the OPENING line and scores value vs the CLOSE. Reports average CLV, % of bets with positive CLV, and win-vs-open, for spreads and totals.

clv backtest --edge-spread 2 --edge-total 3

Positive average CLV β‡’ when our model disagrees enough to bet, the market tends to move toward us by kickoff β€” evidence of edge.

The local odds-archive and snapshot directories are gitignored (local data / manual downloads).


Backtest CLV (one-time, free): 1. Download the aussportsbetting NFL .xlsx in a browser into the local odds archive. 2. Run the archive-import tool on the downloaded file. 3. Run the CLV backtest.

Capture CLV (going forward, free): 1. Set ODDS_API_KEY (optional, for Pinnacle) β€” otherwise a free online source is used. 2. Schedule the closing-line capture near kickoffs each week. 3. Compare the line we took (in the weekly bets file) to the closing snapshot.

Cheapest path to a true Pinnacle close without manual work: The Odds API Business (~$99/mo) β€” a small adapter to pull the first and pre-kickoff snapshots per game would let the CLV backtest run on real open/close automatically.


← Back to the series overview Β· see also Doc 6 β€” Betting Strategy & Bankroll.