2026-05-20 · data quality stale lines methodology

Detecting stale sportsbook lines: the three tells and how to filter them

Stale sportsbook prices are the single largest source of false +EV signals in betting models. A scanner says "+8.3% edge on Yankees -110 at SoftBook." You bet it. The book voids the bet citing "palpable error" or "obvious pricing error." The bet is dust. You blame the scanner; the scanner was just doing math on a number that wasn't real.

This post is about how to know that number isn't real BEFORE you click bet. Three structural tells, in order of reliability, plus the six-step filter we apply on every +EV and arbitrage candidate.

What "stale" actually means

A sportsbook line is stale when it's still displayed on the book's site but doesn't reflect the book's current pricing model. Three things produce this:

  1. CDN caching: the book's web page is served from a CDN edge that hasn't refreshed. You see yesterday's price; the book's risk engine knows about today's news but its lobby doesn't.
  2. Market suspension without removal: the book has internally suspended the market (injury news, review, weather) but the price is still on the page. The risk engine will reject any bet, but a passive scanner sees the price and counts it.
  3. Ingest lag in your aggregator: your odds aggregator hasn't polled the book recently. The price you're seeing is correct as of the last poll, but the book has already moved.

From the bettor's perspective, all three look identical: a price that produces apparent edge but won't actually let you bet at it.

The three tells, in order of reliability

1. Timestamp lag against peer books

Sharp anchor (Pinnacle, Circa) and the major US books update at different cadences, but they all update regularly. If Pinnacle has new data within the last 30 seconds and SoftBook hasn't moved in 8 minutes on the same event, SoftBook is almost certainly stale. Books that are alive don't go quiet for 8 minutes on a flagship market.

Implementation. Pull /v1/meta/source-quality per request cycle. Reject any +EV candidate whose underlying book is in degraded, breach, or stale state. The thresholds are at /v1/meta/per-book-sla: each book class (us_marquee, us_mid, dfs, exchange, monopoly_retail, international) has its own tight / slack / stale windows reflecting healthy cadence for that class.

2. Peer-book disagreement at high confidence

Liquid books rarely disagree by more than 4-6 cents on flagship markets when both are live. If SoftBook has Yankees -110 and four other US books have Yankees -135, -132, -130, -128, SoftBook is either stale OR you've found a real outlier; the prior heavily favors stale. The cluster of -128 to -135 is the real market; -110 is an artifact.

Spread of cluster (4 peers, cents)What it means
≤ 8 centsHealthy disagreement. An outlier 15+ cents from the cluster is almost certainly stale.
9-20 centsMarket in transition (post-news, late-stage scoring, weather). Outliers harder to classify.
20+ centsMarket is volatile right now (injury just announced, etc.). Trust the sharp anchor only; ignore retail outliers.

3. Suspended-but-posted on the source page

This requires checking the source book's status field. Many books expose a market-status alongside the price (open / suspended / closed). A "suspended" market with a price still posted is the single most reliable stale signal; the book has explicitly told you it won't accept bets. We surface this in status on our prop and odds responses; trust it before edge math.

The six-step filter

Every +EV or arbitrage candidate should pass these six checks before it's actionable. Roughly ordered by how cheap they are to compute.

  1. Source freshness check. The book's last observation must be within its slack threshold (see /v1/meta/per-book-sla). Reject if degraded or worse.
  2. Status check. If the source response includes a status field, it must be active (or whatever the book's "open" state is called). Reject suspended / closed / settled.
  3. Two-sided present check. For devig math: both sides of the market must be priced. If only one side is on the page, the devig is unreliable; the missing side may be where the suspension hides.
  4. Peer-disagreement check. The candidate's price must be within K cents of the median of N peer-book prices on the same market. K=12 and N=3 are reasonable defaults; tighten for flagship markets, loosen for niche.
  5. Magnitude sanity check. The computed edge must be below a "data error" threshold. We cap +EV demo output at 20% explicitly because no real +EV on a liquid moneyline is 20% (see reading +EV outputs honestly). For player props the threshold is higher (~30%) because props have legitimately wider mispricing on niche players.
  6. Commence-time agreement check. If the candidate is across books (arbitrage, +EV vs sharp), the books must agree on commence_time within a 5-minute tolerance. Event-ID drift between books otherwise produces phantom matches. See reading +EV outputs honestly for the long-form on this.
The hardest case. Sometimes a book IS posting fresh data with an open status, peer-disagreement is wide, and the price is just genuinely off. This happens 2-3 times per slate on the soft books, especially around late injury news. Those are real opportunities, but they're also the same shape as a CDN cache miss. The honest answer: when in doubt, bet smaller. Half-Kelly already protects you against this case; quarter-Kelly with a 5% cap protects further. See the Kelly post.

How ParlayAPI handles this

Two layers:

  1. Aggregator-level. Our ingest pipeline tracks per-book per-sport freshness in real time. The /v1/meta/source-quality endpoint is the authoritative read; the /v1/meta/per-book-sla endpoint exposes the thresholds. Any book in breach or stale state gets quarantined from our cross-book scans automatically until it recovers.
  2. Candidate-level. The full /v1/sports/{sport}/ev and /v1/sports/{sport}/arbitrage endpoints apply all six filters above by default. The free /v1/try/{sport}/* demos apply a subset (excludes prediction-market books from the cross-book pool and caps displayed edge at 20%) but customers should layer the full filter set on top of any candidate before staking.

You can verify a book's status before betting:

# Pull live source quality
curl -s 'https://parlay-api.com/v1/meta/source-quality?minutes=2' \
  | jq '.by_source[] | select(.source == "fanduel")'

If sla isn't ok, treat any +EV signal from that book as suspect.

The honest summary

Stale lines are the dominant source of "scanner said +EV but the bet got voided" stories. The pattern is always the same: a price that's structurally disconnected from the book's current model gets surfaced as edge, you bet it, the book rejects.

The six-step filter above eliminates most of these. The remaining 5-10% are genuine "soft book is just wrong right now" cases, which is what +EV scanning is supposed to find. Quarter-Kelly + 5% cap protects you against the residual.

If a scanner is showing you 50% edges, check freshness before checking math. The math is almost never wrong; the data underneath it almost always is.

All posts · Reading +EV outputs honestly · No-vig CLV explained · Kelly criterion guide