Skip to main content

Modelled closing line for tracked bets

Date: 2026-08-31. Status: design approved in principle; model choices and caps are set by the backtest in v3/cmd/closebacktest.

Problem

A Terminal-tracked bet gets its CLV from the reference book’s closing price for the exact line it was tracked at. When that line is not on the book’s closing board the bet has no CLV. After the exact-close fixes (oddsapi #442, hub #1028) the remaining misses are lines the book no longer quoted at close: the main line moved (basketball median move 4 pts against a stored window of 2.5 pts), single-line markets (NFL, team totals, tennis totals, most player props), or a market with no capture for that book. Goal: every tracked bet gets a CLV, with an honest label and a measured error.

What the capture gives us

historical.closing_odds holds, per book and market, a WINDOW of lines around the closing main line (basketball 11 rungs, football 7, halves/corners 5, NFL / team totals / tennis totals / most props 1), each with both sides priced. The 1X2 / ML is captured too. There is no full board.

Model

Every lined market is a bet on an integer latent quantity X: total points or goals (totals), or home margin (spreads, threshold -line). A rung of the ladder is then (threshold t, fair price for “X above t”, fair price for “X below t”), the fair prices from the shared LOG de-vig (utils.NoVigFromRow). Fair price of a line under a distribution D over the integers, with pushes and quarter lines handled exactly: split the line into its components (a quarter line is two half stakes on the adjacent half and whole lines), then fair = 1 + sum(P(lose)) / sum(P(win)) over the components. This is the identity bettors use, not an approximation. Two distribution families, chosen per sport by the backtest:
  • Normal with continuity correction (mean, sd): basketball, American football, tennis games, handball, volleyball, esports maps, yards-type props.
  • Poisson family: Poisson(lambda) for goal/run/corner/card totals and count props; Skellam for goal-margin spreads, with the goal total taken from the event’s own totals ladder when present, else a sport prior.
Fitting: minimise squared error between model and de-vigged implied probabilities across the ladder (Nelder-Mead over the family’s parameters). With a single rung only the location is fitted; the dispersion comes from a prior table per (sport, market family) that the backtest itself calibrates (median fitted dispersion across multi-rung ladders). Prediction: evaluate the fitted distribution at the bet’s line and side.

Tiers and labels

  1. exact: quoted line at the reference book (existing).
  2. derived: identities on quoted markets (DNB / Double Chance from 1X2; quarter line from its two halves when both are quoted). Exact.
  3. modeled: the fitted distribution evaluated at the bet’s line. Stored with the anchor (closing main line and its fair price), the distance from the nearest quoted rung, and the family used. Shown as “est.” in the tracker, with the hover text naming the main line it was priced from. Excluded from odds-verified on public records; filterable in stats.
  4. Refused: no reference market rows for the event, or distance beyond the per-sport cap set from the backtest.

Where it lives

Go only, in v3/closemodel, called from resolveSettlementOutcome after the exact and derived attempts fail. The hub stores closingSource and the anchor fields and renders them; it does not reimplement the model (live CLV for open bets keeps refusing until an endpoint exposes the model).

Backtest (this is what makes “accurate” a measured claim)

v3/cmd/closebacktest reads recent Pinnacle (and DraftKings prop) ladders from historical.closing_odds (read replica, read-only) and reports the CLV error of a predicted rung against its real de-vigged price:
  • Interpolation: leave one interior rung out.
  • Extrapolation: hold out the top 1..3 rungs of the window, predict from the rest. This is the real “line moved past the window” case.
  • Single anchor: fit on the main rung only with the prior dispersion, predict every other rung. This is the NFL / team total / prop case.
Reported per sport and market family: median and p90 absolute CLV error (%), signed bias, sample size, by distance in rungs. Caps and family choices come from these tables; anything without an acceptable error stays refused.