Full Count Model

How a pick gets made — from a per-plate-appearance rate to eight published bets.

← Today's card and the record

The short version

The model does not predict games. It prices individual events — does this hitter record a base, does this starter stay under his strikeout number — and then compares its own price to the sportsbook's, with the sportsbook's margin stripped out.

Almost everything interesting happens in two places. First, a stack of multipliers turns a hitter's own rate into a rate for tonight: who's pitching, which way the wind is blowing, which hand he swings from, how much of the game the bullpen will cover. Second, a calibration layer fit on the model's own graded ledger decides how much that opinion is worth in each market — and in some markets the honest answer is not much. Both are traced below on real picks.

The pipeline

Seven stages, roughly 11 hours before first pitch. Data flows once; nothing is fetched twice.

1B 2B 3B 01 Ingest MLB API · Statcast weather · odds 02 Base rates per-PA, shrunk toward the league 03 Modifiers platoon · matchup wind · park · pen 04 Projection rate × projected plate appearances 05 Probability count distribution fit per market 06 Calibration weighed against the de-vigged book 07 Gate cEV ≥ +2%, and only proven lanes Eight picks, published before first pitch · graded at that price
One trip around the bases per pick. The edge is manufactured on the way to second; it gets audited at third.

Stage 03 — the stack, literally

A hitter's total-bases projection is one line of arithmetic. Every term is a multiplier on his own per-plate-appearance rate.

TB  =  tb_pa (shrunk own rate)  ×  opposing arm  ×  platoon  ×  pitch-type matchup  ×  weather  ×  projected PA

The first three are blended by starter share — the fraction of the lineup's plate appearances the starting pitcher is projected to cover. A platoon edge against a lefty starter is worth 57% of itself if the bullpen is covering the other 43%, because you cannot know in August which reliever throws the seventh.

TermWhat it readsRange it may move
PlatoonHitter's split severity vs. this arm's hand, leveraged by the starter's arsenal0.80 – 1.20
Pitch-type matchupBatter's per-pitch-type value against what this starter actually throws0.90 – 1.10
WeatherWind speed and direction resolved against the hitter's hand — out to right helps left-handed pull, out to left helps rightper-venue
Park geometryVenue × handedness fixed effect, three-season blend, 850-observation shrinkage — home-run channel only0.75 – 1.35
Opposing lineup KApplied to the starter's strikeout projection, not the hitter's0.85 – 1.15

Park geometry is deliberately confined to home runs. It relocates batted balls over a fence; that is not the same physics as a single, and total bases would need its own fit before it earns the term. Applying a home-run multiplier to total bases because it is sitting right there is exactly the kind of shortcut that backtests beautifully and loses money.

Case one — the stack clears the gate

A published pick from the card of Friday, August 28, traced from rate to result.

Ben Rice · TB Over 0.5 · BOS @ NYY
Published · 3 total bases · win
EnvironmentLeft-handed bat, second in the order. Wind 6 mph, out to right field — the direction that helps a left-handed pull hitter.
Opposing armPatrick Sandoval, left-handed. Same-side matchup, so the platoon term works against the pick.
Starter shareSandoval projected to cover 57% of the lineup's plate appearances; the platoon penalty is diluted across the other 43%.0.568
ProjectionStacked rate × projected plate appearances1.71 TB
Model priceProbability of at least one base, through the fitted count distribution63.8%
Market priceOffered at −110; no-vig probability after stripping the book's margin54.1%
Raw EVModel probability at the offered price+21.7%
Calibrated EVAfter the ledger has its say (see below)+16.2%
ResultDouble, single — three total basesWin

The park term never touched this pick. Yankee Stadium's short porch is real and the model knows it, but that fixed effect is confined to Rice's home-run number — 0.21 projected, a different bet on a different line. The pick was carried by his own rate, the diluted platoon penalty, and the wind.

Case two — the gate says no, and the pick wins anyway

The uncomfortable one. Same card, same night.

Jacob Lopez · K Under 6.5 · BAL @ ATH
Held back · 6 strikeouts · would have won
Projection5.62 strikeouts over 5.06 projected innings, after the opposing lineup's contact profile5.62 K
Model priceProbability of staying under 6.564.5%
Market priceOffered at −145; no-vig probability55.5%
Raw EVA nine-point edge on the book. The model liked it.+8.9%
Calibrated EVThe strikeout-under weights barely credit the model's disagreement−2.2%
DecisionBelow the +2% publishing floor — not shown on the cardHeld
ResultSix strikeouts. The under cashed.

This is what the gate is supposed to look like from the inside. It is not a judgment about Jacob Lopez on August 28 — it is a judgment about the population of picks that look like this one, made from 352 graded strikeout unders. A gate that only ever suppresses losers is not a gate, it is hindsight. Publishing this pick because it happened to win would mean the ledger stopped governing and the vibes took over.

The model grades its own opinions

Every Monday the calibration layer refits on the full graded ledger. It asks one question per market: given what the model thinks and what the market thinks, what actually happens?

calibrated probability = σ( a + wmodel·logit(model) + wmarket·logit(no-vig market) )

The weights are the interesting part. A high model weight means the model's disagreement with the price has historically been informative. A weight near zero means it hasn't. A negative weight means the model's opinion in that market has been actively worth fading — and the layer fades it, automatically, without anyone being asked to admit anything.

MarketGradedWeight on the model's own opinionwmodelwmarket
Full-game moneyline147+0.610.74
Total bases — Over552+0.591.01
Strikeouts — Over148+0.450.18
Strikeouts — Under352+0.040.62
Earned runs — Under149−0.10−0.15
Outs — Under198−0.110.84
Total bases — Under314−0.160.82

Weights current as of August 2026 — fit 2026-08-28 on 2,339 graded picks, expanding window from 2026-07-21. The layer refits weekly on the growing ledger, so treat this table as a dated snapshot of the mechanism, not a live feed; the live weights are what actually price each day's card. Bars are scaled to the largest absolute weight.

Read the bottom of that table honestly and it says something a marketing page would never volunteer: the model's opinion about unders is worth less than nothing in three markets. It is good at finding hitters who will do something and starters who will do a lot of something. When it argues that a number is too high, the ledger says the book was already right.

Nothing was rewritten to fix that. The weights simply carry it, and picks in those lanes have to clear the +2% floor on the market's terms rather than the model's. That is the whole mechanism: an edge you cannot prove out of sample is not an edge, and the code should be the thing that enforces it, not your discipline at 11am.

Where it loses

Published because it's true, not because it helps.

Game moneylines are the model's worst product and have been all season — a losing record against the closing no-vig price, shown on the front page in the same table and the same colours as the winning lanes. The prop lanes carry the system. The right response to a losing lane is to measure it in the open until the evidence is decisive, not to quietly stop printing it.

See the full record →