Lesson 5 - Guided Project: Choosing ARIMA Orders for Cyclepath

Welcome to the Guided Project

Every lesson in this module built toward one deliverable: a real, evidence-backed shortlist of orders to hand to the models Module 5 and 6 actually fit. You’ve defined ACF and PACF (Lesson 1), learned their AR and MA signatures on known data (Lesson 2), learned which bars to trust and which to doubt (Lesson 3), and read Cyclepath’s real table (Lesson 4). Now: turn that reading into candidate orders, take a quick preview look at how they’d actually perform, and — just as importantly — be honest about what that preview does and doesn’t settle.

By the end of this project, you will be able to:

  • Translate an ACF/PACF reading into a concrete shortlist of model orders
  • Use a quick preview fit to see which shortlisted candidate is currently leading
  • Read a Ljung-Box test as a check on whether a model’s residuals are actually done
  • Explain why “the best of three candidates” isn’t the same as “a finished model”

Let’s build the shortlist.


Stage 1: Recap the Reading

Lesson 4 found the same two things worth acting on:

  • Lags 1–6, 8–11, 13–15: both ACF and PACF flat, inside the ±0.2139 band — no meaningful non-seasonal structure. The regular order is essentially (p, q) = (0, 0).
  • Lag 12: significant in both ACF (-0.417) and PACF (-0.483), with an independent story (the seasonal period, corroborated by Module 3). Ambiguous between a seasonal AR(1) and seasonal MA(1) interpretation.
  • Lag 7: significant (-0.220 / -0.273) but with no independent story — flagged in Lesson 3 as the kind of isolated spike pure chance produces in roughly 42% of white-noise series tested at 15 lags. Treated as likely spurious, not built into the shortlist.

That reading translates directly into three candidates, all sharing the regular order (0, 0, 0) and the seasonal differencing D=1 already applied in Module 3, differing only in the seasonal AR/MA term at lag 12:

CandidateSpecificationWhat it represents
ASARIMA(0,0,0)(0,1,0)[12]Seasonal differencing alone, no seasonal AR/MA term
BSARIMA(0,0,0)(1,1,0)[12]Seasonal AR(1) — this year’s deviation partly explained by last year’s
CSARIMA(0,0,0)(0,1,1)[12]Seasonal MA(1) — this year’s deviation partly explained by last year’s shock

Stage 2: A Preview Fit

Module 5 and 6 cover fitting and comparing ARIMA-family models in full — this is a quick preview using the same tool, just to see where the shortlist currently stands:

import warnings
warnings.filterwarnings("ignore")
import numpy as np, pandas as pd
from statsmodels.tsa.statespace.sarimax import SARIMAX

def cyclepath():
    idx = pd.date_range("2016-01-01", periods=96, freq="MS")
    t = np.arange(96); rng = np.random.default_rng(42)
    trend = 9000 + 90*t; seasonal = 3200*np.sin(2*np.pi*(t-3)/12); noise = rng.normal(0,350,96)
    return pd.Series(np.round(trend+seasonal+noise).astype(int), index=idx, name="trips")

y = cyclepath()

candidates = {
    "A (0,1,0)": (0,1,0,12),
    "B (1,1,0)": (1,1,0,12),
    "C (0,1,1)": (0,1,1,12),
}

for name, sorder in candidates.items():
    res = SARIMAX(y, order=(0,0,0), seasonal_order=sorder,
                   enforce_stationarity=False, enforce_invertibility=False).fit(disp=False)
    print(f"{name}  AIC={res.aic:.2f}  BIC={res.bic:.2f}")
A (0,1,0)  AIC=1404.62  BIC=1407.04
B (1,1,0)  AIC=1123.93  BIC=1128.48
C (0,1,1)  AIC=1174.71  BIC=1179.24

Candidate B, seasonal AR(1), wins clearly on both AIC and BIC — over 280 points lower than the no-term baseline, and about 50 points lower than the seasonal-MA(1) alternative. (Lower AIC/BIC means a better balance of fit and simplicity; Module 5 explains the criterion in full.) This is a real, useful result: it confirms lag 12 wasn’t just statistically significant but actually improves the model substantially once fit, and it resolves part of Lesson 4’s AR-vs-MA ambiguity — at least on this preliminary comparison, the AR interpretation fits Cyclepath better than the MA one.


