NBA Team Totals — Data Audit Council Ruling

Date: 2026-04-02 Process: Architectural review — data sources, probability model, edge detection methodology Scope: NBA team totals market (individual team scoring over/under) Status: BUILT & DEPLOYED (2026-04-02)


WHAT IS A TEAM TOTAL?

A team total is a bet on how many points a specific team will score in a game (e.g., Lakers Over/Under 112.5). This is distinct from the game total which is the combined score of both teams.

Why it matters: Team totals are less efficiently priced than game totals because they require team-specific modeling rather than aggregate game modeling. This creates edge opportunities.

Kalshi series: KXNBATEAMTOTAL


DATA SOURCES

Primary Anchor: Pinnacle Team Totals (NEW)

Field Value
Source Pinnacle via Arcadia guest API intercept
Data Per-team total line + over/under decimal odds
Method Puppeteer page load intercepts guest.api.arcadia.pinnacle.com responses
Identification type="total" + participantId present = team total
Storage sports_odds_snapshots with source='pinnacle-teamtotal'
Freshness key pinnacle-nba-teamtotal
Schedule Adaptive cadence (2h/15m/5m) — same as main Pinnacle scraper

Secondary Anchor: Derived from Pinnacle Game Lines

When Pinnacle team total odds are unavailable, team totals are derived:

Home team total = (game_total + spread) / 2
Away team total = (game_total - spread) / 2

Example: Game total 225.5, home -5.5
  Home TT = (225.5 + 5.5) / 2 = 115.5
  Away TT = (225.5 - 5.5) / 2 = 110.0

This derivation uses Pinnacle's spread and game total — both already scraped on adaptive cadence.

Existing Data Sources (Already Collected)

Source What it provides for team totals
Pinnacle ML/Spread/Total Game-level anchor, derivation fallback
DRatings Per-game predicted scores (home/away separately)
Sagarin Team power ratings, predicted spreads
GameSim Monte Carlo predicted scores per team
NBA Stuffer Pace, offensive/defensive ratings
NBA Advanced Stats Off/def/net rating, pace, eFG%, TOV%
BBRef Team Stats Backup stats source
Team Variance Std dev, skewness, kurtosis of scoring distribution
Dimers Win probabilities per game

PROBABILITY MODEL

Distribution: Normal

NBA team scoring is approximately normally distributed. The edge scanner uses:

teamSigma = gameSigma / sqrt(2)

Where:
  gameSigma = 14 (NBA game total standard deviation)
  teamSigma = 14 / sqrt(2) ≈ 9.9

Model probability = Normal CDF exceedance at threshold
  P(team scores > threshold) = 1 - Phi((threshold - teamImplied) / teamSigma)

Anchor Selection

The team implied score comes from:

  1. Pinnacle team total line (preferred — direct market price)
  2. Derived from spread + game total (fallback — mathematical identity)

Both are valid. The direct Pinnacle line is preferred because it includes market information about team-specific factors (injuries, pace matchups, rest) that the derivation doesn't capture.

De-Vig Method

Team total odds from Pinnacle are de-vigged using the Shin method (same as game totals):

Shin de-vig removes the bookmaker margin while preserving the
favorite-longshot bias inherent in real odds.

The de-vigged over probability becomes the model's fair value anchor.


EDGE DETECTION METHODOLOGY

Scan Flow

1. Pinnacle team total odds → de-vig → fair over/under probability
2. Build Normal curve around team implied score (σ ≈ 9.9)
3. For each Kalshi alt line:
   a. Calculate model probability at that threshold
   b. Compare to Kalshi mid-price
   c. Calculate raw edge = model_prob - execution_price
   d. Subtract Kalshi fee (7% of profit)
   e. If net_edge > min_threshold → flag as executable
4. Store in sports_edges table with marketType='teamTotal'

Edge Filters

Filter Value Why
Min net edge 2% (configurable) Below this, fees eat the edge
Max net edge 25% Above this, likely a data error
Kalshi mid range 10c - 90c Extreme prices are illiquid
Max spread 20c Wide spreads = no real execution
Tail confidence Must be "reliable" Far-from-anchor lines degrade

Rung Distance

Distance from anchor affects model confidence:

rungDistance = |threshold - teamImplied| / 1.5

Thresholds far from the implied score have lower model confidence
because the normal approximation degrades in the tails.

CUSTOM CALCULATED METRICS

  1. Team Pace Delta: (Team_pace - Opponent_pace) / 2 — faster pace = higher team total
  2. Defensive Rating Matchup: Team_OffRtg * (Opp_DefRtg / League_Avg_DefRtg) — offense adjusted for opponent defense
  3. Rest Advantage Impact: B2B = -2.5 pts, 2+ days rest vs B2B opponent = +1.5 pts
  4. Home/Away Scoring Split: NBA home teams score ~2.5 pts more on average
  5. EWMA Scoring Form: Decay-weighted last 10 games scoring average (alpha 0.12)
  6. Blowout Risk Flag: Teams with high scoring variance (σ > 12) have wider team total ranges
  7. Pace Matchup Extreme: Both teams top-10 pace = team totals likely OVER; both bottom-10 = UNDER

NOISE TO TRIM


NBA-SPECIFIC FACTORS FOR TEAM TOTALS

  1. Pace is king — two fast teams (Memphis vs Indiana) produce higher team totals than two slow teams (Knicks vs Cavaliers)
  2. Back-to-back fatigue — reduces scoring by ~2-3 points per team
  3. Garbage time inflation — blowouts inflate losing team's total in 4th quarter
  4. Star player rest — load management reduces team scoring by 3-5 points when a star sits
  5. 3-point variance — teams that live by the 3 have higher scoring variance
  6. Altitude — Denver home games have slightly elevated totals
  7. Defensive matchups — elite rim protectors (e.g., Wembanyama) suppress opponent interior scoring
  8. Late-season tanking — eliminated teams may rest starters, depressing totals

INTEGRATION WITH EXISTING PIPELINE

Collector (collector.ts)

NBA Pinnacle scrapes now use scrapePinnacleWithTeamTotals() which:

Edge Scanner (edge-scanner.ts)

The team total scan block (lines ~655-780):

Dashboard (desk-config.ts)


FUTURE IMPROVEMENTS

  1. Use actual Pinnacle team total odds for de-vig instead of deriving from spread+total (deployed — Arcadia API intercept)
  2. Team-specific sigma — compute per-team scoring std dev from recent games instead of league-wide 9.9
  3. Pace-adjusted sigma — fast-pace matchups have higher variance
  4. Correlate with player prop lines — if a star's points prop moves, team total should move proportionally
  5. Live team total tracking — in-game team total edges using Kalshi live odds
  6. Cross-sport expansion — NHL team totals (KXNHLTEAMTOTAL), MLB team totals (already in config), NCAAB team totals

BUILD STATUS

Component Status
Kalshi series config (KXNBATEAMTOTAL) DONE
Pinnacle team total scraper (Arcadia API) DONE
Collector wiring (scrapePinnacleWithTeamTotals) DONE
Storage in sports_odds_snapshots DONE
Edge scanner team total logic DONE (existed)
Dashboard entries DONE
Freshness monitoring DONE
Normal curve model (σ = gameSigma / sqrt(2)) DONE
Team-specific sigma calibration NOT YET
Pace-adjusted model NOT YET
Live team total tracking NOT YET
Source: ~/edgeclaw/results/panel-results/nba-team-totals-data-audit-ruling.md