Skip to content

feat(forecast): add LightGBM feature-aware forecasting model (#242)#243

Merged
w7-mgfcode merged 1 commit into
devfrom
feat/forecasting-lightgbm-first-model
May 19, 2026
Merged

feat(forecast): add LightGBM feature-aware forecasting model (#242)#243
w7-mgfcode merged 1 commit into
devfrom
feat/forecasting-lightgbm-first-model

Conversation

@w7-mgfcode
Copy link
Copy Markdown
Owner

Summary

Implements PRP-30 (MLZOO-B) — the first advanced feature-aware forecasting model. Closes #242.

Adds LightGBMForecaster (wrapping lightgbm.LGBMRegressor) on top of the leakage-safe shared feature-frame contract from PRP-29 (MLZOO-A, #238). LightGBM ships as an optional dependency group so a single-host install stays dependency-light.

What changed

  • LightGBMForecaster (forecasting/models.py) — requires_features=True, structural twin of RegressionForecaster. lightgbm is lazy-imported inside fit() so importing the module never needs the optional extra. Deterministic via n_jobs=1 + deterministic=True + force_col_wise=True + fixed random_state.
  • model_factory — the lightgbm branch now instantiates the real forecaster (behind the existing forecast_enable_lightgbm flag); NotImplementedError removed.
  • Scenario re-forecastScenarioService.simulate dispatch generalised from a hard-coded model_type == "regression" to capability-based bundle.model.requires_features, so a LightGBM bundle takes the genuine model_exogenous path.
  • JobsJobService._execute_train accepts model_type="lightgbm"; _execute_backtest unchanged (feature-aware backtesting deferred to PRP-MLZOO-B.2).
  • ReproducibilityModelBundle.lightgbm_version (best-effort save + mismatch-warn on load) and registry runtime_info["lightgbm_version"]. No migration — runtime_info is JSONB.
  • Dependency — new [project.optional-dependencies] ml-lightgbm; uv.lock regenerated; mypy override for lightgbm.*. Core dependencies list unchanged. CI already runs uv sync --frozen --all-extras --dev.

Out of scope (per PRP DECISIONS LOCKED)

No second model (XGBoost/Prophet → MLZOO-C), no hyperparameter search, no feature-aware backtesting (deferred to PRP-MLZOO-B.2 — test_feature_aware_model_fails_loud_in_backtest stays), no migration, no API/WebSocket contract change, no baseline-model change.

Minor accuracy fixes folded in

  • Generalised three regression-specific strings in scenarios/service.py (a docstring + an error message) to "feature-aware" so a LightGBM bundle reads correctly — behaviour-preserving for regression.
  • Added the missing regression row to README's supported-model-type list.

Validation

  • ✅ ruff check + format, mypy --strict, pyright --strict — all clean
  • ✅ 1321 unit tests pass; new test_lightgbm_forecaster.py (13 tests, importorskip-guarded)
  • ✅ 70/70 integration tests pass on a fresh DB (forecasting / scenarios / jobs / registry)
  • ✅ baselines, regression, and the backtest loud-fail guard unchanged
  • ✅ deterministic forecasts, lazy-import contract, and the examples/models/advanced_lightgbm.py example all verified

Note: a benign UserWarning ("X does not have valid feature names") surfaces from the sklearn↔LightGBM wrapper — cosmetic, not gated.

Implements PRP-30 (MLZOO-B) — the first advanced feature-aware
forecasting model, LightGBMForecaster wrapping lightgbm.LGBMRegressor,
on top of the PRP-29 shared feature-frame contract.

- LightGBMForecaster (requires_features=True), structural twin of
  RegressionForecaster; lightgbm is lazy-imported inside fit() so the
  module never requires the optional dependency. Deterministic via
  n_jobs=1 + deterministic=True + force_col_wise=True + random_state.
- model_factory lightgbm branch (behind forecast_enable_lightgbm).
- ScenarioService.simulate dispatch generalised from a model_type
  string to bundle.model.requires_features — a LightGBM bundle now
  takes the genuine model_exogenous re-forecast path.
- JobService._execute_train accepts model_type=lightgbm.
- ModelBundle.lightgbm_version + registry runtime_info captured
  best-effort; no migration (runtime_info is JSONB).
- LightGBM ships as an optional [project.optional-dependencies]
  group ml-lightgbm; uv.lock regenerated.

No baseline-model change, no API contract change, no migration.
Feature-aware backtesting stays loud-fail (deferred to PRP-MLZOO-B.2).
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f710539d-02f2-48df-9378-74342c74aa83

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/forecasting-lightgbm-first-model

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @w7-mgfcode, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@socket-security
Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedpypi/​lightgbm@​4.6.099100100100100

View full report

@w7-mgfcode w7-mgfcode merged commit 2b44491 into dev May 19, 2026
10 checks passed
@w7-mgfcode w7-mgfcode deleted the feat/forecasting-lightgbm-first-model branch May 20, 2026 03:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant