The 2026 Season — What Actually Happened

166 scoring days, 14,821 logged transactions, 1,912 MLB games, and one champion. The regular season ran March 26 to September 7, and This Schlitt is Bazzanas closed it out by winning the title round 7 categories to 2 (with quality starts tied). This is the season told through the daily data rather than through vibes.

One thing to get out of the way first, because it shaped the whole analysis: four of the ten managers renamed their teams mid-season. Big Papi became Rock and Aroldis, Big Dumpers became PCA and some bums, Long Bohms Away became Welcome to the JUNGle, and This Sh!t is Bazzana became This Schlitt is Bazzanas. Any analysis that groups by team name — as my own scorecard script had been doing — silently splits those four into eight partial-season fragments and ranks a phantom 14-team league. Every number below groups on team_id instead.

Methodology & Data Sources

  • Data Sources:
    • 2026_espn_stats_daily — per-player, per-day fantasy data for all 10 teams across all 166 scoring days. This is the spine of the recap. Coverage is complete: no missing calendar dates, no anomalously low-volume days.
    • ESPN Fantasy API (live) — final standings, category records, and playoff bracket results. The data-lake scoreboard snapshot was stale (June 20, all scores 0.0, 35 of 90 matchups still UNDECIDED), so standings were pulled fresh rather than reconstructed.
    • 2026_espn_activity_season — 14,821 activity events (627 free-agent adds, 604 drops, 5 trades, 13,585 lineup moves) used to date every pickup and measure manager engagement.
    • 2026_espn_draft_results — the 280 drafted players, used to separate genuine waiver finds from re-adds of already-owned players.
    • player_map.csv — canonical ESPN↔MLBAM identity bridge. Required: the player_position column in the ESPN daily file is unreliable (it lists Mason Miller as an outfielder and Pete Crow-Armstrong as a corner infielder), so every position here is resolved through the map.
    • 2026_mlb_bat_tracking_season — Statcast bat-speed and swing-quality context.
    • 2026_espn_waiver_watchlist / 2026_local_multi_method_watchlist — the Idea 16 and Idea 17 signal models, audited retrospectively.
  • Methodology:
    • Team category totals count active lineup slots only — bench and IL player-days are excluded, because that is how H2H category scoring actually accrues.
    • Rate stats (OPS, ERA, WHIP, K/9) are recomputed from summed components (OBP and SLG from PA/AB/TB; ERA and WHIP from earned runs, walks, hits and outs), never averaged-of-averages.
    • Player and pickup value is a 5-category composite z-score across the league’s own scoring categories, with ERA and WHIP sign-flipped. Minimums: 250 AB or 40 IP for season leaderboards, 100 AB or 20 IP for pickups.
    • Pickup value counts only production accrued after the add date, which matters — measuring full-season stats instead makes season-long roster mainstays look like waiver genius.
    • Half-season movement compares each team’s sum of category ranks before and after the midpoint (June 17).

Finding 1 — The champion won on balance, not on peaks

This Schlitt is Bazzanas finished with a category record of 106-67-7 (.608), the best in the league, then won both playoff rounds by the identical 7-2-1 line — over Skubal Snacks in the semifinal and Midnight Muncy’s in the final.

The season-long category ranks explain why. Summing each team’s ten category ranks (lower is better, 10 is a perfect score):

Team R HR RBI SB OPS K/9 QS SVHD ERA WHIP Rank sum
This Schlitt is Bazzanas 1 1 1 4 6 4 2 3 2 1 25
Skubal Snacks 5 5 5 6 3 3 9 4 5 4 49
Welcome to the JUNGle 2 4 2 10 2 6 8 2 7 6 49
Rock and Aroldis 4 6 3 3 7 5 6 5 8 5 52
Midnight Muncy’s 9 8 8 2 8 2 1 9 3 3 53
Dingers Only 8 10 7 5 10 1 4 6 1 2 54
Datalickmyballs 6 3 6 7 9 10 3 1 6 8 59
All Rise 3 7 9 1 1 7 7 8 10 10 63
PCA and some bums 7 2 4 8 5 9 10 10 9 9 73
Shohei Me the Money 10 9 10 9 4 8 5 7 4 7 73

