Forecasting Quickstart#
Train a GBLinear model on real energy data and generate probabilistic forecasts with confidence intervals — all in under a minute.
What you’ll learn:
Load the Liander 2024 benchmark dataset
Configure a forecasting workflow with
ForecastingWorkflowConfigTrain a model and inspect evaluation metrics
Generate quantile forecasts (P10 / P50 / P90)
Visualize predictions against actuals
Note
This tutorial uses a small data slice for fast execution.
See examples/benchmarks/ for production-scale runs.
Key API references:
ForecastingWorkflowConfig
create_forecasting_workflow
· LeadTime
· Q
Load the dataset#
The Liander 2024 benchmark dataset contains load measurements, versioned weather forecasts, EPEX prices, and load profiles for a medium-voltage feeder in the Netherlands.
We split the data into:
45 days of training data
7 days for forecasting
The predict window includes 14 days of history before the forecast start so
that lag features (e.g. load_lag_P7D) can be computed during prediction.
from datetime import datetime, timedelta
from openstef_core.testing import load_liander_dataset
dataset = load_liander_dataset()
train_start = datetime.fromisoformat("2024-03-01T00:00:00Z")
train_end = train_start + timedelta(days=45)
forecast_end = train_end + timedelta(days=7)
train_dataset = dataset.filter_by_range(start=train_start, end=train_end)
# Include 14 days of history before forecast start for lag feature computation
predict_dataset = dataset.filter_by_range(
start=train_end - timedelta(days=14),
end=forecast_end,
)
print(
f"Training: {train_dataset.data.shape[0]:,} rows, "
f"{train_dataset.data.index.min():%Y-%m-%d} to {train_dataset.data.index.max():%Y-%m-%d}"
)
print(
f"Predict: {predict_dataset.data.shape[0]:,} rows, "
f"{predict_dataset.data.index.min():%Y-%m-%d} to {predict_dataset.data.index.max():%Y-%m-%d}"
)
Training: 4,320 rows, 2024-03-01 to 2024-04-14
Predict: 2,016 rows, 2024-04-01 to 2024-04-21
Configure the workflow#
ForecastingWorkflowConfig bundles all settings — model type, horizons, quantiles,
and feature columns — into a single object. create_forecasting_workflow turns
it into a ready-to-use pipeline with preprocessing, training, and postprocessing.
We pick GBLinear (gradient-boosted linear model) for its speed and ability to extrapolate beyond training data.
from openstef_core.types import LeadTime, Q
from openstef_models.presets import ForecastingWorkflowConfig, create_forecasting_workflow
from openstef_models.presets.forecasting_workflow import GBLinearForecaster
workflow = create_forecasting_workflow(
config=ForecastingWorkflowConfig(
model_id="quickstart_gblinear",
model="gblinear",
horizons=[LeadTime.from_string("PT36H")],
quantiles=[Q(0.5), Q(0.1), Q(0.9)],
target_column="load",
# Weather features available in the Liander dataset
temperature_column="temperature_2m",
relative_humidity_column="relative_humidity_2m",
wind_speed_column="wind_speed_10m",
radiation_column="shortwave_radiation",
pressure_column="surface_pressure",
verbosity=0,
mlflow_storage=None,
gblinear_hyperparams=GBLinearForecaster.HyperParams(n_steps=50),
)
)
Train the model#
workflow.fit() runs the full pipeline: feature engineering, data validation,
model training, and evaluation on a held-out test split.
result = workflow.fit(train_dataset)
if result is not None:
print("Training metrics:")
print(result.metrics_full.to_dataframe())
if result.metrics_test is not None:
print("\nTest-set metrics:")
print(result.metrics_test.to_dataframe())
Training metrics:
quantile R2 observed_probability
0 0.5 0.707408 0.427586
1 0.1 0.651366 0.103448
2 0.9 0.265259 0.910345
Generate forecasts#
The trained workflow produces a ForecastDataset with point predictions and
quantile bands. The P10-P90 interval covers 80 % of expected outcomes.
To improve the reliability of these quantile estimates, see
Quantile Calibration.
from openstef_core.datasets import ForecastDataset
forecast: ForecastDataset = workflow.predict(predict_dataset, forecast_start=train_end)
print(f"Forecast rows: {len(forecast.data)}")
print(f"Quantiles: {forecast.quantiles}")
forecast.data.tail()
Forecast rows: 145
Quantiles: [0.5, 0.1, 0.9]
| quantile_P50 | quantile_P10 | quantile_P90 | load | stdev | |
|---|---|---|---|---|---|
| timestamp | |||||
| 2024-04-16 11:00:00+00:00 | -550104.4375 | -854959.5000 | 42038.531250 | -390000.000000 | 334069.798256 |
| 2024-04-16 11:15:00+00:00 | -529552.2500 | -850952.2500 | 48707.546875 | -226666.666667 | 334069.798256 |
| 2024-04-16 11:30:00+00:00 | -484266.6875 | -832215.5000 | 79022.046875 | -553333.333333 | 334069.798256 |
| 2024-04-16 11:45:00+00:00 | -422226.3750 | -801489.4375 | 121177.070312 | -733333.333333 | 334069.798256 |
| 2024-04-16 12:00:00+00:00 | -364359.7500 | -773782.8750 | 159615.703125 | -320000.000000 | 222646.564072 |
Visualize the results#
ForecastTimeSeriesPlotter overlays measurements and predictions with shaded
confidence bands in a single interactive chart.
Next steps#
Backtesting Quickstart — evaluate how this model performs on historical data with realistic temporal constraints.
Building a Custom Pipeline — build a model from individual transforms when presets don’t cover your use case.