Skip to main content
MLForecastAdapter wraps a global ML model (one model fit across the whole panel) with lags and calendar features doing the work that a per-series statistical model does structurally. We can then calibrate on the errors from the fitted ML model.

Fit the global model

Standard mlforecast: lags at the seasonal boundaries, calendar features, and two target transforms: a per-series standard scaler and one seasonal differencing step.
Scale the panel, or the small series get no interval at all LocalStandardScaler is not decoration here. These eight series span three orders of magnitude, and a single global tree model trained on unscaled targets simply ignores the small ones — its splits are chosen to reduce error on H50, whose values are in the tens of thousands. Dropping the scaler from this pipeline takes marginal coverage from 95% to 71%, and the two smallest series (H200, H300) from 96% and 83% down to 2% and 0%. Conformal prediction cannot repair that. Calibration widens a band around a point forecast; it cannot make a forecast that ignores your series informative. Fix the model first, then calibrate it.

The one capability it lacks

MLForecastAdapter is a point forecaster only. There is no SupportsQuantiles, so CQR is unavailable.
Why not just ask LightGBM for quantiles? Setting objective="quantile" fits one model per quantile, so you would need a different MLForecast object per level, and the adapter speaks for one model. The package does not paper over that with an abstraction that fits models behind your back. If you want interval shape from a boosted model, the supported route is SPCI, which learns the residual distribution instead.
Everything else works. MLForecastAdapter also rejects a few configurations at construction rather than later: an MLForecast built with mlforecast’s own prediction_intervals=, with static features, or with a weight column is refused outright, because the adapter cannot honour those semantics.

Calibrate and predict

Measured coverage

Coverage lands at 76.7% against a 90% target, with H300 and H50 at barely half. Nothing about the calibration is wrong: the interval is sized from cross-validation windows inside the training period, and this holdout sits entirely after it. A global tree model’s error grows once the forecast origin moves past where it was fitted, and a band calibrated before that point cannot anticipate it — no conformal method can see, from inside the training data, that the forecaster is about to get worse. Refitting on a schedule is the structural answer. ACI recovers a little of it (77.6%, and the better Winkler score of the two) because evaluate feeds it the truths as it rolls, but it is correcting a level when the problem is the point forecast.
A global model does not give you global calibration One LightGBM produced every forecast above, but the conformal quantile is still taken per (series, horizon) cell. That is deliberate: a global model’s errors are systematically different across a panel whose series span three orders of magnitude, and pooling residuals across them would give every series the same band — far too wide for the small series, too narrow for the large ones. Sharing the model across series and sharing the calibration across series are independent choices, and this package makes the second one for you.

Next

  • StatsForecast — the same panel, per-series statistical models.
  • NeuralForecast — and a neural global model.
  • SPCI — varying interval width without a quantile model.