A rank sum of 25 against a field whose next-best is 49 is not a close race. The champion’s worst category all season was OPS at 6th. It won R, HR, RBI and WHIP outright, and sat 2nd or 3rd in QS, SVHD and ERA. Nobody else was even top-6 in all ten.

Compare that to All Rise, which owned the two best batting-rate categories in the league — 1st in SB (205) and 1st in OPS (.771) — and still finished 9th, because it was simultaneously last in both ERA (4.385) and WHIP (1.332). In a format where every category is its own weekly win, two dead-last ratios cost you 20% of the board every single week no matter how good your bats are.

Category leaders:

Category 1st 2nd 3rd
R This Schlitt is Bazzanas (1,034) Welcome to the JUNGle (1,013) All Rise (998)
HR This Schlitt is Bazzanas (301) PCA and some bums (296) Datalickmyballs (278)
RBI This Schlitt is Bazzanas (987) Welcome to the JUNGle (975) Rock and Aroldis (963)
SB All Rise (205) Midnight Muncy’s (179) Rock and Aroldis (176)
OPS All Rise (.771) Welcome to the JUNGle (.769) Skubal Snacks (.765)
K/9 Dingers Only (10.12) Midnight Muncy’s (9.78) Skubal Snacks (9.71)
QS Midnight Muncy’s (94) This Schlitt is Bazzanas (91) Datalickmyballs (83)
SVHD tied — Datalickmyballs & Welcome to the JUNGle (125) This Schlitt is Bazzanas (114)
ERA Dingers Only (3.205) This Schlitt is Bazzanas (3.459) Midnight Muncy’s (3.541)
WHIP This Schlitt is Bazzanas (1.146) Dingers Only (1.151) Midnight Muncy’s (1.158)

Finding 2 — The biggest swing was a 28-rank second-half surge

Splitting the season at June 17 and comparing each team’s rank-sum before and after:

Team 1st half 2nd half Δ Categories that jumped
Rock and Aroldis 66 38 +28 SB 4→1, OPS 9→3, K/9 9→3, HR 9→4, SVHD 7→4, R 6→3
PCA and some bums 72 61 +11 HR 5→1, RBI 6→2, OPS 5→2, R 8→4
This Schlitt is Bazzanas 34 26 +8 RBI 4→1, SB 5→2, OPS 6→4
Shohei Me the Money 71 66 +5 HR 10→6, QS 7→3, RBI 10→8
Midnight Muncy’s 55 52 +3 K/9 7→1, RBI 9→7
Datalickmyballs 58 61 -3 HR 6→3, RBI 8→5
Skubal Snacks 48 53 -5 SVHD 8→1, SB 9→5
Welcome to the JUNGle 50 56 -6 OPS 4→1
Dingers Only 47 57 -10 WHIP 5→1
All Rise 49 80 -31 none

Rock and Aroldis — the team formerly known as Big Papi — improved in six of ten categories and turned a bottom-third first half into a 3rd-place finish. It was also the most hyperactive manager in the league: 105 adds and 2,544 lineup moves, both near or at the top.

All Rise is the mirror image: it did not improve in a single category after June 17, dropped 31 rank-points, and slid from the 7th seed to a 9th-place finish.


Finding 3 — Two March 30 waiver claims decided the best-pickup race

Measuring only post-add production, and restricting to players who were never drafted by anyone and had never previously been on that roster, the top waiver finds of 2026:

