It started with my brother's model
My brother had built a model of his own, manually entering game scores and KenPom ratings along with a small set of features. I wanted to take a different approach: automate the data collection, build a repeatable pipeline, and test whether additional team and game-level information could improve the predictions.
The workflow
The project is designed as a pipeline rather than a one-off spreadsheet. Python pulls and prepares the data, feature engineering creates the model inputs, BigQuery stores the tables and supports analysis, and the prediction process generates estimates for upcoming games. Scheduled workflows help keep the data and predictions refreshed.
The site is intended to make the output easy to explore, while Looker Studio provides a flexible place to visualize performance and game-level predictions.
View the Python pipeline and SQL project on GitHub ↗. The repository contains the underlying implementation; model feature details are intentionally not documented here.
What goes into the model
The model uses regression to estimate the expected home-team scoring margin. The feature set is intentionally kept broad here, since it can evolve as the project develops:
- Team strength ratings
- Home-court advantage
- Team-level statistics
- Rest and recent form
The historical data challenge
One challenge is that some ratings and team-statistics endpoints provide a snapshot of the current state rather than a historical record of what those numbers looked like at a given point in the season. To build a usable historical dataset, I manually ingest those endpoint snapshots and store each one with a timestamp. That creates a time-stamped history that can support backtesting, instead of accidentally using today's ratings and stats to represent an earlier date.
Injuries and live context
Injuries are a major limitation. A key player being unavailable can make a forecast substantially less reliable before a game, and injuries or in-game availability changes can shift the matchup after tip-off. The current pipeline has no reliable injury feed or alerting mechanism, so those changes are not automatically reflected in predictions. Injury information should be checked separately and predictions treated with appropriate caution.
How performance should be judged
A prediction needs to be recorded before the game starts if it is going to count as a real forecast. I want to track prediction error over time and, where reliable closing spreads and consistent grading rules are available, evaluate against-the-spread performance separately. No single metric tells the whole story, and a good-looking result over a small sample is not proof that a model has an edge.
Still a work in progress
Because reliable historical ratings and team-stat snapshots are limited, the model is starting completely fresh with the 2026 season. As the season progresses, the timestamped dataset will continue to grow, giving the project a stronger foundation for evaluating future predictions. This is an ongoing learning project, not a promise of betting results.