Skip to content

Forecasting Guide

polars-ts provides a complete forecasting stack — from simple baselines to ML pipelines, ensembles, and probabilistic intervals.

Baseline models

Start with baselines to establish a benchmark before moving to complex models.

import polars_ts as pts

naive = pts.naive_forecast(df, h=12)
seasonal = pts.seasonal_naive_forecast(df, h=12, season_length=24)
ma = pts.moving_average_forecast(df, h=12, window_size=7)
fft = pts.fft_forecast(df, h=12, n_harmonics=5)

Exponential smoothing

Rust-accelerated implementations of SES, Holt, and Holt-Winters.

ses = pts.ses_forecast(df, h=12, alpha=0.3)
holt = pts.holt_forecast(df, h=12, alpha=0.3, beta=0.1)
hw = pts.holt_winters_forecast(df, h=12, season_length=24, seasonal="additive")

ARIMA / SARIMA

Two backends: manual order via statsmodels, or automatic selection via statsforecast.

# Manual order
fitted = pts.arima_fit(df, order=(1, 1, 1))
forecast = pts.arima_forecast(fitted, h=12)

# Automatic
forecast = pts.auto_arima(df, h=12, season_length=12)

ML forecast pipeline

ForecastPipeline wires up feature engineering, target transforms, and any sklearn-compatible model.

from sklearn.ensemble import GradientBoostingRegressor

pipe = pts.ForecastPipeline(
    GradientBoostingRegressor(),
    lags=[1, 2, 7, 14],
    rolling_windows=[7, 14],
    calendar=["day_of_week", "month"],
    target_transform="log",
)
pipe.fit(train_df)
forecasts = pipe.predict(train_df, h=7)

Multi-step strategies

recursive = pts.RecursiveForecaster(model, lags=[1, 7])
recursive.fit(train_df)
preds = recursive.predict(train_df, h=14)

direct = pts.DirectForecaster(model, lags=[1, 7], h=14)
direct.fit(train_df)
preds = direct.predict(train_df)

Global models

Train a single model across all series with optional series-identity encoding.

gf = pts.GlobalForecaster(model, lags=[1, 7], id_encoding="ordinal")
gf.fit(train_df)
preds = gf.predict(train_df, h=7)

Ensembles

# Weighted combination
ens = pts.WeightedEnsemble(weights="inverse_error")
combined = ens.combine([forecast_a, forecast_b], validation_dfs=[val_a, val_b])

# Stacking meta-learner
stacker = pts.StackingForecaster(base_models=[model_a, model_b], meta_model=linear)
stacker.fit(train_df)

Probabilistic forecasting

# Quantile regression
qr = pts.QuantileRegressor(model, quantiles=[0.1, 0.5, 0.9])
qr.fit(train_df)
intervals = qr.predict(train_df, h=7)

# Conformal prediction intervals
result = pts.conformal_interval(cal_residuals, predictions, coverage=0.9)

# EnbPI — online adaptive intervals
enbpi = pts.EnbPI(model, n_bootstraps=100)
enbpi.fit(train_df)
intervals = enbpi.predict(train_df, h=7)

Evaluation metrics

from polars_ts import mae, rmse, mape, smape, mase, crps

print(f"MAE:  {mae(actuals, forecasts):.4f}")
print(f"RMSE: {rmse(actuals, forecasts):.4f}")
print(f"MAPE: {mape(actuals, forecasts):.4f}")

Further reading