Model or dataset
kyleskom/NBA-Machine-Learning-Sports-Betting avatar
kyleskom/NBA-Machine-Learning-Sports-Betting

NBA-Machine-Learning-Sports-Betting: XGBoost and Neural Net Picks on a SQLite Backbone

NBA sports betting using machine learning

1,713 stars569 forksPythonLicense varies

At a glance

What is it?
A Python pipeline that joins NBA team stats with sportsbook odds, trains moneyline and totals models, and prints expected value plus optional Kelly stakes. The interesting part is the data plumbing, not the model zoo.
Who is it for?
Adopt it if you want a readable reference implementation of the full loop from raw NBA endpoints and SBR odds through feature building to a priced pick, and you are willing to treat the missing licence file and the hard-coded neural network scripts as blockers to resolve before anything leaves your laptop. Skip it if you need a maintained data contract, a documented backtest, or a service you can hand to someone else.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem is the join, not the classifier

Anyone can fit a gradient boosted tree to a table of basketball box scores. The hard part is producing a table where each row is a game, each column is known before tip-off, and the label is the outcome you actually want to price. This project exists to do that join. It pulls daily team stats from NBA endpoints into one SQLite database, pulls sportsbook odds and final scores from SBR into a second SQLite database, and then merges team stats, odds, scores and days-rest into a single training set. The README describes the whole thing in four numbered steps: collect, build features, train, predict today.

The audience is narrow and self-selecting. You need to be comfortable running Python modules from a source checkout, because there is no packaged CLI and no hosted service. You also need to accept that the output is a probability and an expected value, not a bet. The README is explicit that the script prints predictions, expected value and optional Kelly Criterion sizing, which means the final decision stays with the person reading the terminal.

Two SQLite databases and a merge step

The architecture is a batch pipeline with a file-based boundary. Get_Data writes team stats to SQLite. Get_Odds_Data writes odds and scores to a separate SQLite database. Create_Games is the join: it merges team stats, odds, scores and days-rest into a training dataset. That separation is the most defensible design decision in the repository, because odds and stats have different refresh cadences and different failure modes. If the odds source is down, your stats database is still intact and you can re-run only the odds fetch.

At prediction time main.py fetches today's schedule, builds matchup features with the same code path, loads trained models, and prints predictions. The feature construction is therefore shared between training and inference, which is the thing you want. The Flask app sits on top of the outputs for browsing rather than recomputing anything.

The weak point is the boundary itself. Nothing in the README describes a schema version, a migration, or a validation step between Create_Games and training. If the NBA endpoint changes a field name, the failure surfaces as a column of nulls in a dataset file, not as an error at ingest.

Running the pipeline end to end

The README gives a concrete sequence. Install with pip3 install -r requirements.txt against Python 3.11, with TensorFlow, XGBoost, NumPy, Pandas, Colorama, Tqdm, Requests and Scikit-learn listed as the package set. Then the data stage:

cd src/Process-Data python -m Get_Data python -m Get_Odds_Data python -m Create_Games

Training is a second directory with per-model entry points. The README shows XGBoost_Model_ML and XGBoost_Model_UO invoked with --dataset dataset_2012-26 --trials 100 --splits 5 --calibration sigmoid, and the logistic regression pair invoked the same way against dataset_2012-26_new with --trials 50. The --calibration sigmoid flag is worth pausing on: it implies the raw model output is not treated as a probability until a calibration step is applied, which is the right instinct for betting, where the price you compare against is itself a probability.

Inference is one command: python3 main.py -xgb -odds=fanduel. The supported books are listed as fanduel, draftkings, betmgm, pointsbet, caesars, wynn and bet_rivers_ny. Omit -odds and the script prompts for manual odds and totals. Add -nn, -xgb, -A for all models, or -kc for the Kelly bankroll fraction. The Flask app runs from the Flask directory with flask --debug run.

The neural network scripts are the weak seam

The README is unusually candid here, and it deserves credit for it. It states that the current NN training scripts are the original versions with hard-coded dataset and model paths, that they train on dataset_2012-24_new, and that they save into Models/ with timestamped names. It then says that if you want configurable flags or feature and scaler sidecars, you should switch back to the newer NN scripts.

