NRL Model Artifact Pipeline

The production prediction path is the dbt/artifact path:

  1. Build dbt ML tables.
  2. Train a versioned model artifact.
  3. Generate round predictions into DuckDB.
  4. Read gold_nrl_predictions from the app/dashboard.
  5. Evaluate with season walk-forward folds only.
bash scripts/dbt_build_nrl.sh
python -m ml.train_margin_model --train-from-season 2016 --train-through-season 2025
python -m ml.predict_weekly_margin --season 2026 --round 18
python -m ml.evaluate_margin_model
python scripts/report_nrl_lineup_feature_health.py --season 2026

Canonical Feature Sources

Use dbt ML tables rather than nrl-bet-advisor/data/nrl_historical.csv for production predictions:

  • ml_nrl_match_training_examples
  • ml_nrl_upcoming_matches
  • ml_nrl_match_lineup_features
  • ml_nrl_match_weather_features
  • ml_nrl_team_form_features
  • ml_nrl_ladder_features

Prediction Table

gold_nrl_predictions is the app-facing table. It includes:

  • match identity: season, round, match_id, home_team, away_team
  • model identity: model_id, market_type, model_version, predicted_at_utc
  • H2H outputs: predicted_home_win_prob, predicted_away_win_prob
  • compatibility outputs: home_win_probability, away_win_probability
  • margin output: predicted_margin
  • market output placeholders: predicted_total
  • recommendation fields: recommended_side, best_bet_team, best_bet_edge, value_home, value_away
  • trust flags: lineup_available
  • explanation fields: top_factors, explanation

The dashboard loader should read this table. Request-time model training is deprecated for production predictions.

Validation

python -m ml.evaluate_margin_model defaults to walk-forward folds:

  • train through 2021, validate 2022
  • train through 2022, validate 2023
  • train through 2023, validate 2024
  • train through 2024, validate 2025
  • train through 2025, validate 2026

The report includes margin MAE/RMSE, winner accuracy, Brier score, log loss, calibration slope/intercept, and probability buckets.

Recency Weighting

ml.train_margin_model uses transparent era weights by default:

  • 2016-2020: 0.55
  • 2021-2023: 0.80
  • 2024-current: 1.00

Use --no-recency-weights only for diagnostics.

Lineup Guardrail

Lineup-aware labels are only valid when lineup_available=true. Run:

python scripts/report_nrl_lineup_feature_health.py --season 2026

If a newly rebuilt dbt table still reports all-zero lineup rates for a round that should have team lists, fix the lineup staging/join before trusting lineup-aware explanations.