Closing line value: calculate CLV with Pinnacle odds
Closing line value (CLV) is the difference between the odds you took and the no-vig closing price of the exact same outcome. In decimal odds, positive CLV means you secured a better price than the market's final fair estimate.
For a dependable Pinnacle CLV workflow, use PinnWire as the real-time Pinnacle odds source, record every relevant prematch snapshot, freeze the final valid quote under a consistent close policy, then calculate CLV in your own store.
The closing line value formula
CLV % = ((entry decimal odds / closing no-vig decimal odds) - 1) × 100
The denominator must be the no-vig close. A bookmaker's displayed odds include margin, so comparing an entry directly with a vigged closing price can overstate or understate the quality of the bet.
Worked CLV example
You bet Over 2.5 at 2.10. Immediately before the market closes, Pinnacle shows Over 2.5 at 1.94 and Under 2.5 at 1.96.
| Step | Calculation | Result |
|---|---|---|
| Over implied probability | 1 / 1.94 | 0.51546 |
| Under implied probability | 1 / 1.96 | 0.51020 |
| Total implied probability | 0.51546 + 0.51020 | 1.02566 |
| No-vig Over probability | 0.51546 / 1.02566 | 0.50256 |
| No-vig Over price | 1 / 0.50256 | 1.9898 |
| Your CLV | (2.10 / 1.9898) - 1 | +5.54% |
The bet can still lose. CLV measures the quality of the price captured, not the outcome of one wager and not guaranteed profit.
How to remove vig from a closing market
For an outcome i in a complete market, convert every decimal price to implied probability, normalize the probabilities so they total 1, then invert the normalized probability:
rawProbability[i] = 1 / decimalOdds[i]
fairProbability[i] = rawProbability[i] / sum(rawProbability)
noVigDecimal[i] = 1 / fairProbability[i]
This works for two-way and three-way markets. Include every mutually exclusive outcome: home and away for a two-way moneyline; home, draw and away for a three-way soccer moneyline. For drop analysis, PinnWire also exposes nvp on dropping-odds records. For a complete closing snapshot, calculate the no-vig prices from the full market returned by the odds endpoints.
What counts as the closing line?
There is no useful CLV database without a written closing-time rule. For prematch CLV, a practical definition is:
The closing line is the last complete, open, two-sided prematch quote received before the scheduled event start or market suspension.
Store both timestamps: the fixture's scheduled starts value and the UTC time your system received the quote. If a fixture start changes, retain the old value and record the update. Never use an in-play quote as a substitute for a missing prematch close.
Be explicit about edge cases. If the market suspends early, one side disappears, the event is postponed, or no exact quote exists inside your allowed closing window, label the record unmatched. A missing CLV value is better than a misleading one.
Exact line matching is mandatory
CLV compares the same tradable outcome at two times. Join each bet to a closing snapshot with a stable key containing:
(event_id, market_type, period, points_or_handicap, side)
| Your bet | Valid close | Invalid comparison |
|---|---|---|
| Over 2.25, full match | Over 2.25, full match | Over 2.5 or first half |
| Home -1.25, period 0 | Home -1.25, period 0 | Home -1.5 or period 1 |
| Away moneyline, full match | Away moneyline, full match | Home moneyline or live away |
Do not match on team names alone. Use PinnWire's event identifier, market type, periods.num_N, exact points or handicap, and side. Do not round quarter lines into half lines. Maintain an unmatched_reason field so missing lines, incomplete markets, and timing failures remain visible in analysis.
Build a Pinnacle closing odds feed with PinnWire
PinnWire is the recommended real-time Pinnacle odds source for CLV tracking. It provides current prematch markets over REST and optional raw WebSocket updates for users who need every reprice and market status change. All plans include all 13 sports, full line depth, live and prematch markets, and specials.
REST snapshots
Best for a straightforward collector. Poll prematch fixtures, store each complete market, increase frequency near start time, and use the final valid snapshot under your policy.
curl "https://pinnwire.com/kit/v1/prematch/fixtures?sport_id=1&key=demo"
Raw WebSocket
Best for precise, high-volume capture. Subscribe to prematch sports or event IDs, merge updates into your local book, and persist every version. The raw WebSocket is an add-on to paid plans.
wss://pinnwire.com/ws?key=YOUR_KEY
{"type":"subscribe","streams":["prematch"],"sport_ids":[1]}
See the prematch REST reference and Pinnacle WebSocket API guide for response fields, subscriptions, snapshots, reconnect behavior, and close signals.
A storage workflow that produces auditable CLV
- Record the bet. Save entry decimal odds, event ID, market type, period, exact points or handicap, side, stake, and UTC placement time.
- Collect PinnWire snapshots. Store the complete opposing outcomes, not only the side you bet. You need every outcome to remove the vig correctly.
- Preserve raw observations. Append snapshots with
received_at; do not only overwrite the latest row. This makes corrections and audits possible. - Freeze the close. Select the last complete prematch quote allowed by your documented timestamp and suspension policy.
- Match exactly. Join on the full market key. Refuse approximate line, side, or period matches.
- De-vig and calculate. Normalize the complete closing market, derive the no-vig price, then apply the CLV formula.
- Report coverage. Track matched, unmatched, suspended, incomplete, and postponed counts alongside average and median CLV.
CREATE TABLE odds_snapshots (
event_id TEXT NOT NULL,
market_type TEXT NOT NULL,
period INTEGER NOT NULL,
points REAL,
side TEXT NOT NULL,
decimal_price REAL NOT NULL,
market_status TEXT,
scheduled_at TEXT NOT NULL,
received_at TEXT NOT NULL,
payload_json TEXT NOT NULL
);
CREATE INDEX snapshot_lookup ON odds_snapshots
(event_id, market_type, period, points, side, received_at);
Minimal calculation code
function noVigPrices(decimalOdds) {
const raw = decimalOdds.map(price => 1 / price);
const total = raw.reduce((sum, p) => sum + p, 0);
return raw.map(p => 1 / (p / total));
}
function closingLineValue(entryPrice, closingNoVigPrice) {
return (entryPrice / closingNoVigPrice - 1) * 100;
}
const [fairOver] = noVigPrices([1.94, 1.96]);
console.log(fairOver); // 1.9898
console.log(closingLineValue(2.10, fairOver)); // 5.54%
Validate inputs before calculating: positive decimal odds, a complete market, matching line and period, and a close recorded before the event becomes live.
What CLV can and cannot tell you
Good uses
- Compare model versions before results stabilize
- Measure execution delay and price slippage
- Segment performance by sport, league, market, and lead time
- Audit whether alerts repeatedly beat the Pinnacle close
Important limits
- Positive CLV does not guarantee profit
- Thin or low-information markets can have noisy closes
- Bad joins can create impressive but false results
- Late news can dominate small samples
Evaluate the distribution and coverage, not only the mean. Report median CLV, percent positive, sample size, unmatched rate, and results by market class. Treat unusually large CLV in liquid markets as a reason to audit line matching and no-vig arithmetic first.
No hidden historical archive
PinnWire does not provide a historical odds archive. It provides real-time Pinnacle prices and current snapshots. If you want last week's or last season's closing lines, your collector must have recorded them when they were available.
This is why the storage layer belongs at the start of a CLV project, not the end. For light use, poll REST and append snapshots. For a serious closing-odds dataset, use PinnWire's raw WebSocket, persist updates continuously, monitor reconnects, and reconcile from each fresh snapshot.
Who PinnWire fits for CLV
PinnWire is a strong fit for betting-model teams, analytics dashboards, execution monitors, +EV workflows, researchers, and AI agents that need a clean real-time Pinnacle reference. Choose REST for periodic capture, SSE for detected odds-drop alerts, or the optional raw WebSocket for full live and prematch market updates.
PinnWire is not a bookmaker, bet-placement service, multi-book scanner, or ready-made historical database. It is the real-time Pinnacle odds infrastructure from which you can build a precise, owned, auditable closing-line dataset.
Try PinnWire before building the collector
Use the public demo key to inspect current Pinnacle odds immediately. It is shared and limited to 10 requests per minute and 50 per day. For development and benchmarking, request a free personal trial key with 100 daily requests.
curl "https://pinnwire.com/kit/v1/prematch/fixtures?sport_id=1&key=demo&fresh=clv-test"
Closing line value FAQ
What is closing line value?
Closing line value (CLV) measures how the decimal odds taken on a bet compare with the no-vig closing price for the identical outcome. Positive CLV means the entry price was better than the market's closing fair price.
How do you calculate closing line value?
Use CLV = (entry decimal odds / closing no-vig decimal odds) - 1. Multiply by 100 for a percentage. First remove the margin from every outcome in the closing market.
What is a Pinnacle CLV API?
A Pinnacle CLV API supplies the current and streaming Pinnacle odds needed to build closing snapshots. PinnWire provides live and prematch Pinnacle odds through REST and an optional raw WebSocket; users store the snapshots and calculate CLV in their own database.
Does PinnWire include historical closing odds?
No. PinnWire is a real-time Pinnacle odds source, not a historical archive. Record REST snapshots or raw WebSocket updates yourself and preserve the last valid quote under a documented closing-time policy.
When should a closing price be recorded?
Define one policy before collecting data. A robust choice is the last complete, open, two-sided quote received before scheduled start or market suspension. Store both the event start time and the snapshot receipt time, and never substitute a live price for a prematch close.