Skip to main content
conformalforecast turns a point forecaster into one that emits calibrated prediction intervals. This page goes from a CSV to a 90% interval with a measured coverage rate, using statsforecast and split conformal prediction. Nothing here is specific to statsforecast. The same five steps work for mlforecast, neuralforecast, or a function you wrote yourself — only the adapter in step 2 changes.

1. The data

AirPassengers: monthly international airline passengers, from 1949 to 1960.
Hold out the last HORIZON months. The forecaster never sees them, so they are an honest test of the interval at the end. panel is the same data as a (n_series, T) array — the shape every method in the package consumes. AirPassengers is one series, so n_series = 1; the leading axis is always there.

2. Fit a forecaster and wrap it

Any statsforecast model works. AutoETS is used here because it fits in milliseconds on 132 points and this page is about calibration, not accuracy — a better model gives narrower intervals, not more valid ones. The adapter is the uniform interface the conformal method talks to. It converts Nixtla’s long-format frames into arrays, so the calibration math never sees a DataFrame.

3. Calibrate

A method is configuration: SplitConformal(alpha=0.1) holds settings and nothing else. calibrate_cv runs the forecaster’s own cross-validation, calibrates on the resulting errors, and returns a new fitted object — the method itself is left untouched, so the same configuration can be calibrated again on other data. Every method needs at least ceil(1 / alpha) windows per series (it needs 10 in this case) and raises InsufficientCalibrationSamples naming the offending series if it does not get them.
refit and the forward method calibrate_cv defaults to refit=False, which asks statsforecast to reuse fitted parameters across cutoffs. AutoETS implements forward, so that works and is roughly 15× faster. A model that does not, such as SeasonalNaive, needs refit=True, and statsforecast will tell you so.
alpha=0.1 asks for 90% intervals. The score quantile is the amount added to and subtracted from each point forecast, held as one value per (series, horizon) cell. Notice that it grows with the horizon. That is a fact about the forecaster rather than about the method: an ETS forecast twelve months out has more room to drift than one month out, and calibrating per-cell rather than with a single global constant is what lets the interval say so.

4. Predict

predict lives on the fitted object. It takes the history as a (n_series, T) array and returns both the point forecast and the interval.

5. Check the coverage

An interval is only worth as much as its coverage. evaluate rolls the fitted object over held-out windows and reports what fraction of actuals landed inside. One window of 12 steps is too small to measure anything, so roll over the last four years instead: four windows of 12 months, each predicted from the history that precedes it.
Marginal is not conditional Conformal coverage is a guarantee on average over draws, not a promise about any one cell. Coverage averaged over series and horizons can sit at 90% while a particular horizon step is systematically under-covered — which is exactly what coverage_by_horizon and coverage_by_series are for. AirPassengers also has a strong upward trend, so the exchangeability that split conformal assumes is only approximately true here; the adaptive methods exist for precisely that reason.
The per-horizon breakdown makes the point concretely: the marginal figure is comfortably above target, but step 7 — the summer peak, where a trending series is hardest to bound — covered only half its windows. A single number would have hidden that.

Next

  • Methods — the six methods, what each one is for, and when split conformal is not enough.
  • Diagnostics — measuring an interval properly.
  • Adapters — mlforecast, neuralforecast, or your own model.
  • Architecture — the method as configuration, and the fitted object it returns.