Part II: Classical Forecasting and Time Series Analysis
Chapter 5: Univariate Forecasting Models

Univariate Forecasting Models

The classical forecasting workhorses, ARIMA to ETS to Prophet, and how to choose and validate them honestly.

"Every morning they ask me where the series is headed, and every morning I answer with the same quiet confidence and a band of uncertainty that grows a little wider with each step I take. Forecast me one day ahead and I am nearly sure of myself. Forecast me a season ahead and I become a soft gray cone of maybe. I am not evasive. I am simply honest about how far my memory can reach, which is exactly as far as the data lets it and not one step more."

A Forecast Interval Widening With Every Step

Chapter Overview

The two previous chapters taught you to look at a time series. Chapter 3 gave you stationarity, the autocorrelation and partial-autocorrelation functions, and the differencing and decomposition that tame a wandering series; Chapter 4 rotated the picture into frequency and let you read off a series' dominant cycles. This chapter finally turns all of that diagnosis into prediction. It builds the classical forecasting models that actually project a series into its future: the moving-average and autoregressive primitives, their combination into ARMA and ARIMA, the seasonal extension SARIMA, the exponential-smoothing and ETS family, and the modern statistical frameworks led by Prophet and the Nixtla ecosystem. Each diagnostic you learned earlier now has a job. The ACF cutoff selects a moving-average order, the PACF cutoff selects an autoregressive order, the differencing that made a series stationary becomes the integration in ARIMA, and the seasonal peaks you found in the spectrum become the seasonal terms of a SARIMA model.

The chapter develops these models in a deliberate order, from parts to wholes. It starts with the two atoms of linear time-series modeling, the moving-average model that carries forward a finite memory of past shocks and the autoregressive model that regresses the present on its own past, and it shows that these are duals: a stationary autoregressive process is an infinite moving average, and an invertible moving-average process is an infinite autoregression. It then fuses them into ARMA, wraps differencing around the result to reach ARIMA for non-stationary series, and threads the Box-Jenkins identification-estimation-diagnostic loop through all of it. SARIMA adds seasonal lag polynomials for data with a fixed period, and SARIMAX lets exogenous drivers enter the model. Exponential smoothing and the ETS state-space taxonomy arrive next as a parallel tradition that often matches or beats ARIMA with less ceremony, and Prophet and statsforecast round out the chapter with the decomposable, automation-friendly tools that dominate industrial practice.

Running underneath every model is one lesson the chapter never lets you forget: a simple, well-validated classical model is a strong baseline, and a strong baseline is the bar a fancier model has to clear. The deep architectures of Part III are powerful, but the M-competitions and a decade of practice keep returning the same uncomfortable verdict, that a carefully fitted ARIMA or ETS, validated by an honest rolling backtest against a seasonal-naive benchmark, beats a great many elaborate models on a great many real series. The final section makes this discipline explicit, weighing fit against complexity with the AIC, AICc, and BIC information criteria, checking residual whiteness with the Ljung-Box test, and ranking candidates by backtested MASE rather than by in-sample fit. The chapter teaches you to forecast and, just as firmly, to distrust a forecast you have not validated.

The temporal thread runs straight through this chapter and out the far side of the book. The autoregressive model is a linear recurrence: the next value is a fixed linear function of a finite window of past values. That single idea generalizes, almost without modification, into the recurrent networks of Chapter 10, where the linear update becomes a learned nonlinear one, and into the structured state-space models of Chapter 13, where ARIMA itself reappears as a form of linear attention. When you write down the AR recurrence in this chapter you are writing, in its simplest and most interpretable form, the equation that the rest of the book spends thirty chapters learning to make deeper. Following the running-dataset convention for Part II, the worked examples here lean on a finance-flavored series, the prices and returns whose trends, volatility, and seasonality exercise every model in turn.

Prerequisites

