Dugout Math

Command Palette

Search for a command to run...

Sign inSign up free

Everything here is descriptive analytics over public MLB data. No black-box model, no external odds feed. If a number looks wrong, it is checkable — that is the point of this page.

The verdict

The core idea is one line of baseball reasoning: results without process is luck; results with process is a change. A hitter slugging .700 over ten games whose exit velocity and barrel rate are unchanged is having a nice week. One whose barrel rate jumped six points is doing something different. The first regresses; the second might not.

So we score results (recent wOBA / ERA vs the player's own baseline) and process (recent quality of contact from Statcast) separately, and the verdict is what happens when you cross them:

  • Real breakoutResults are up AND the contact quality confirms it.
  • Running hotResults are up but contact quality is only average — enjoy it, don't extrapolate.
  • Hot but luckyResults are up and the contact quality actively disagrees.
  • Cold but unluckyResults are down but he's hitting the ball fine.
  • ScufflingResults are down with nothing underneath — a normal cold stretch.
  • Real declineResults are down and the underlying numbers agree.
  • SteadyRight around his usual level.
  • Too earlyNot enough recent sample to say anything.

Every verdict carries a confidence tier from the actual sample size, and never claims high confidence without a measurable process signal behind it.

Small samples: empirical-Bayes shrinkage

A .450 hitter over 10 at-bats and a .450 hitter over 400 are not the same bet, so every rate is pulled toward the league mean in proportion to how little evidence there is: adjusted = (events + leagueRate·K) / (chances + K). K is a prior strength in the same units as the chances. This is why a two-week call-up does not top a season leaderboard.

Scores are league-relative

Most 0–100 scores are z-scored across the qualified pool and rescaled so 50 is league average and ~15 points is one standard deviation. Filtering the table (position, sample) narrows and re-ranks the list — it never re-grades anyone.

Momentum

“Momentum” is recent form versus a player's ownseason baseline, with the raw difference shrunk toward zero by sample size. It is deliberately not the difference between a shrunk recent rate and an unshrunk season rate — that leaves a residual which is non-zero even when nothing has changed, and would label good players “cooling” by construction.

Data definitions that trip people up

These are the ones that quietly produce wrong numbers, so they are worth stating:

  • A batted ball is a ball put in play. Statcast records launch data on foul balls too — counting those roughly doubles the denominator of every contact rate.
  • xwOBA on contact is not xwOBA per plate appearance. The underlying column is populated on every PA-ending pitch (a strikeout scores 0.000, a walk 0.702).
  • Sweet spot is the 8–32° launch-angle band.
  • Average exit velocity excludes bunts(a ~34 mph bunt drags a speedster's average down several mph), but bunts stay in the rate denominators — matching Baseball Savant on both counts.
  • A foul tip is a whiff.
  • Innings pitched use thirds notation — 6.2 IP is six and two-thirds innings, not 6.2 of them.
  • Rate leaderboards are qualifiedat baseball's conventional 3.1 PA / 1.0 IP per team game, which rises through the season.

Known limitations

One season of data, so there is no career context. No injury or lineup feed, so a listed probable starter can be scratched and we will not know. Nothing is live. And an offline backtest found the form-aware prop model is within noise of a season-long baseline at the single-game level — which is why Prop Lab is presented as a fair-odds calculator and not as an edge.

More detail, including every component weight, lives in the repo's methodology document. Questions or corrections: get in touch.