Player Pos Added By AB R HR RBI SB OPS z
Jordan Walker RF Mar 30 Midnight Muncy’s 520 80 26 94 18 .817 12.69
Miguel Vargas 3B Mar 30 Midnight Muncy’s 509 91 29 73 15 .848 12.30
Jake Bauers 1B Apr 1 Rock and Aroldis 357 63 18 64 6 .870 6.79
Jake McCarthy CF Jun 4 This Schlitt is Bazzanas 302 49 11 46 18 .834 6.09
Dillon Dingler C Apr 4 This Schlitt is Bazzanas 446 56 21 69 0 .747 4.66
Brandon Marsh LF Apr 15 Datalickmyballs 400 57 15 46 9 .739 4.33
Liam Hicks C Apr 2 All Rise 413 55 14 64 3 .784 4.22
Pitcher Added By IP ERA WHIP K/9 QS SVHD z
Louis Varland Apr 15 Welcome to the JUNGle 60.3 1.49 .994 10.74 0 36 5.63
Bryan Baker Apr 28 Welcome to the JUNGle 43.7 1.24 .893 9.69 0 34 5.53
Cade Cavalli Jul 5 Midnight Muncy’s 54.0 1.83 .870 12.00 8 0 5.41
Jacob Latz May 7 Rock and Aroldis 44.7 2.22 .896 10.88 0 26 4.60
Tanner Scott Apr 10 Skubal Snacks 52.7 2.73 .987 10.94 0 32 4.44
Parker Messick Mar 31 Skubal Snacks 156.0 2.65 1.045 9.35 12 0 3.90
Payton Tolle Apr 21 Skubal Snacks 137.0 3.28 1.088 10.45 12 0 3.80

Three separate strategies show up clearly here:

  • Midnight Muncy’s played the sniper. It made only 36 adds all season — fourth-fewest in the league — but two of them, both on March 30, were the two best pickups of the year by a wide margin. Jordan Walker and Miguel Vargas both finished as top-11 batters league-wide, not merely as good pickups. That’s a 2nd-place finish built on two decisions made in the season’s first week.
  • Welcome to the JUNGle built an entire elite bullpen off waivers. Varland (Apr 15) and Baker (Apr 28) combined for 70 saves-plus-holds at a sub-1.50 ERA, and carried the team to a share of the league SVHD lead (125) — from two players nobody drafted.
  • Skubal Snacks played the volume game. League-high 146 adds, and it worked: Messick, Tolle and Scott were all undrafted, all delivered, and they were the backbone of a 4th-place finish and a playoff berth.

Finding 4 — Season’s best players

Batters (min 250 AB, active-slot production, 5-category composite z):

Player Pos AB R HR RBI SB OPS z
Pete Crow-Armstrong CF 541 104 39 92 33 .947 12.03
Yordan Alvarez DH 505 94 38 95 1 1.039 8.98
CJ Abrams SS 513 83 30 93 26 .841 7.68
James Wood RF 437 100 30 73 17 .928 7.59
Ben Rice 1B 500 89 36 88 3 .896 6.49
Junior Caminero 3B 543 85 37 90 3 .889 6.41

Pete Crow-Armstrong’s 39 HR / 33 SB / .947 OPS season is the single most valuable fantasy line in the league, and the gap to second is enormous — 12.03 to Alvarez’s 8.98. In a 5x5 format the only way to post a z-score like that is to win four categories at once; Alvarez had the better OPS (1.039, the league’s best) but one stolen base.

Pitchers (min 40 IP):

Player IP ERA WHIP K/9 QS SVHD z
Mason Miller 60.3 1.19 .829 16.56 0 33 9.04
Jacob Misiorowski 155.0 1.97 .794 13.18 17 0 6.87
Cade Smith 60.0 2.25 1.033 12.90 0 33 5.15
Louis Varland 60.3 1.49 .994 10.74 0 36 5.04
Cam Schlittler 167.3 1.94 .926 10.86 17 0 4.94

Mason Miller’s 16.56 K/9 with a 1.19 ERA and 33 SVHD is the most dominant pitching profile in the data — a reliever who wins four of the five pitching categories by himself. Jacob Misiorowski was the best starter: a 0.794 WHIP over 155 innings with 17 quality starts.


Finding 5 — Bat speed backed up the best waiver call

Cross-referencing the top bats against Statcast bat tracking (league mean 72.21 mph, sd 2.84):

Player Avg bat speed Percentile Blast/swing Hard-swing %
Junior Caminero 79.65 100th .193 86.1%
Jordan Walker 79.22 99th .158 85.2%
Kyle Schwarber 77.15 96th .119 75.0%
James Wood 76.93 95th .183 69.1%
Yordan Alvarez 76.16 92nd .176 61.7%
Pete Crow-Armstrong 74.94 83rd .129 51.9%