Stage 3: The Honest Part — Is the Leader Actually Done?

A lower AIC than its competitors doesn’t mean a model is finished. Check whether Candidate B’s residuals still have leftover autocorrelation — if they do, there’s still real structure the model hasn’t captured:

from statsmodels.stats.diagnostic import acorr_ljungbox

res_b = SARIMAX(y, order=(0,0,0), seasonal_order=(1,1,0,12),
                 enforce_stationarity=False, enforce_invertibility=False).fit(disp=False)
resid = res_b.resid.iloc[res_b.loglikelihood_burn:]
lb = acorr_ljungbox(resid, lags=[12], return_df=True)
print(round(resid.std(), 1))              # 559.4
print(round(lb["lb_pvalue"].iloc[0], 6))  # 1.2e-05 (0.000012)

That p-value, 0.000012, is a Ljung-Box test on the residuals — its null hypothesis is that the residuals are white noise (no leftover autocorrelation up to lag 12), the same kind of hypothesis-and-p-value logic as the ADF test back in Module 3, just applied to what a fitted model left behind instead of the raw series. A p-value this small rejects that null: Candidate B’s residuals, even though it’s the best of the three candidates by a wide AIC margin, still have significant leftover structure. It is not a finished model.

A three-stage pipeline diagram. Stage 1, 'ACF/PACF reading', shows the two significant lags 7 and 12 with lag 7 crossed out as likely spurious. An arrow leads to stage 2, 'shortlist of 3 candidates', showing three small model boxes labeled no seasonal term, seasonal AR(1), seasonal MA(1). An arrow leads to stage 3, 'preview fit', with the seasonal AR(1) box highlighted as the AIC winner at 1123.93 versus 1174.71 and 1404.62 for the others. A final arrow leads to a box labeled 'Ljung-Box check', flagged with a warning icon and the text 'residuals still significant, p=0.000012 -- not finished, hand off to Module 5 and 6'.
From ACF/PACF reading to a validated leader — but the Ljung-Box check on the winning candidate's residuals shows real structure still unaccounted for, which is exactly the honest, unfinished state this module hands off to Module 5 and 6.

Why this is a good place to stop, not a failure

It would be tempting to keep tweaking orders until the Ljung-Box test passes, but that’s exactly the kind of undisciplined, plot-chasing process this module warned against — remember Lesson 3’s simulation, where 42% of pure noise threw a spurious spike somewhere. A responsible process narrows candidates with evidence (this lesson), checks them with a real criterion (AIC/BIC), and diagnoses honestly (Ljung-Box) — then hands off to the next stage of work with a validated, well-reasoned starting point instead of a model quietly overfit to pass one specific test. That handoff, done properly, is the actual deliverable of ACF/PACF work, not a fully diagnosed final model.


Stage 4: The Takeaway

Step back and look at what this project produced. You now hold a genuine, evidence-backed starting point for the modeling modules ahead:

  1. A regular order of (0, 0) — the non-seasonal part of Cyclepath’s stationary series shows no meaningful AR or MA structure, confirmed by a flat ACF/PACF table across lags 1–6 and 8–11.
  2. A resolved seasonal ambiguity, provisionally — of the two lag-12 interpretations Lesson 4 couldn’t distinguish, a preview fit strongly favors seasonal AR(1) (AIC 1123.93) over seasonal MA(1) (AIC 1174.71) and over no term at all (AIC 1404.62).
  3. An honest open question — even the AIC-favored candidate fails the Ljung-Box whiteness check (p = 0.000012), and lag 7 from Lesson 4 remains an unresolved, probably-spurious loose end. Both are real work for Module 5 and 6, not swept under the rug.

That’s the whole point of this module: ACF and PACF don’t hand you a finished model, they hand you a disciplined, defensible starting point — which is exactly what you have now. Next up, Module 5 builds the AR, MA, ARMA, and ARIMA model family from the ground up, fits them properly (rather than this lesson’s quick preview), and gives you the tools to finish what this shortlist started.


Practice Exercises

Exercise 1: Why test lags=[12] in Ljung-Box rather than a smaller number?

The Ljung-Box test above was run with lags=[12]. Why 12 specifically, rather than testing only up to lag 3 or 4?

Hint

