Quant Terminal
D1-06D1·intermediate·~21 min

Model selection and forecasting — the humbling benchmark

time-seriesmodel-selectionaicbicforecastingnaive-benchmarkoverfitting

▸ Pretest — guess, even if you don't know

You fit AR(1), AR(2), ... up to AR(10) to the same daily return series. Which model will have the lowest in-sample mean squared error?

The overfitting ratchet

AR(2) contains AR(1) as a special case: set the second coefficient to zero and AR(2) is AR(1). Models related this way are called nested — the smaller one lives inside the bigger one. That containment has a hard consequence. The best-fitting AR(2) can never do worse in-sample — that is, measured on the same data used to fit it — than the best AR(1), because it could always just copy the AR(1) answer. With noisy data it does strictly better. The extra coefficient bends toward whatever noise pattern this particular sample happens to contain. Same for AR(3) over AR(2), and for every ARMA extension from D1-05.

This is the time-series face of the disease you met in A2-05 and D4-01: maximizing in-sample fit selects for luck. Fit a rich enough model and you can reproduce history exactly — and forecast nothing. So we need scorekeeping that either charges for parameters or hides data from the fit.

AIC and BIC — paying for parameters

Information criteria charge for parameters directly. Two symbols first: LL is the model's likelihood — how probable the observed data is under the fitted model, so higher means better fit — and ln\ln is the natural logarithm (np.log), which just compresses LL onto a manageable scale. For a model with kk parameters fit on nn points:

AIC=2k2lnLBIC=klnn2lnL\text{AIC} = 2k - 2\ln L \qquad\qquad \text{BIC} = k\ln n - 2\ln L

In words: AIC equals 2 times the parameter count minus 2 times the log-likelihood; BIC swaps the flat 2 for lnn\ln n, the log of the sample size. In both, the 2lnL-2\ln L term rewards fit (it falls as fit improves), the first term is the fine per parameter, and lower is better. The difference is the fine schedule: AIC charges a flat 2 per parameter; BIC charges lnn\ln n, which is already ~5.5 at 250 daily observations and grows with the sample. So BIC penalizes harder and picks smaller models. For daily financial data, where true signals are faint and extra parameters mostly harvest noise, the stingier BIC is usually the safer default. Statsmodels prints both for any ARMA fit; you just have to resist the urge to ignore them.

Information criteria are cheap and use all the data — but they still score in-sample likelihood, just with a handicap. The sterner test hides data.

Splitting time: train/test without shuffling

The machine-learning reflex is to shuffle the data and split randomly. For time series this is forbidden. Shuffling puts 2023 observations in the training set for "predicting" 2019 — look-ahead bias (D4-01) manufactured by your own evaluation harness. Autocorrelation makes it worse: a test point randomly sandwiched between two training points is partly memorized, not forecast.

The rule: temporal order is sacred. Train on the first chunk, test on the later chunk, and let information flow only forward:

split = int(len(x) * 0.7)
train, test = x[:split], x[split:]   # fit on train ONLY, forecast test

One split gives one verdict; rolling the split forward gives walk-forward analysis, the full treatment in Track D4.

The naive benchmark

Score forecasts on the test set with mean squared error or mean absolute error:

MSE=1nt(xtx^t)2MAE=1ntxtx^t\text{MSE} = \frac{1}{n}\sum_t (x_t - \hat{x}_t)^2 \qquad \text{MAE} = \frac{1}{n}\sum_t |x_t - \hat{x}_t|

In words: x^t\hat{x}_t ("x-hat sub t" — the hat marks a forecast) is your prediction for time t, so xtx^tx_t - \hat{x}_t is the forecast error. MSE averages the squared errors; MAE averages their absolute values. Tiny example: errors of +2, −1, +1 give MSE = (4 + 1 + 1) / 3 = 2 and MAE = (2 + 1 + 1) / 3 ≈ 1.33. MSE punishes big misses quadratically; MAE is more forgiving of outliers. But a raw error number means nothing alone — you need a baseline, and time series has a brutally effective one: the naive forecast, tomorrow equals today (x^t+1=xt\hat{x}_{t+1} = x_t). For a random walk (D1-02), the naive forecast is optimal. So "beat naive out-of-sample" is the minimum bar for claiming your model found structure — and for prices, most models fail it. For returns, the analogous humbling benchmark is the constant forecast (tomorrow's return equals the historical mean, or just zero): decades of academic horse races show sophisticated return forecasts struggling to beat even that.

The honest scoreboard

Where do linear time-series models actually land, out-of-sample, on financial data?

That asymmetry is the doorway to the rest of this track: the next two lessons are about the forecasts that actually work.

Try it

Race the two classic baselines. The naive forecast predicts each point with the previous point; the mean forecast predicts every point with the training mean (here: the mean of all points before the last step, a miniature train/test split):

▮ EXERCISE · d1-06-ex1

Implement naive_mse(x): the MSE of predicting x[t] with x[t-1], i.e. mean of (x[1:] - x[:-1]) squared. And mean_mse(x): the MSE of predicting every x[t] for t >= 1 with the mean of x[:-1]. Both return floats.

⧉ Review card
Why can in-sample fit never choose between nested models?
A bigger nested model can never fit worse in-sample — extra parameters always absorb at least some noise. In-sample error is a ratchet that only rewards complexity, so it selects for luck, not structure.
⧉ Review card
AIC vs BIC — formulas in words, and which penalizes harder?
Both are fit-reward minus parameter-fine, lower is better. AIC fines 2 per parameter; BIC fines ln(n) per parameter, which exceeds 2 once n is above about 8. BIC penalizes harder and picks smaller models — usually the safer default for noisy financial data.
⧉ Review card
Why must you never shuffle a time-series train/test split?
Shuffling puts future observations in the training set — look-ahead bias built into your own evaluation. Temporal order is sacred: train on the earlier chunk, test on the later one, information flows forward only.
⧉ Review card
What is the naive forecast and why is it the benchmark?
Tomorrow equals today. For a random walk it is the optimal forecast, so beating it out-of-sample is the minimum evidence of real structure. Most return forecasts fail this bar; volatility forecasts routinely clear it.
⧉ Review card
Where do linear time-series models honestly succeed and fail in markets?
Fail: forecasting returns — autocorrelations near 0.01-0.05 leave almost nothing to predict, and costs eat the rest. Succeed: forecasting volatility — squared returns are strongly autocorrelated, so risk is genuinely forecastable.

Predict before the next lesson

Next up is D1-07: volatility, ARCH and GARCH — the models built for the one thing that is forecastable. Before reading, predict:

◈ Calibration check

Could you explain to a colleague why AR(10) always beats AR(1) in-sample, how BIC arbitrates, and why the naive forecast is the bar to clear?

1 = guessing · 5 = could teach it

⏻ End of lesson

Mark it read to book its 5 review cards into your deck.

Sources & further reading