The interesting row is Jordan Walker at the 99th percentile in bat speed — the best waiver pickup of the season was also, physically, one of the hardest swingers in baseball. Whatever Midnight Muncy’s saw on March 30, the underlying tool was real and measurable.

The other useful signal is a negative one: Crow-Armstrong was only 83rd percentile in bat speed and 51.9% hard-swing. The most valuable batter in the league got there on speed, contact and volume rather than raw power — a reminder that in a 5x5 with SB as its own category, bat speed is not the whole story.


Finding 6 — Managing your lineup appears to matter more than churning your roster

Ranking every team by engagement against its category record:

Team Seed Final W-L-T Adds Drops Lineup moves
This Schlitt is Bazzanas 1 1 106-67-7 76 74 1,727
Midnight Muncy’s 2 2 100-70-10 36 33 1,967
Rock and Aroldis 3 3 94-75-11 105 104 2,544
Skubal Snacks 4 4 92-76-12 146 144 1,678
Welcome to the JUNGle 5 7 91-83-6 51 48 804
Dingers Only 6 6 88-81-11 112 109 793
All Rise 7 9 73-97-10 61 59 615
Datalickmyballs 8 5 74-101-5 20 18 1,800
Shohei Me the Money 9 10 70-99-11 8 5 154
PCA and some bums 10 8 63-102-15 12 9 1,503

Spearman correlation against category wins:

  • Lineup moves: ρ = +0.661, p = 0.038 — significant at the 0.05 level.
  • Adds: ρ = +0.564, p = 0.090 — not significant.

With only ten teams this is weak evidence and purely correlational — engaged managers are probably also better drafters. But the direction is consistent, and the extreme case is stark: Shohei Me the Money made 8 adds and 154 lineup moves all season, roughly one move every 27 hours of a 166-day season, and finished dead last. Setting a lineup in March and walking away is a losing strategy.

The counter-example is my own team. Datalickmyballs made just 20 adds — third-fewest — but 1,800 lineup moves, and although it finished with the second-worst category record (74-101-5), it won both consolation-bracket rounds to climb from the 8th seed to a 5th-place final standing. It also led the league in SVHD (125, tied) and finished 3rd in HR. The roster was thin; the weekly management wrung a lot out of it.


Finding 7 — The signal models, audited honestly

The Idea 16 waiver watchlist ran 22 snapshots between June 19 and September 8, scoring every sub-80%-owned player against eight pre-pickup signals. Of the 49 players who ever fired 7 or 8 of 8 signals, 36 (73%) were actually added by a league team. That is a genuinely encouraging hit rate — the model was largely identifying the same players the ten managers independently converged on. Names that fired all eight and were not picked up (Martin Perez, Reynaldo Lopez, Eric Lauer, Andrew Painter, Hayden Wesneski) are the interesting residual for next season.

The Idea 17 multi-method consolidation is where re-running against the repaired game logs changed the answer — and not flatteringly. The June run, built on the gap-affected boxscore file and a half-season ground-truth set, put the batter confidence score’s rank-biserial correlation at r = 0.471. Rebuilt on complete game logs and full-season labels, it drops to r = 0.227. Pitchers fall from 0.224 to 0.171. The top tier (Idea 16 rule and ≥3 Idea 17 methods) slips from lift 1.32 to 1.21 for batters.

The control here is 2025, whose data I did not touch: it barely moved (batters 0.777 → 0.755, pitchers 0.530 → 0.543). A 2026 number that halves while the 2025 number holds steady is a real change, not pipeline noise. The honest reading is that the mid-season results were flattering, and that the multi-method approach which looked strong in 2025 (r = 0.755) largely did not replicate in 2026 (r = 0.227).

Two caveats on that conclusion. First, two things changed at once — the repaired features and a ground-truth set that grew from 257 to 470 pickups as the season completed — so I can’t cleanly attribute how much of the drop is data repair versus a larger, more marginal pickup population diluting the signal. Isolating that needs a run with old labels and new features. Second, the Idea 17 watchlist CSV still retains only a single snapshot (September 7), so the runtime scorer remains un-auditable over time regardless — a pipeline problem, separate from the modeling result above.


