Closing Line Value: What It Is and How to Measure It

Why the closing price is the benchmark for any betting model, and how to measure CLV from odds history.

By the HoopsAPI team · Updated

Closing line value (CLV) is how much better your odds were than the market's fair price just before the game started: CLV = your odds / fair closing odds − 1. It is the most widely used test of whether a betting model or tipster has a real edge, because it gives an answer after a few hundred bets, long before profit and loss can.

What is the formula for closing line value?

CLV
CLV = your odds / fair closing odds - 1

“Fair” means the closing odds with the bookmaker's margin removed (see how to remove the margin). Example: you bet the home team -4.5 at 2.10. At tip-off the reference bookmaker prices that line at 1.95 / 1.95, a fair price of 2.00 for each side. Your CLV is 2.10 / 2.00 - 1 = +5%.

A positive CLV means you got a better price than the market's best final estimate. If the closing price is accurate, a bet with +5% CLV returns 5% on average over the long run, whether this particular bet wins or loses.

Why use the closing line instead of profit?

By tip-off, the price has absorbed team news, line-ups and the money of the sharpest bettors. In liquid markets such as the NBA, closing prices are very hard to beat, so they are the best available estimate of the true probability.

Profit is a much noisier measure. A handicap bet is close to a coin flip, so over 100 bets at around 2.00 the return has a standard deviation of roughly ±10 percentage points: a model with no edge at all can easily show +10%, and a good one can show a loss. CLV strips most of that luck out, because it measures the price you got rather than how the game ended. Two caveats:

  • Bets are not always independent. Several bets on the same game (different lines or markets) win and lose together. Measure CLV and results per game, not per bet, or the uncertainty will look smaller than it is.
  • The close is only as sharp as the market. In lower leagues and on alternate lines, closing prices are set with less money behind them. Check CLV against actual results there, not only against the close.

How do I measure CLV with the API?

You need two things for each bet: the closing odds on the same line, and a sharp reference bookmaker to take them from. HoopsAPI keeps both.

Option 1: closing odds of finished games

After a game starts, GET /v1/games/{game_id} returns it with status: "archived" and every bookmaker's closing odds, with every alternate line under lines:

closing odds for one bet
import requests

API = "https://hoopsapi.com/api/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}

def power(odds):
    lo, hi = 1.0, 3.0
    while hi - lo > 1e-10:
        k = (lo + hi) / 2
        lo, hi = (k, hi) if sum((1 / o) ** k for o in odds) > 1 else (lo, k)
    return [(1 / o) ** k for o in odds]

def clv(game_id, reference, line, side, my_odds):
    """CLV of a full-game handicap bet against the reference bookmaker's close."""
    game = requests.get(f"{API}/games/{game_id}", headers=HEADERS).json()
    for s in game["lines"]["ft"][reference]["spread"]:
        if s["line"] == line:
            fair = power([s["home"], s["away"]])
            fair_odds = 1 / fair[0 if side == "home" else 1]
            return my_odds / fair_odds - 1
    return None  # the reference bookmaker didn't offer that line at the close

print(clv(1637808609, "pinnacle", -4.5, "home", 2.10))

Option 2: the full price history

GET /v1/games/{game_id}/history (Data plan) returns every price change, newest first. It also lets you measure how the price moved after your bet, and what CLV you would have had at any earlier moment:

price history
GET /v1/games/1637808609/history?provider=pinnacle&market=spread&period=ft

{
  "game_id": 1637808609,
  "count": 214,
  "changes": [
    { "provider": "pinnacle", "market": "spread", "period": "ft",
      "line": -4.5, "outcome": "home", "price": 1.95, "at": "2026-10-13T15:58:02Z" },
    ...
  ]
}

The closing price of a line is its last change before start_time. See the historical odds API for what is stored and for how long.

How should I read my CLV?

  • Track the average per game with a confidence interval. If it stays clearly above zero over a few hundred games, the edge is very likely real.
  • Check that the prices were really available. A price that vanished seconds after you saw it shows great CLV but could never have been bet. Recording the price again a minute or two later is a cheap check.
  • Compare CLV with results as they arrive. Over enough games, profit should drift towards what CLV predicts. If it consistently falls short, the closing line you are using is not as sharp as assumed.

Try it with real data

The free plan includes 10 requests a day across every league and market. No credit card.