Read that as a warning about reproducibility. A hard-coded dataset path means the NN you train tonight is not the NN someone else trains from the same commit, unless their working tree happens to contain that exact dataset file. Timestamped model names mean the inference path has to find the right file, and the README does not document how that selection happens. The XGBoost and logistic regression scripts accept --dataset, so they are the reproducible half of the model zoo. If you only care about one model, pick from that half.

There is a second gap. The README documents --backfill and --season for both Get_Data and Get_Odds_Data, which is a real convenience for filling holes in a season. It does not document any way to verify that a backfill produced complete coverage, and it does not document rollback if a backfill writes bad rows.

Where this is the wrong tool

The repository has no licence file, and the README does not state terms of use. A repository with an unknown licence is not something you can vendor into a commercial product without resolving that first, and the absence is itself a signal about how much the author thought about downstream consumers.

The second limitation is scope. Everything here assumes you are pricing a game before tip-off using team-level aggregates and days-rest. There is no player-level model, no injury feed, no lineup adjustment. For NBA totals in particular, a late scratch can move the number more than any team-season aggregate, and nothing in the described pipeline ingests that. If your edge depends on lineup news, this is the wrong starting point.

The third is the data dependency. Odds come from SBR, stats from NBA endpoints, and both are scraped rather than contracted. The README lists seven supported books, all of which are US-facing. If you bet a market outside that list, you are back to manual odds entry through the prompt, which removes the automation that makes the pipeline worth running.

Finally, there is no backtest harness described. Training scripts report on splits, but the README does not describe a walk-forward evaluation against closing lines, which is the only test that matters for a betting model.

How it differs from a general AutoML stack

The obvious alternative is to take scikit-learn or a general AutoML tool, hand it a CSV of games, and let it search. That approach gives you better model selection tooling and a documented API, and it is genuinely less code to maintain. What it does not give you is the two-database ingest, the days-rest feature, the sportsbook odds join, or the expected value and Kelly output. You would write all of that yourself, and the join is the part that takes the time.

A second alternative is a commercial sports betting API that returns a probability directly. Those services own the model and the data contract, so you get a number and a support channel. The trade-off is that you cannot inspect the feature set, cannot retrain on your own data, and cannot see whether the probability has been calibrated. This project's --calibration sigmoid flag exists precisely because the author cared about that step.

The honest framing is that this repository is a reference implementation of a pipeline, not a product. Its value is that the four stages are visible and editable in one checkout. Its cost is that every stage is your responsibility.

Maintenance, upgrades and what to check first

The last push was on 2026-09-12, and the release history shows a seasonal cadence: 2024-25.1.0 in December 2024, 2025-26.0.0 in October 2025, and 2025-26.1.0 in January 2026. That pattern suggests the project is refreshed around the NBA calendar rather than continuously, which is reasonable for a seasonal workload but means you should not expect mid-season fixes to land quickly.

The upgrade cost is concentrated in the datasets. Training commands reference dataset_2012-26 and dataset_2012-26_new, while the neural network scripts are pinned to dataset_2012-24_new. Moving a season forward means regenerating those files through Create_Games and then re-running training, and the README does not describe a way to diff an old dataset against a new one. Budget for retraining all four model families, not just the one you use.

On licensing: the repository has no licence file, so there are no stated terms for redistribution or commercial use. That is a fact about the repository, not a legal opinion, and it is the first thing to resolve before this code goes anywhere near a product.

Editorial conclusion

Adopt it if you want a readable reference implementation of the full loop from raw NBA endpoints and SBR odds through feature building to a priced pick, and you are willing to treat the missing licence file and the hard-coded neural network scripts as blockers to resolve before anything leaves your laptop. Skip it if you need a maintained data contract, a documented backtest, or a service you can hand to someone else. Before trusting a single number, run the Process-Data and Train-Models sequence yourself and check whether the calibration you passed actually changed the probabilities the models emit.

Official sources

  1. Issues
  2. kyleskom/NBA-Machine-Learning-Sports-Betting on GitHub
  3. README
  4. Releases
Community notes

Community notes