League Donation
xStats: How It Works
The methodology behind the Statcast-adjusted value metric. Formulas, derivations, signal tiers, and omissions. See the colophon for the full system architecture.
Baseball generates two data streams for every hitter and every pitcher. The box score tracks outcomes: hits, outs, home runs, earned runs. Statcast tracks the contact that produced those outcomes: exit velocity and launch angle on every batted ball, measured by high-speed cameras in every MLB stadium since 2015.
From those measurements, Baseball Savant computes expected statistics. A line drive at 105 mph has an expected batting average around .700. A weak grounder at 75 mph has an xBA around .100. Aggregate every batted ball a hitter produces in a season, weight each one by its historical outcome probability, and you get xBA, xSLG, and xwOBA: what the contact quality says the stat line should look like, independent of where any particular ball happened to land.
A hitter batting .238 on an xBA of .295 is making hard contact that keeps finding gloves. The .238 is what happened. The .295 is what the contact quality says should be happening. Over a full season, these two numbers converge. The contact quality wins. The question for a fantasy manager is what to do in the meantime, and how much to trust the convergence at any given point.
The xStats system in League Donation is built around that question. It takes the gap between what Statcast’s expected statistics say a player should be producing and what the preseason projections predicted, and uses that gap to adjust every player’s fantasy value. The adjustment starts small when the sample is thin. It grows as plate appearances accumulate and the contact data earns authority over the projection. This page documents the methodology. Every formula, every derivation, every omission.
The entire system rests on one equation. The adjustment blends a projected stat with a Statcast-derived expected stat using a weight that increases with sample size:
PA is plate appearances for batters, batters faced for pitchers. k is a stabilization constant, different for each stat, calibrated to how quickly that stat produces reliable signal from batted-ball data.
The equation blends two opinions about a player. The preseason projection is what the experts believed before the season started. The Statcast expected stat is what the contact quality says right now. The blend starts by trusting the projection entirely and transfers authority to the contact data as the season generates evidence.
At zero PA, w is 0. The projection holds. At 200 PA with k of 200, w reaches 0.50 and both opinions carry equal weight. By 600 PA, the contact quality holds 75% of the authority. The projection fades but never fully disappears, a receding prior that the season gradually talks over.
This is empirical Bayes shrinkage applied to within-season updating. The projection is the prior. The expected stat is the likelihood. The stabilization constant governs how quickly the posterior moves away from the prior. The formula ensures the system never overreacts to a hot week or underreacts to three months of evidence.
Different stats deserve different patience. A hitter’s expected batting average requires more plate appearances to stabilize than a pitcher’s strikeout rate, because batting average involves more moving parts. The system assigns a stabilization constant k to each stat, governing how quickly the blend shifts from projection to contact quality:
| Category | Source | k | w@50 | w@150 | w@300 | Tier |
|---|---|---|---|---|---|---|
| AVG | xBA | 200 | 0.20 | 0.43 | 0.60 | ● Strong |
| SLG | xSLG | 180 | 0.22 | 0.45 | 0.63 | ● Strong |
| wOBA | xwOBA | 150 | 0.25 | 0.50 | 0.67 | ● Strong |
| ERA | xERA | 120 | 0.29 | 0.56 | 0.71 | ● Strong |
| WHIP | Derived xWHIP | 150 | 0.25 | 0.50 | 0.67 | ● Strong |
| HR | Barrel rate | 200 | 0.20 | 0.43 | 0.60 | ◑ Moderate |
| R | xwOBA | 250 | 0.17 | 0.38 | 0.55 | ◑ Moderate |
| RBI | xwOBA + ctx | 300 | 0.14 | 0.33 | 0.50 | ◑ Moderate |
| K (pit) | Savant K% | 70 | 0.42 | 0.68 | 0.81 | ◑ Moderate |
| BB (pit) | Savant BB% | 170 | 0.23 | 0.47 | 0.64 | ◑ Moderate |
| K (bat) | Savant K% | 100 | 0.33 | 0.60 | 0.75 | ○ Weak |
| BB (bat) | Savant BB% | 100 | 0.33 | 0.60 | 0.75 | ○ Weak |
Pitcher K% is the most impatient stat in the system (k=70). Strikeout rates converge quickly. RBI is the most patient (k=300): the derivation involves several inference steps and lineup-dependent context, so the system waits longer before trusting it.
Five categories get no adjustment. Stolen bases have no contact-quality analog. You can barrel every pitch you touch and still be slow. Wins depend on run support. Saves depend on whether the manager hands you the ball in the ninth. The system leaves these at their projected values and doesn’t pretend otherwise.
Savant publishes xBA, xSLG, xwOBA, and xERA. Those map directly onto AVG, SLG, wOBA, and ERA, and the blend is straightforward: Savant number in, projection blended, adjusted value out. Most fantasy leagues score counting stats. There is no xHR on Baseball Savant. No xR. No xRBI. The system derives expected rates from contact quality data, blends those rates with projected rates, and scales back to counting stats using projected playing time as the denominator.
Each derivation is a small model. Each model introduces inference beyond the raw Statcast data. Each one is labeled accordingly.
Expected HR Rate
Barrel rate measures the fraction of batted balls with exit velocity and launch angle in the zone that historically produces a .500+ batting average and 1.500+ slugging. About 85% of barrels leave the park, a coefficient that holds up year to year. Park effects, wind, and wall height create variance around it.
Contact rate is approximated as (1 − K%), using the player’s Statcast strikeout rate. A hitter who barrels 8% of batted ball events and puts the ball in play 78% of the time produces an expected HR rate of 0.053 per PA. Over 600 PA, that’s 32 home runs. Moderate tier.
Expected R Rate
Runs derive from xwOBA through the standard wOBA-to-runs conversion, a formula stable enough across seasons that the league average constants barely shift:
An xwOBA of .360 produces an expected 0.157 runs per PA. Multiply by projected PA for the counting stat. Moderate tier.
Expected RBI Rate
RBI depends on who’s on base when you come up: your teammates, your lineup slot, the manager’s whims. Contact quality can’t measure any of that. The derivation bridges the gap using the projection source:
The contact quality updates the rate. The projection supplies the lineup context. If the projection system had the player driving in 1.1 runs for every run scored, the system preserves that ratio while the underlying rate shifts. This derivation carries the highest k (300) and the Moderate tier. At 300 PA the system still gives the projection half the weight, because the inference chain is long.
Expected WHIP
Savant doesn’t publish xWHIP, but all the ingredients are available:
xBA for pitchers is expected batting average against. BF is batters faced. BB comes from the pitcher’s Savant walk rate. IP is estimated from batters faced at a 0.37 out-conversion rate. Every input is event-level or fast-stabilizing. Strong tier.
A hitter enters mid-May with 120 plate appearances. Preseason projection: .270 AVG, 22 HR over 550 PA. Current actual line: .238 AVG, 6 HR. The stat line looks like a bust.
Savant says otherwise. xBA: .295. Barrel rate: 8.2%. K%: 22%. The bat is performing. The results haven’t caught up.
The AVG adjustment:
The projection said .270. The contact quality says .295. At 120 PA the system trusts the contact quality 37.5% and moves the projection to .279. By August, if the xBA holds, the weight will pass 60% and the adjusted AVG will approach .290.
The HR adjustment uses the barrel rate derivation:
The barrel rate says 30-HR contact quality. The projection said 22. The blend lands at 25 and will keep rising if the barrel rate holds.
Both adjustments, and every other mapped category, produce a new stat line. That line gets fed through the same z-score and VORP pipeline the projection-based rankings use, recomputed against the adjusted population. The adjusted VORP minus the projected VORP is the xΔ. Adjustments smaller than ±0.3 VORP are suppressed as noise.
The xΔ answers a specific question: how much is the contact quality disagreeing with the projection, expressed in positional fantasy value, in your league’s scoring system, at the current sample size? Green means the bat or arm is worth more than the projections suggest. Red means less.
Every xΔ carries a confidence label. The tier reflects which stat category drove the largest z-score shift in the recomputation, then caps that tier by the blending weight.
The tier is then capped by the blending weight. An xBA gap that looks dramatic at 40 PA gets a Weak label because 40 PA hasn’t earned the system’s confidence. The cap logic: w < 0.25 forces Weak. w < 0.50 forces Strong down to Moderate. The tier tells you how seriously to take the system’s own number.
Separate from the adjusted value pipeline, the xStats tab displays a regression score per player: a single number capturing how far actual stats have drifted from expected.
For batters, the primary component is the xwOBA-minus-wOBA gap, with the xSLG-minus-SLG gap as a secondary power signal. The xBA gap is excluded because xwOBA already incorporates it, and including both would double-count contact quality on singles. For pitchers, the secondary component is ERA-minus-xERA, picking up strand rate and sequencing divergence.
The raw gaps are normalized to pool-based z-scores. A regression score of +1.5 means the player’s gap sits 1.5 standard deviations above the pool average. The normalization self-calibrates through the season: early on, the standard deviation is wide because everyone’s gaps are noisy. A +1.5 is hard to reach. As the season progresses, the distribution tightens. A smaller absolute gap can carry the same relative weight.
Starting pitchers and relievers are normalized in separate sub-pools. SP wOBA distributions are structurally tighter than RP distributions. Combining them inflates the standard deviation and buries genuine SP signals at 0.5 sigma even when they’re meaningful.
The xStats tab classifies each player by overlaying two questions: is the player recently hot or cold (last 14 games versus season average, minimum 30 PA), and does the contact quality explain the streak (expected-versus-actual gap at the season level).
These are observations, each backed by a specific data relationship. “Unlucky Slump” means the player is cold and the contact quality says the cold streak has no support in the batted-ball data. “Unsustainable” means the player is hot and the contact data says the hot streak is running ahead of the quality of contact. The contact data doesn’t care about your roster. It reports what the bat did.
Park effects. Expected stats use leaguewide batted-ball distributions. A fly ball at Coors Field has different outcomes than the same ball at Oracle Park. A full-season Coors hitter will show an expected-versus-actual gap that partly reflects altitude. The system doesn’t adjust for park. The gap is displayed. Evaluating how much is park is the user’s job.
Defensive positioning. Shifts turn expected hits into outs. The system treats this as noise that should resolve over a season. Whether it actually resolves depends on how persistently teams align against a specific hitter. The system doesn’t model that persistence.
Spray angle. Savant’s own xwOBA model excludes spray angle. Tom Tango’s research showed that without spray angle, xwOBA on contact better predicts future performance than with it. The system follows Savant’s decision.
Stolen bases. No contact-quality signal. Speed lives outside the batted-ball data entirely.
Wins and saves. A pitcher’s contact quality tells you how well he pitched. Whether his team scored runs or whether his manager used him in the ninth inning is a different question that exit velocity cannot answer.
Tom Tango, the architect of expected statistics at MLB, has stated that xStats were designed to be descriptive. They tell you what should have happened given the contact quality. They were never built to forecast next season.
This system uses them for something narrower than forecasting and more actionable than description: within-season belief revision. Given what the contact quality says right now, and given how much season has accumulated, how much should we revise our beliefs about this player’s value in this specific league?
The stabilization constants determine when the revision begins. The derivations extend it to the stats leagues actually score. The signal tiers quantify how much confidence the revision has earned. The regression score and trend matrix display the raw gap the revision is built from. The omissions catalog where the system has no opinion.
The math is auditable. The inputs are public. The derivation is shown.