Early-Season Fantasy Basketball: Last Season's Stats Almost Made Me Drop a Top-5 Player

Two days into the NBA season, my waiver script told me to drop Yves Missi. He was the lowest-value player on my roster by a clear margin. Then I opened Yahoo, and the same player was ranked 4th overall for the season.

Both numbers were "right". They were just answering different questions. This post is about that gap, why it's widest in the first few weeks, and the check I now do before every early-season drop: season-to-date 9-category ranks built from this season's box scores.

The setup

I play in a 12-team, head-to-head, 9-category league on Yahoo (FG%, FT%, 3PM, PTS, REB, AST, STL, BLK, TO). My scripts value players with z-scores: for each category, how many standard deviations above or below an average rostered player someone is, then sum the nine.

Early in the season the scripts deliberately use last season's averages, because one or two games is far too small a sample. That's reasonable most of the time. It fails in one specific way: it can't see a role change.

What last season said vs. what happened

  • Last season: Missi came off the bench for about 20 minutes a night. Few points, no threes, weak free throws. In 9-cat terms, a blocks-and-rebounds specialist with a negative total.
  • Opening game: he started at center and played 30 minutes: 13 points, 14 rebounds, 5 assists, 2 steals, 3 blocks, 5-of-6 from the field, 3-of-4 at the line.

Was that a fluke? The box score answers part of it: every teammate listed as not playing that night was out by coach's decision, not injury, so the start doesn't look like a one-night fill-in. A rank built on one game is noise, but starting plus 30 minutes is a role, and roles tend to stick.

Season-to-date ranks from box scores

Season-average stat tables tend to lag in the first days of a season. The one my scripts use had only been updated with the opening-night games, six teams, so most of the league, including Missi, wasn't in it yet. Box scores, on the other hand, are complete as soon as each game ends. So instead of waiting, I sum this season's box-score lines myself and rank players the same way my scripts rank last season:

  • Per-game averages, so a player who has played two games isn't ranked above one who has played one.
  • The player pool is the 156 players with the most total minutes (12 teams × 13 roster spots). Means and standard deviations come from that pool, not from every end-of-bench player.
  • Percentages are volume-weighted. FG% becomes "makes above what a league-average shooter would make on the same attempts". A 5-of-6 night helps you more than a 1-of-1 night, which matches how percentages actually move in a weekly matchup.
  • Turnovers are negated, since fewer is better.
  • Each category's z-score is (value − pool mean) ÷ pool standard deviation, and the nine are summed.

How close is it to Yahoo?

Yahoo doesn't publish its exact ranking formula, so I compared against the ranks its app showed me for players on my roster after the same games:

PlayerYahooBox-score scriptMinutes
Yves Missi4630
Tyrese Maxey6540
Jalen Duren313228
Michael Porter Jr.494234
Ivica Zubac645734
Davion Mitchell12913333
Andrew Wiggins23723327
Keegan Murray27025528

Across the 14 players I checked, most landed within about 10 spots of Yahoo's rank. That's close enough to use as a stand-in when you want the numbers in your own spreadsheet or script rather than in an app.

The real lesson: read minutes, not ranks

Look at the bottom of that table. Andrew Wiggins and Keegan Murray were solid fantasy contributors last season, and after one game they sit around 230–270. Their minutes were normal; they just had a bad shooting night. Dropping them on that rank would be the same mistake as dropping Missi on last season's numbers, only in the other direction.

A second example from the same night: Yahoo told me that Reed Sheppard had been dropped by over a thousand teams. His line was 3 points on 1-of-6 shooting in 16 minutes off the bench. The rank (219 in my script) made the drops look obvious. The minutes told the actual story: two guards ahead of him in the rotation, a veteran starter back from a long injury playing 30 minutes and another guard playing 26. Part of last season's role came while that starter was out, and it's gone for now. That is worth watching for another game or two, not a panic drop and not a hold based on last year.

So my early-season rule is now:

  1. Last season's averages tell you a player's skills.
  2. This season's minutes and starting role tell you whether he'll get to use them.
  3. This season's rank is mostly noise until about 10 games in. Use it only to spot role changes worth checking, never as the reason to drop someone.

Box scores mark who started, so the check is easy to make a habit: before trusting either set of numbers, look for anyone whose minutes or starting status changed sharply from last season.

Caveats

  • This approximates Yahoo-style 9-cat value. It isn't Yahoo's formula, and leagues with different categories need a different set of categories.
  • On any given day, some teams haven't played yet, so a player's rank can move just because the pool changed.

Summary

  • In the first weeks, last season's averages can't see role changes, and this season's ranks are mostly noise.
  • Season-average tables lag early in the season, so summing box scores is the fastest way to get season-to-date numbers.
  • Before dropping anyone early, check minutes and starting role. That one check kept a top-10 player on my roster.

Comments

Popular posts from this blog

Gear Ratio Calculator: Multi-Stage Ratio, Output Speed, Torque and Direction

Mecanum-Wheel Pick-and-Place Robot: From Arduino UNO to Mega2560 + ESP32-CAM

Voltage Divider Calculator: Output Voltage, or the Best E24 Resistor Pair for a Target Voltage