This chapter assumes the two chapters before it. From Chapter 3: Statistical Foundations you need stationarity, the autocorrelation and partial-autocorrelation functions, white noise, and the differencing and decomposition that make a series stationary, because every model here is identified by reading those diagnostics and ARIMA's integration is exactly that differencing. From Chapter 4: Frequency-Domain and Spectral Analysis you need the idea that a series carries cycles at definite frequencies, since the seasonal peaks of the spectrum are the seasonal terms a SARIMA model fits and the Fourier seasonality Prophet uses. Just as important is the evaluation discipline of Chapter 2: Temporal Data Engineering: forecasting is where leakage is most tempting and most punishing, so the strict separation of past from future, the rolling-origin split, and the refusal to peek across the forecast boundary are assumed throughout and made concrete in this chapter's lab. The mathematics stays light, comfort with the lag operator, geometric series, and ordinary least squares is enough, and readers wanting a refresher on any of these will find the relevant appendices and earlier chapters indexed in the Table of Contents.

Remember the Chapter as One Sentence

If you keep one idea from this chapter, keep this: a low-order ARIMA or ETS, validated by a rolling-origin backtest against a seasonal-naive baseline, is the bar every fancier model must clear. The models in this chapter are cheap to fit, fast to run, and interpretable to the last coefficient, and on a large fraction of real series they are also the most accurate thing you will try. Before reaching for a deep network, fit the simple classical model, backtest it honestly with MASE, and confirm its residuals are white. If a heavier model cannot beat that number on held-out data, the heavier model is not better, it is just more expensive. Every chapter after this one is, in part, an attempt to clear this bar.

Chapter Roadmap

Once you have worked through the seven sections, the Hands-On Lab below chains them into a single forecasting bake-off. Each lab step maps to a section, so the lab doubles as a review: by the time the harness names a winner you will have fit the ARIMA family of Section 5.3 and Section 5.4, the ETS model of Section 5.5, and the Prophet model of Section 5.6, then ranked them all by the backtested MASE and residual diagnostics of Section 5.7 against the seasonal-naive baseline every serious forecast must beat.

Hands-On Lab: Build a Forecasting Bake-Off

Duration: about 90 to 120 minutes Difficulty: Intermediate

Objective

Run a fair, honest forecasting competition on a single seasonal series from the running dataset and let the data pick the winner. You will fit four contenders, an automatically ordered ARIMA, an automatically selected ETS, a Prophet model, and a humble seasonal-naive baseline, then judge them not by how well they fit the training data but by how well they predict data they never saw. The judging is a rolling-origin backtest scored with the mean absolute scaled error (MASE), the one accuracy metric that is comparable across series and that bakes the seasonal-naive baseline directly into its denominator, so a MASE below one literally means "better than seasonal-naive." For the winning model you will confirm its residuals are white with a Ljung-Box test, because a model whose residuals still carry structure has left forecastable signal on the table, and you will report the winner with calibrated prediction intervals rather than a single brittle point forecast. This is the exact workup a forecasting team runs before it commits a model to production: not "which model fits best" but "which model, validated the way the future will validate it, earns the right to ship."

What You'll Practice

  • Fitting an automatically ordered ARIMA and reading its differencing and seasonal terms, following Section 5.3 and Section 5.4.
  • Fitting an automatically selected ETS model and recognizing where exponential smoothing matches or beats ARIMA, following Section 5.5.
  • Fitting a Prophet model with seasonality and comparing it honestly against the simpler classical tradition, following Section 5.6.
  • Scoring every model with a rolling-origin backtest and MASE, and ranking by held-out error rather than in-sample fit, the core discipline of Section 5.7.
  • Confirming residual whiteness with the Ljung-Box test and reporting the winner with prediction intervals, the diagnostic close of Section 5.7.

Setup

You need statsmodels for ETS and the classical ARIMA backbone, pmdarima for automatic ARIMA order selection, and prophet for the decomposable model; statsforecast is an optional faster route to the same auto-ARIMA and auto-ETS. A small monthly or daily seasonal series ships with the lab so it runs out of the box, but the bibliography links the M4 and M5 competition data and the Monash archive when you want a genuine many-series benchmark. The seasonal period is fixed and known (twelve for monthly data), so the seasonal-naive baseline simply repeats the value from one full season ago.

pip install statsmodels pmdarima prophet statsforecast
The minimal environment for the bake-off; pmdarima supplies auto_arima, statsmodels supplies ETSModel, prophet supplies Prophet, and statsforecast offers a faster vectorized alternative for many series at once.