Data gaps and caveats

Flagging these explicitly, because the first one is significant:

  1. The MLB boxscore file was missing 253 of the season’s 2,166 games — 11.7% — and has now been backfilled to complete. Audited game-by-game against the MLB Stats API schedule, 2026_mlb_stats_boxscore held only 1,912 games. 17 dates were fully missing: July 6, July 16, July 20–22, August 5, August 7–16, and August 19. A further 19 dates were partially collected, going back to the season’s first week — April 4, April 5, April 14, April 26, April 30, May 23, May 24, June 1, June 24, July 11, July 17, July 19, July 28, July 29, August 6 (only 1 of 11), August 17, August 18, August 29, September 4. A targeted gap-scan backfill (diffing collected game_ids against the API schedule and fetching only the missing games) closed it: the file now holds every completed regular-season game, 2,165 of 2,165, verified with zero duplicate keys.
  2. Only July 13–15 are genuine off-days. The 2026 All-Star break ran July 13–15 — no regular-season games of any kind were scheduled, and July 14 carries only the All-Star Game itself (gameType=A). July 16’s single game (Mets @ Phillies) is a real miss, not a break day.
  3. A word on how that was verified, because the obvious check is wrong. ESPN’s scoring date is offset one day ahead of MLB’s official game date: MLB’s July 12 slate (15 games) appears in the ESPN file as July 13 (531 AB), and MLB’s lone July 16 game shows up as ESPN July 17 (43 AB). So “the ESPN file shows at-bats on that date” does not establish that games were played on it. Every gap above is confirmed against the MLB Stats API schedule directly. This offset is worth knowing about generally — any date-aligned join between the ESPN and MLB files in this project needs to account for it.
  4. No headline number in this article is affected. Every team total, category rank, leaderboard, pickup valuation and half-season split above is computed from 2026_espn_stats_daily, which is complete — 166 of 166 scoring days, no missing dates, no low-volume days. The one-day ESPN offset doesn’t move season totals either; it only shifts which calendar day a stat is filed under, and at most one day’s production sits on the wrong side of the June 17 half-season boundary or an add date. The boxscore gap did degrade anything derived from MLB game logs — specifically the 7-day/14-day rolling features behind the Idea 16 and Idea 17 signals. Idea 17 has since been rebuilt against the repaired logs, and the revised figures are the ones quoted in Finding 7 (the June numbers are shown alongside for contrast). The 73% Idea 16 hit rate has not been rebuilt: it was computed from 22 historical daily watchlist snapshots, each written at the time against whatever data existed then, and regenerating them means recomputing every snapshot individually — so treat that figure as provisional. Finding 5 is unaffected either way: the Statcast bat-tracking figures come straight from Baseball Savant’s season-to-date leaderboard, fetched independently of the boxscore file.
  5. Root cause — four separate bugs, which is why it went unnoticed for a season.
    • Intermittent TLS failures. The collection machine sits behind a TLS-intercepting proxy, and statsapi.mlb.com sporadically throws SSLCertVerificationError: self-signed certificate in certificate chain. This reproduced live during the audit — one failure in the middle of a loop whose other 15 requests succeeded.
    • Those failures are swallowed silently. get_game_ids catches every exception and returns an empty list, so one SSL error on the schedule call makes an entire run collect nothing; get_boxscore returns None and the loop continues, quietly dropping single games. Three runs in the log (June 4, July 23, August 31) recorded games=0, rows=0 — and July 23 is exactly the run that should have picked up July 20–22. The run log hardcodes 'status': 'ok', so nothing ever flagged it, and a 16-day operational gap (no run at all between August 3 and August 19) passed unnoticed.
    • The gap could never self-heal. The incremental start date was max(dates already having ≥300 rows). Once the August 19 run wrote rows for August 17–18, that high-water mark jumped past the empty August 5–16 stretch and no scheduled run could reach back. By September it sat on September 7.
    • Doubleheaders were structurally impossible to store. The dedup key was (date, player_id, b_or_p) — with no game_id. A player who appears in both halves of a doubleheader legitimately needs two rows for one date, and the second was always discarded as a duplicate. 16 of the 31 games missing on “partial” dates were doubleheaders, not fetch failures — a quiet, permanent loss that had nothing to do with the network. The key now includes game_id, and re-running the collector immediately recovered 53 previously-blocked player rows from the August 29 doubleheader alone.
    • Postponed games were being written as real ones. MLB reports abstractGameState == 'Final' for postponed games (detailedState: 'Postponed', codedGameState: 'D'), so the collector’s != 'Final' filter accepted them and wrote ~52 rows of zeroed roster placeholders. The filter now also requires codedGameState == 'F'. One such phantom — a Rays/Yankees game rained out on May 23, makeup not played until September 22 — had landed in the file dated in the future, and was removed.
  6. Idea 16 has no first-half coverage — its first snapshot is June 19, so pickups made in March through mid-June (including the two best of the season) were never scored by it.
  7. Standings came from the live ESPN API, not the data lake. The stored 2026_espn_scoreboard_matchup snapshot is from June 20, carries 0.0 for every score, and still lists 35 of 90 matchups as UNDECIDED. 2026_espn_schedule_matchup only maps scoring periods 1–88 (through June 21), so the period-to-date mapping for the season’s second half is not reconstructable locally either.
  8. Two stale artifacts were deliberately not used: 2026_espn_best_pickups.csv (June 18, and built on the gap-affected MLB archive) and 2026_local_trade_finder.csv (June 11). The pickup analysis here was rebuilt from scratch against ESPN daily data.
  9. A bug was found and fixed in analyze_team_scorecards.py. It grouped by team_name rather than team_id, so the four mid-season renames fragmented into eight partial-season entities and the script ranked a 14-team league. Its published category ranks before the fix were wrong — for example my own team appeared 1st in HR and 2nd in R, when the correct figures are 3rd and 6th. It also crashed on a missing import os.
  10. W-L-T records are category records, not matchup records. Each of the ten categories is won, lost or tied independently every period, so 106-67-7 means 180 category decisions across 18 matchup periods.

