The stack
A forecast passes through these layers in order. Nothing in it identifies a player by name or id: each player-season is described only by what he did on the floor, so any player can sit in any lineup.
- Possessions
Every possession from 2001–02 to 2025–26, with the ten players on the floor and every event's players.
- Player states
Each player's rates, role, rebounding and defense as of any date, built only from earlier games.
- Capability estimates
Monthly regressions that separate a player's own events from his effect on teammates and on the players he defends.
- Event network
A neural model that turns ten players into the expected events of one possession and the points they produce.
- Calibration
Each fit is pulled toward the league average by the amount history says it overreaches.
- Combination effects
Learned and measured adjustments for pairs of players who play differently together than apart.
- The range
An 80% range built from real-lineup error, cross-era error and named alternative assumptions, with the reasons it is wide.
- In your browser
The whole model runs in the page, with no server, in background workers. It matches the Python model in tests on 1,200 matchups.
Data
The source is the play-by-play of Basketball Reference (Sports Reference LLC). A possession records who had the ball, how it ended, the points, the five players on each side and the text of every event, with each event's players identified by their Basketball Reference id. Teammates who print the same name, like Jalen and Jaylin Williams, are told apart.
In October 2026 the possession table was rebuilt from the original pages wherever the old scrape had gaps: games short of the official score, games with no possessions, and every game with two same-name players on the floor. Each rebuilt game matches the official score exactly once technical free throws are set aside. Training rows group possessions by game, offense five and defense five, with counts of every event: about 1.6 million rows.
Describing a player
Each player has a state for any date, computed only from games before it. Counts decay with half-lives of 180 and 730 days, and thin samples are shrunk toward the population.
- Offensive state
- 18 numbers: how often he takes shots, gets to the line and turns the ball over; where his shots come from across six zones (rim, paint, mid-range, long mid-range, corner three, above-break three); how often each zone goes in; free-throw percentage; how often he assists; how often his makes are assisted.
- Role
- Recent minus long-run usage, and the average of his past teammates, so the model knows the context his numbers came from.
- Rebounding
- His share of the offensive rebounds he could collect, with the evidence behind it.
- Defense
- 19 descriptors: steals, blocks, defensive rebounds, fouls, and what opponents do with him on the floor.
- Capability estimates
- 97 offensive and 49 defensive numbers from the capability library, described next.
The tool works with player-seasons: a player as he stood on the next season's opening night. By default each player-season is placed relative to its own league, so a 2004 center is compared with 2004 centers. "As they played" keeps his raw rates instead.
Capability estimates
Raw rates mix a player's own skill with the teammates and opponents around him. The capability library separates them. Every month it fits regularized regressions on all earlier possessions, weighted toward recent ones, for four kinds of event: shot, free-throw and turnover rates; where shots come from; how often they go in; and who gets the offensive rebound. Each player's event in each possession is explained by three kinds of term: the player himself, his four teammates, and the five defenders.
So every player carries three blocks of 16 estimates, one per event type:
- His own game
- His events against an average player in the same spot, after adjusting for the other nine.
- On his teammates
- How the other four's events change while he is on the floor. A playmaker who cuts his teammates' turnovers, or a passer who lifts their three-point accuracy, shows up here.
- When he defends
- How the events of the five players he faces change while he is on defense, such as fewer shots at the rim or lower accuracy there.
Each estimate comes with its standard error and the amount of evidence behind it. The penalty that controls how far estimates are shrunk is chosen once per season, on the previous quarter. Open Details under any player in the tool to see his estimates in readable units.
The event network
The network takes an offense five and a defense five and returns the expected outcome of one possession, written out as a ledger of events: shot attempts by zone, makes, free throws, turnovers and offensive rebounds. Points come from adding up the ledger.
- Offense
- Each player's state is adjusted by his teammates (the average and spread of the other four) and by his role, then decoded into 15 numbers: how often he shoots, gets to the line and turns it over, where he shoots from, and how often he makes it. Small heads add the capability estimates: his own, and the average of his teammates' effect on teammates.
- Defense
- The reference model averages the five defenders' descriptors and capability estimates into one shift applied to all five attackers. The alternative, capacity defense, counts rim protection from the two best inside defenders and pairs each attacker with one defender. It appears only in the range.
- The ledger
- Opportunities share one budget per possession: shot attempts plus 0.44 free-throw attempts plus turnovers. There is one ball. Shots split across the six zones. Make rates fall when the lineup needs more assisted shots than it has passing, or when a player carries more than his usual load. Misses lead to rebounds, and offensive rebounds start the cycle again.
- Training
- The five seasons before each forecast (2021–22 to 2025–26 for this release), weighted toward recent games with a two-year half-life. Older seasons enter only through each player-season's measured habits. The loss averages the likelihood of four kinds of events and adds a quarter of the squared error in points. The offense is trained first, then the defense on top. The number of passes is chosen on the previous quarter, and the model is refit on the whole window. The forecast mixes the last five checkpoints of each of three independent fits.
Every head is a small two-layer network that starts at zero, so a new part begins as no change and has to earn its effect.
Calibration
Each fit's forecast is pulled toward the league average: league + intercept + slope × (forecast − league), with slopes near 0.80. The constants come from how the same model design, refitted on the rebuilt data, overreached on earlier seasons, 2015 to 2026, with only information available before each forecast.
Combination effects
For typical lineups the network nearly adds up its players: five good players make a good lineup in proportion, and adding up overall qualities lands within a point or two of it. Combination effects are something separate: the pairings that play differently together than apart, beyond what adding up already assumes.
Learned combinations
A small module reads every pair of teammates and every pair of defenders through the same inputs the network reads, and changes the network's events: shot mix, makes, free throws and turnovers. It is trained on real lineups for a fixed number of passes with the network frozen, and its outputs are held inside the range real lineups reach, so clones and impossible lineups cannot push it further. Its average effect on the league's lineups in the last quarter before the season is removed, so it only moves a lineup relative to the league as it stands. The forecast uses it at half strength. On 24 quarters of 2016–21 games that no design choice had seen, refitted on the rebuilt data, this changed forward accuracy by +0.0006 r² (−0.0007 at full strength). On the earlier data the same check gave +0.0010.
Measured combinations
Player types are the top or bottom fifth of each season's players on one measure, such as big, small, shooter, non-shooter, passer, self-creator, slasher, offensive rebounder, shot-blocker or defensive rebounder. 105 type pairings were searched across eight outcomes in 2016–21, and checked on 2022–26 games the search never saw. On the rebuilt data twelve held up there, all in shot locations and free throws. (On the earlier data fourteen had: the three turnover pairings dropped out, and bigs beside defensive rebounders came in.) Each was then re-checked on 2007–13, and the tool shows the result: seven also held up there, four pointed the same way more weakly, and one pointed the other way. None was big enough to see directly in points; the detection limit is about 0.5 points per 100 per pairing.
Each effect is fitted on 2022–26, leaving out the last two minutes of close games, and counted only beyond what adding up already assumes. Points come from accounting at the offense's own rates. Most player types appear at most three together in real games; past that, the forecast holds each effect at its three-player value, and the range covers the alternative where effects keep adding pair by pair. The measured effects are fitted on top of the learned module, so neither counts the same thing twice. Turning them on changes forward accuracy on real 2022–26 lineups by +0.00001 r², which is nothing either way. Their purpose is to bend unusual lineups for a stated, measured reason.
The range
The 80% range is the widest span covered by the forecast under each named assumption, plus model error on either side.
- Model error
- A five's long-run level (its rating with game-to-game luck removed) differs from the forecast with a standard deviation of about 3.2 points per 100 on each end and 4.4 on the net. This is measured on real 2016–2026 lineups from how well each lineup's two halves of games agree with each other beyond the forecast.
- Other eras
- For lineups with player-seasons from before its training window, the model ranks real lineups with about 86% of its in-era correlation under either setting, so the range widens by the share of the lineup from other eras.
- Assumptions
- A stricter view of defense (capacity defense: only the two best rim protectors count, and each attacker is matched with one defender); measured combination effects that keep growing past the counts real lineups reach; and the forecast without learned combinations. Their spread is shown as assumption-based.
- Reasons
- The tool says why a range is wide: a composition no real lineup comes close to, missing roles such as no ball handler, repeated players, thin data, cross-era use, or a large assumption effect.
A lineup's long-run level is never observed directly, so the range can't be checked by counting how often game results land inside it: results over a few hundred possessions carry their own luck. Its width on real lineups comes from the split-half measurement above. Ranges for lineups nobody has played rest on the stated assumptions, not on games. Comparing levels across eras is a modeling choice: "relative to their league" removes league-wide trends, "as they played" keeps them.
Overall quality
Each player-season's overall quality is his share in the model's best straight-line fit: the network's ratings of tens of thousands of position-balanced lineups, fitted as a constant plus one number per player, separately for offense and points allowed. Net is the difference, and a typical 2025–26 player is about 0. The straight line also has a starting point: five typical players come out about 4 points per 100 below the tool's league-average lineup, which is the average lineup that played 100+ possessions together, and the result card shows that start so its arithmetic adds up. Adding up five players' qualities lands within about 1 point per 100 of the model for typical real lineups from any era, and within about 2 points for nine in ten. The model is not a straight line, so the estimate drifts further for unusual lineups such as clones, five bigs or no ball handler. That drift is separate from the combination effects.
The missing piece
The search keeps four of Team A and tries every candidate in the fifth spot. Candidates are the players of one season, starting at the season of the player being replaced (any season from 2001–02 to 2025–26 can be chosen), or every player at his default season, leaving out player-seasons with under 500 offensive possessions. The opponent is either a league-average lineup or Team B's five, as in the main result.
An optional limit on overall quality narrows the candidates, for example to players a team could realistically trade for rather than the league's stars. It starts at the overall quality of the player being replaced, and any number can be typed in. Overall quality is the linear approximation shown under each player (net, per 100 possessions, under the current player-level setting), so the limit is approximate: the search still ranks the remaining candidates by the full forecast.
Against a league-average lineup, an exact forecast runs 15 networks against 561 real lineups, with and without the learned module. That is about 17,000 small calculations, roughly 10 ms in a browser. Against Team B's five it is about 60 of them, so that search is several times faster. Either way the search works in two steps.
- A screen scores every candidate with one network per seed. Against a league-average lineup it also uses only 10 lineups on each side.
- The best screened candidates get the exact forecast, in screen order. This stops when no remaining candidate could reach the top ten: the screen's mean error so far, plus its largest deviation, plus half a point, still leaves the next candidate below the tenth exact forecast.
On eight four-player cores from 2025–26, this found the exact top ten every time: after 16 to 32 exact forecasts against a league-average lineup, and 16 to 40 against two specific fives. The list shows only exact numbers. The forecast, its 80% range and the combination effects are what the main result shows for that lineup.
Against Team B's five, the combinations column is in the margin, so it holds both teams' effects: Team A's minus Team B's. Team B's own are part of every row. Against a five with strong pairings of its own, such as the 2017 Warriors, every row starts about a point lower. Compare the rows with each other, not with zero. The two sides can't be separated exactly, because each team's pairings change how the other team's possessions play out.
The best candidates usually sit within a point or two of each other, inside each other's ranges. Read the list as a short list, not a verdict on who fits best.
Breakdowns
Volume, shot mix, conversion and free throws add up to the gap from a league-average offense in the model's own numbers. They describe how the model gets to its forecast, not proven causes. "League average" means the 2025–26 lineups that played at least 100 possessions together, on offense and on defense.
Accuracy
Measured forward in time: each quarter of 2016–2026 forecast by a model trained only on games before it, scored on possession-weighted lineup outcomes over 44 quarters. r² is the share of the variation in lineup scoring that the forecast explains (one minus the weighted squared error over the total variance). Lineup results over a quarter-season carry a lot of luck, so even a perfect forecast would explain only part of it.
On the rebuilt data, the calibrated network alone scores r² 0.1594 over 44 quarters, and 0.0988 within each quarter (how well it ranks lineups against others in the same quarter). On the earlier data it scored 0.1615 (0.1012), and the release before that, which blended in a straight-line player model, 0.1630. Those used different game records, so the comparison is only rough. The changes below are measured on the populations named.
| What | Change in r² | Population |
|---|---|---|
| Dropping the straight-line half of the earlier release | −0.0015 | Lineup quarters, 44 quarters, earlier data; the price of a model that is not linear in copies of a player |
| Learned combinations, half strength | +0.0006 | 24 fresh quarters of 2016–21, rebuilt data |
| Measured combinations | +0.00001 | Real 2022–26 game-level lineup pairs, rebuilt data |
Refitted on the rebuilt data in October 2026, except the straight-line half, which was measured once on the earlier data.
What is not checked
- Ranges for lineups no team has played. They follow from named assumptions and cannot be checked against games.
- Cross-era comparisons. Placing a 2004 player in today's league is a choice of reference, not a measurement.
- About 1% of play-by-play events credit a player missing from the recorded five, usually around a substitution. Those events count for the team but not for the player.
- 55 old games whose pages could not be parsed keep the original scrape's possessions.
- A separate forecast of the 2026–27 season was frozen before it began and is scored only after the games. It is not what the tool shows.
About this site
Made by Adam Levin and Claude Code. The code is open source under the MIT licence at github.com/adamwlev/lineuplab, without the data; questions and bug reports are welcome as issues there.
Data: play-by-play from Basketball Reference (Sports Reference LLC), 2001–02 through 2025–26, with the games that had problems (missing, short or mixed-up records) rebuilt from their game pages in October 2026.
2026–27 teams: the opening-night rosters from Wikipedia's NBA roster templates (CC BY-SA 4.0), as of 19 October 2026. The projected starters come from the latest reporting: Sports Illustrated's projections of 17 October, with newer team reports for the Warriors (the five Steve Kerr is leaning towards), the Kings (Bleacher Report's five) and the Jazz (Jaxson Hayes for the injured Jusuf Nurkić). A rookie projected to start has no NBA data yet, so a teammate who played in 2025–26 stands in: the one at his position who started the largest share of his games, if that is at least a quarter of them, and otherwise the teammate who started most often. The slot says so. Each player is as of his latest season.
Privacy: the whole model runs in your browser. Nothing you type is sent anywhere. The page loads its fonts from Google Fonts, and your browser remembers the last lineup you built so a reload keeps it; nothing else is stored.