Steps

Step 1: Fit an automatically ordered ARIMA

Fit an ARIMA whose orders are chosen automatically by stepwise search, following the Box-Jenkins loop of Section 5.3 and the seasonal extension of Section 5.4. The auto_arima search runs a unit-root test to pick the differencing order, then searches over the autoregressive and moving-average orders (seasonal and non-seasonal) to minimize AICc, so you get a defensible model without hand-tuning every term. Inspect the chosen order: a non-zero seasonal term confirms the series carries the period you expect.

import pmdarima as pm

def fit_auto_arima(y_train, m=12):
    model = pm.auto_arima(y_train, seasonal=True, m=m,    # m = seasonal period
                          stepwise=True, suppress_warnings=True,
                          error_action="ignore")
    return model                                          # .predict gives point + interval forecasts
Step 1: auto_arima returns a fitted SARIMA whose differencing, seasonal, and non-seasonal orders were selected by AICc, the automation of the Box-Jenkins identification loop.

Step 2: Fit an automatically selected ETS

Fit an exponential-smoothing model whose error, trend, and seasonal components are chosen by information criterion, following the ETS taxonomy of Section 5.5. ETS and ARIMA are different traditions that often land in the same neighborhood, so fitting both and comparing them on held-out error is exactly the kind of cheap, informative bake-off this lab is built around. Let the model decide between additive and multiplicative seasonality rather than fixing it by hand.

from statsmodels.tsa.exponential_smoothing.ets import ETSModel

def fit_ets(y_train, m=12):
    model = ETSModel(y_train, error="add", trend="add",  # damped trend + seasonality
                     seasonal="add", damped_trend=True,
                     seasonal_periods=m)
    return model.fit(disp=False)                          # .get_prediction gives intervals
Step 2: an additive damped-trend Holt-Winters fit; swap error, trend, and seasonal between add and mul and keep the variant with the lowest AICc, the selection rule of Section 5.5.

Step 3: Fit a Prophet model

Fit Prophet's decomposable trend-plus-seasonality model, following Section 5.6. Prophet trades the autocorrelation machinery of ARIMA for an explicit additive decomposition with automatic changepoints and Fourier seasonality, which makes it forgiving on messy business series with holidays and missing days. Feed it the same training window as the other contenders so the comparison stays fair, and let it produce its own uncertainty intervals.

from prophet import Prophet

def fit_prophet(df_train):                               # df has columns ds (date), y (value)
    model = Prophet(yearly_seasonality=True,             # Fourier seasonality, auto changepoints
                    weekly_seasonality=False,
                    interval_width=0.9)                  # 90% prediction intervals
    model.fit(df_train)
    return model
Step 3: Prophet fits trend, seasonality, and changepoints additively and returns 90 percent intervals directly, the automation-first framework of Section 5.6.

Step 4: Score everything with a rolling-origin backtest and MASE

Now judge the contenders the way the future will judge them, following Section 5.7. A rolling-origin backtest repeatedly trains on data up to a cutoff, forecasts the next horizon, records the error, then rolls the cutoff forward, so each model is scored on many genuine out-of-sample windows rather than one lucky split. Score with MASE, which divides the model's mean absolute error by the in-sample mean absolute error of the seasonal-naive baseline, giving a number that is comparable across series and where below one means "beats seasonal-naive." Never let any model see data past its cutoff: this is where the leakage discipline of Chapter 2 earns its keep.

import numpy as np

def mase(y_true, y_pred, y_train, m=12):
    naive_err = np.mean(np.abs(y_train[m:] - y_train[:-m]))  # seasonal-naive in-sample error
    return np.mean(np.abs(y_true - y_pred)) / naive_err      # < 1 means better than naive
Step 4: MASE scales each model's error by the seasonal-naive benchmark, so the baseline is built into the metric and a score below one is the bar every model must clear.

Step 5: Confirm whiteness and report the winner with intervals