Next Steps / TODO

  • Backfill the 253 missing games in 2026_mlb_stats_boxscore — done; the file now covers every completed regular-season game.
  • Fix the doubleheader dedup key and the postponed-game filter in fetch_stats_mlb_boxscore.py — done.
  • Re-run Idea 15 and the Idea 17 consolidation against the repaired game logs — done; Finding 7 now quotes the rebuilt figures.
  • Isolate why the 2026 confidence score halved: re-run Idea 17 with the old 257-row ground truth against the new features, to separate the effect of the data repair from the effect of a fuller, more marginal pickup population.
  • Refresh Idea 16’s research script separately — it reads 2026_mlb_stats_daily_archive.csv (stale since June 3), not the boxscore file, so the backfill did nothing for it.
  • Harden fetch_stats_mlb_boxscore.py against the intermittent proxy SSL failures: retry with backoff around both get_game_ids and get_boxscore, point requests at the proxy’s CA bundle via REQUESTS_CA_BUNDLE rather than disabling verification, and make the run log record the real status plus games_expected vs games_collected so a silent partial run fails loudly.
  • Replace the max(dates with ≥300 rows) high-water-mark start date with the same gap scan used for the backfill — diff collected game_ids against the API schedule and fetch whatever is missing. That makes the collector self-healing instead of permanently blind to anything behind its watermark.
  • Make watch_multi_method_signals.py append snapshots with a dedup key instead of overwriting, so Idea 17 becomes auditable next season the way Idea 16 already is.
  • Investigate the 13 players who fired 7–8 of 8 Idea 16 signals and were never rostered — did the model find real value the league collectively missed, or is that the model’s false-positive tail?
  • Retest the lineup-moves-versus-wins correlation across 2025 and 2026 pooled; ten teams in one season is too small a sample to conclude much, but two seasons of daily data would roughly double it.

Home

Last Updated: 2026-09-08


This site uses Just the Docs, a documentation theme for Jekyll.