19 · Capstone: an end-to-end forecast
Put the whole track together: diagnose the series, fit a model, backtest it against the seasonal-naive baseline, and produce a final forward forecast — the real-world workflow start to finish.
A real forecasting project is a pipeline, not a single model call: diagnose (ADF for stationarity) → fit (Holt-Winters / ARIMA) → evaluate vs the seasonal-naive baseline via backtest → produce a forward forecast. Every step earns its place.
Without this:
Skip the diagnose-and-baseline steps and you'll fit a model blind, never knowing if it actually beats a trivial forecast or generalizes beyond one slice.
This is the capstone: every piece of the track in one workflow, the same four moves you'd run on a real CSV.
- Diagnose. Plot mentally and run the Augmented Dickey-Fuller (ADF) test for stationarity. A small p-value (< 0.05) means stationary; a large one means there's a trend/unit root to handle (difference it, or let a trend-aware model absorb it). Note the seasonal period.
- Fit. For a series with clear trend and seasonality, Holt-Winters (exponential smoothing with trend + seasonal components) is a strong, fast, interpretable choice. ARIMA/SARIMA is the alternative when autocorrelation structure is the story.
- Evaluate vs baseline. A rolling-origin backtest of the model and the seasonal-naive baseline. The model only earns deployment if its backtest error is meaningfully lower.
- Forecast. Refit on all the data and project the horizon you actually need.
The cell below does all four end-to-end on a synthetic seasonal series: ADF p-value → Holt-Winters fit → backtest MAE of model vs seasonal-naive → a final 14-day forward forecast. Read the printed comparison — that single "model beats baseline by X%" line is the deliverable a stakeholder cares about.
Python (in browser)
End-to-end: ADF diagnose → Holt-Winters fit → rolling-origin backtest vs seasonal-naive → a 14-month forward forecast. The 'beats baseline by X%' line is the deliverable.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Where to go next. You now own the classical forecasting toolkit — decomposition, stationarity, ARIMA/SARIMA, exponential smoothing, lag features, ML/DL forecasters, and honest evaluation. The ecosystem builds straight on these foundations:
- Prophet (Meta) — an additive trend + seasonality + holidays model that's robust to missing data and outliers, great when you want fast, interpretable forecasts with minimal tuning.
- NeuralProphet — Prophet's ideas re-implemented on PyTorch, adding autoregression and neural components for more flexibility.
- sktime — the scikit-learn of time series: a unified API for forecasting, classification, and the windowed splitters you backtested with by hand.
- Darts — a single tidy API spanning everything from naive baselines and ARIMA to N-BEATS, TFT, and other deep models, with built-in backtesting.
Every one of these still expects you to diagnose, baseline, and backtest. The tools change; the workflow you just ran does not.
Read-along: the exact diagnose → backtest-vs-baseline → forecast workflow you ran by hand, expressed in sktime's unified API. The concepts carry over one-to-one.
In the capstone workflow, why do you backtest the seasonal-naive baseline alongside Holt-Winters instead of just reporting the model's error?
- A forecasting project is a pipeline: diagnose (ADF) → fit (Holt-Winters/ARIMA) → backtest vs baseline → forward forecast.
- Always backtest the model AND the seasonal-naive baseline with the same folds; deploy only if the model meaningfully beats it.
- The classical workflow transfers directly to Prophet, NeuralProphet, sktime, and Darts — the tools change, the loop doesn't.
This exact diagnose → fit → backtest-vs-baseline → forecast loop is what production demand-planning and capacity-forecasting systems run on a schedule.
If you remove it: Drop any step — skip the ADF diagnosis, skip the baseline, skip the backtest — and you ship a forecast you can neither trust nor defend.