The Ljung-Box test at lags=[12] checks for joint leftover autocorrelation across all lags from 1 through 12 at once, not just lag 12 in isolation. Since this module’s whole shortlist was built around lag 12 being the seasonal period of interest, testing residuals up to and including that lag is what actually checks whether the model has cleaned up the structure this module cared about — including any residual echo of the still-unresolved lag-7 spike from Lesson 4, which falls within that range.

Exercise 2: A quicker sanity check

Before ever fitting a SARIMAX model, is there a cheaper way to have predicted that a seasonal term was going to matter a lot here?

Hint

Yes — the sheer size of the lag-12 ACF/PACF values (-0.417 and -0.483) relative to the significance band (0.2139) was already a strong hint. A lag that’s roughly double the significance threshold, as this one is, tends to represent a substantial, not marginal, piece of structure — which is exactly what the large AIC gap between Candidate A (no seasonal term) and Candidates B/C confirmed once actually fit. The magnitude of a significant bar, not just whether it crosses the line, is worth reading as a rough preview of how much a term is likely to matter.

Exercise 3: What would you try next, given the Ljung-Box result?

Given that Candidate B still fails the whiteness check, what’s a reasonable next experiment, without yet knowing the full ARIMA/SARIMA toolkit Module 5 and 6 will introduce?

Hint

A reasonable next step, even with just the tools from this module, is revisiting the lag-7 question — checking whether Candidate B’s residuals still show a spike at lag 7 (if the original series’ lag-7 signal is real after all, it would still show up in the residuals of a model that never accounted for it). Beyond that, trying a higher-order seasonal AR term ((2,1,0)[12]) or combining both seasonal AR and MA ((1,1,1)[12]) are natural next candidates — exactly the kind of systematic, ACF/PACF-informed exploration Module 5 and 6 formalize instead of guessing.


Summary

You translated Module 4’s entire ACF/PACF reading into a concrete deliverable. The non-seasonal order is (0, 0) — no meaningful short-lag structure survived seasonal differencing. The seasonal term at lag 12 is real and substantial, and a preview fit resolves Lesson 4’s AR-vs-MA ambiguity in favor of seasonal AR(1) (AIC 1123.93, clearly ahead of seasonal MA(1) at 1174.71 and no term at all at 1404.62). But a Ljung-Box test on that leading candidate’s residuals (p = 0.000012) honestly shows it isn’t finished — real leftover structure remains, likely connected to the still-unresolved lag-7 question from Lesson 4. That’s not a failure of the process; it’s exactly the calibrated, evidence-backed starting point this module was built to produce.

Key Concepts

  • Shortlist, not a single answer — ACF/PACF reading narrows candidates; it doesn’t always pick a single unambiguous winner (lag 12’s AR/MA tie).
  • AIC/BIC as a tiebreaker — a quick preview fit resolved the shortlist’s ambiguity with real evidence, previewing what Module 5 covers in depth.
  • Ljung-Box as an honesty check — tests whether a fitted model’s residuals are actually white noise; a low p-value means real work remains.
  • A validated starting point, not a finished model — the responsible endpoint of ACF/PACF work is a defensible shortlist and a leader, not a fully diagnosed model.

Why This Matters

The discipline this project modeled — read the evidence, shortlist candidates, preview-test them, and report honestly on what’s still unresolved — is the actual professional practice of time series modeling, and it’s a sharp contrast to the tempting shortcut of picking whichever order “looks right” on a plot and moving on. Handing Module 5 a validated regular order, a leading seasonal candidate, and a named open question (the Ljung-Box failure, the lag-7 mystery) is a far more useful handoff than a false sense of completion would have been. Next, Module 5 builds AR, MA, ARMA, and ARIMA from the ground up and gives you the tools to properly finish what this shortlist started.


Next Steps

Continue to Module 5 - AR, MA, ARMA, ARIMA

Build and fit the ARIMA model family, and put this shortlist to work on real forecasts.

Back to Module Overview

Return to the Autocorrelation: ACF and PACF module overview


Continue Building Your Skills

You now have a real, defensible shortlist for Cyclepath: regular order (0, 0), a leading seasonal AR(1) candidate, and an honestly unresolved diagnostic question. Next, Module 5 builds the AR, MA, ARMA, and ARIMA model family from first principles and gives you the tools to fit, compare, and diagnose models properly — finishing what this module’s shortlist started.