Pick the model with the lowest backtested MASE, then earn the right to ship it by confirming its residuals are white, following the diagnostic close of Section 5.7. The Ljung-Box test asks whether the residual autocorrelations up to a chosen lag are jointly indistinguishable from zero; a large p-value means the residuals look like white noise and the model has extracted the forecastable structure, while a small p-value means signal is still leaking into the errors and the model is not finished. Report the winner as a point forecast wrapped in a prediction interval, never as a bare number, because a forecast without a stated uncertainty is a forecast you cannot act on responsibly.

from statsmodels.stats.diagnostic import acorr_ljungbox

def residuals_are_white(resid, lags=12, alpha=0.05):
    lb = acorr_ljungbox(resid, lags=[lags], return_df=True)
    pval = lb["lb_pvalue"].iloc[0]
    return pval > alpha, pval                            # True => residuals look like white noise
Step 5: a Ljung-Box p-value above 0.05 clears the winning model's residuals as white; only then is the model reported with its prediction interval as the bake-off's verdict.

Expected Output

Running the bake-off prints a small table: each of the four contenders with its rolling-origin MASE, the seasonal-naive baseline pinned at a MASE of one by construction, and the winner highlighted. On a typical seasonal business series the auto-ARIMA and the auto-ETS finish close together, both comfortably below one, with Prophet competitive but rarely dominant unless the series has strong holiday effects, and all three beating the seasonal-naive baseline (any model that does not is disqualified). The winning model's Ljung-Box p-value comes back above the threshold, confirming its residuals carry no remaining autocorrelation, and the final line reports the forecast as a point path with a ninety percent interval that widens with the horizon, exactly the cone the chapter's epigraph describes. The lesson lands in the table itself: the elaborate model has to earn its place against a baseline a child could compute, and on this series the disciplined classical models clear that bar with room to spare.

Right Tool: statsforecast Runs the Whole Bake-Off in a Few Lines

The lab fits each model with its own library so you see what each tradition does, but Nixtla's statsforecast collapses the entire comparison into a handful of lines. A single StatsForecast object holds AutoARIMA, AutoETS, and SeasonalNaive together, its cross_validation method runs the rolling-origin backtest for all of them at once, and it is fast enough to do this across thousands of series in parallel, which is exactly how the M-competition leaderboards are produced. The roughly fifty lines here become about ten, with the library handling the windowing, the per-series fitting, and the metric bookkeeping. Build the bake-off by hand once so you understand what MASE measures and why the rolling origin is non-negotiable, then lean on statsforecast whenever you need to score many models across many series under a deadline.

Stretch Goals

  • Add a SARIMAX contender that ingests an exogenous driver (a calendar or price covariate) and check whether the extra information actually lowers the backtested MASE or merely overfits, the SARIMAX caution of Section 5.4.
  • Replace the single MASE with both MASE and sMAPE and confirm the ranking is stable across metrics; where it is not, the disagreement is itself a finding, following Section 5.7.
  • Hold the winning model fixed and re-run the backtest on a second series from the running dataset to see whether the same model wins twice, the first hint of the global-versus-local question that Section 5.6 raises and Part III answers.

What's Next?

This chapter forecast a single series from its own past, the univariate case, and that is where most forecasting begins and a great deal of it honestly ends. But series rarely live alone. Sales move with prices, demand moves with weather, one sensor moves with its neighbors, and the future of one variable is often written in the present of another. Chapter 6: Multivariate and Econometric Models opens that door, generalizing the autoregression of this chapter to the vector autoregression that lets several series predict one another, adding the cointegration and error-correction machinery that handles series which drift together, and bringing in the GARCH family that models the changing volatility a returns series carries. The single-series workhorses you built here remain the baselines those richer models must beat, and the rolling-origin discipline you practiced in the lab carries over without a single change.

Bibliography & Further Reading

Foundational Texts

Box, G. E. P., Jenkins, G. M., Reinsel, G. C., Ljung, G. M. "Time Series Analysis: Forecasting and Control," 5th edition. Wiley, 2015. wiley.com

The book that defined the ARIMA family and the identification-estimation-diagnostic loop carried through Sections 5.1 to 5.4; the original source of the Ljung-Box test the lab uses to check residual whiteness.

📖 Book

Hyndman, R. J., Khandakar, Y. "Automatic Time Series Forecasting: The forecast Package for R." Journal of Statistical Software 27(3), 2008. jstatsoft.org

The paper behind auto.arima and the automated ETS selection that Section 5.3 and Section 5.5 describe and the lab automates; the methodological basis of every "auto" model in the bake-off.

📄 Paper

Key Books

Hyndman, R. J., Athanasopoulos, G. "Forecasting: Principles and Practice," 3rd edition (FPP3). OTexts, 2021. otexts.com/fpp3

The definitive free textbook for this chapter; its ARIMA and exponential-smoothing chapters are the closest companions to Sections 5.3 through 5.5, and its account of MASE underpins the lab's scoring.

📖 Book

Hyndman, R. J., Koehler, A. B., Ord, J. K., Snyder, R. D. "Forecasting with Exponential Smoothing: The State Space Approach." Springer, 2008. link.springer.com

The complete state-space treatment of exponential smoothing and the ETS taxonomy of Section 5.5, including the likelihood-based model selection the lab's auto-ETS step relies on.

📖 Book

Papers

Taylor, S. J., Letham, B. "Forecasting at Scale." The American Statistician 72(1), 2018 (Prophet). peerj.com/preprints/3190

The Prophet paper: a decomposable trend-plus-seasonality-plus-holiday model with automatic changepoints, the framework Section 5.6 develops and the lab fits as its third contender.

📄 Paper

Makridakis, S., Spiliotis, E., Assimakopoulos, V. "The M4 Competition: 100,000 Time Series and 61 Forecasting Methods." International Journal of Forecasting 36(1), 2020. sciencedirect.com

The large-scale competition whose results ground the chapter's recurring lesson: simple, well-validated statistical models and their combinations are formidable baselines, the verdict Section 5.7 builds its workflow around.

📄 Paper

Makridakis, S., Spiliotis, E., Assimakopoulos, V. "The M5 Competition: Background, Organization, and Implementation." International Journal of Forecasting 38(4), 2022. sciencedirect.com

The hierarchical retail-demand competition that sharpened the global-versus-local and reconciliation questions of Section 5.6 and reaffirmed strong, cheap baselines on real business data.

📄 Paper

Tools & Libraries

statsmodels: time-series analysis in Python (ARIMA, SARIMAX, ETS, Ljung-Box). statsmodels.org

The library behind the from-scratch and library worked examples of Sections 5.1 to 5.5 and the lab's ETS fit and Ljung-Box residual check; the reference implementation of the classical models.

🔧 Tool

pmdarima: auto_arima and the Box-Jenkins workflow for Python. alkaline-ml.com/pmdarima

Brings R's auto.arima stepwise order selection to Python; the engine of the lab's Step 1 and the automatic identification described in Sections 5.3 and 5.4.

🔧 Tool

Nixtla statsforecast: fast, vectorized statistical forecasting (AutoARIMA, AutoETS, cross-validation). github.com/Nixtla/statsforecast

The high-performance ecosystem of Section 5.6; its cross_validation method runs the whole rolling-origin bake-off across many series at once, the library shortcut the lab points to.

🔧 Tool

Prophet: decomposable forecasting from Meta. facebook.github.io/prophet

The official Prophet library and documentation for the trend, seasonality, changepoint, and holiday model of Section 5.6 and the lab's third contender.

🔧 Tool

sktime: a unified scikit-learn-style interface for time-series forecasting and classification. sktime.net

A consistent fit-predict API wrapping ARIMA, ETS, Prophet, and rolling-origin evaluation; a convenient harness for the model-selection workflow of Section 5.7.

🔧 Tool

Darts: a Python library for forecasting with a unified model interface. unit8co.github.io/darts

Wraps the classical ARIMA, ETS, and Prophet models alongside deep forecasters under one API with built-in backtesting; a smooth bridge from this chapter's baselines to the deep models of Part III.

🔧 Tool

Datasets & Benchmarks

Godahewa, R., Bergmeir, C., Webb, G. I., Hyndman, R. J., Montero-Manso, P. "Monash Time Series Forecasting Archive." NeurIPS Datasets and Benchmarks, 2021. forecastingdata.org

A large curated collection of evenly clocked series across many domains; the multi-series benchmark on which the bake-off of this chapter is most informative when scaled up.

📊 Dataset