ARIMA Models
Difference the series until its mean sits still, then forecast the next step from recent values plus recent mistakes.
Why Does This Exist?
Two facts about the near future are usually predictive: where the series just was, and where your last forecast just missed. Autoregression uses the first. A moving average over past errors uses the second. Both assume the series wobbles around a fixed level, which real series rarely do because trends drag the level along.
ARIMA exists to bundle the fix with the forecast. Difference the series until its mean sits still, fit the value-and-error regression on that steadied series, then undo the differencing to land back on the original scale. It is the baseline every fancier forecaster must beat, and when it wins, the lesson is that the series was mostly momentum plus noise.
This page covers the non-seasonal model picked by orders , and . Seasonality with its own extra orders lives in sarima. Whether the series is steady enough to model at all is the stationarity question, and the lag diagnostic that sets and is autocorrelation.
Basics first: a lag is just how many steps back you look, so lag 1 means yesterday. Stationarity means the mean and spread stay put over time. Everything below assumes those two ideas and links them where used.
Think of It Like This
The delivery van on a hill
You drive a van across a hilly town and log the odometer each minute: 5, 7, 9, 11 kilometres. Predicting the raw odometer is silly because it always climbs. Predicting the per-minute gain is easy, because the gains sit still at 2.
That is differencing: stop forecasting the climbing total and forecast the steady step. Then two corrections steer you. The van keeps its speed, so most of the last step carries forward, and that is the autoregressive part. Your last guess overshot a pothole, and part of that miss carries into the next minute, which is the moving average part. ARIMA is the habit of forecasting gains with both corrections, then adding the gain back onto the odometer.
Where it stops: hills change. A new gradient means a new typical step, and no fixed blend of old steps tracks it. That drift is why the stationarity check comes before the model, not after.
How It Actually Works
Name the series , the value at time . Name the differenced series , the step from the last value. Name past mistakes , the gap between forecast and truth. The orders are for how many past steps feed the forecast, for how many times you difference, and for how many past mistakes feed it.
Difference first, then regress
With , model the steps instead of the levels . A steady climb becomes a flat line of equal steps, and a flat line has the fixed mean the regression needs. If the steps still drift, difference again, but each round costs one observation and injects noise, so stop at the first order that steadies the mean.
One equation with two memories
An ARIMA(, , ) forecast of the next steadied value blends both memories:
Here is a constant drift, each (phi) weights a past step, and each (theta) weights a past mistake. Set all terms to zero and the model trusts momentum only. Set all terms to zero and it trusts only the correction of old misses. Then integrate: add the predicted step back onto the last level to return to .
Worked example
Take . First differences: , , , so . Steady, so suffices.
Fit ARIMA(1, 1, 1) with , , and last recorded mistake . The next step forecast is . Add it back: . Momentum alone would have said , and the error correction nudges it to 12.32. The diagram above draws this exact lane: 5, 7, 9, 11 across the top, 2, 2, 2 below, 12.32 at the end.
Code
Stdlib only. Difference the levels, blend the last step with the last recorded miss, integrate back:
def diffs(levels: list[float]) -> list[float]: return [levels[i] - levels[i - 1] for i in range(1, len(levels))]
levels = [5.0, 7.0, 9.0, 11.0]steps = diffs(levels)forecast_step = 0.6 * steps[-1] + 0.3 * 0.4print(steps) # -> [2.0, 2.0, 2.0]print(round(forecast_step, 2)) # -> 1.32print(round(levels[-1] + forecast_step, 2)) # -> 12.32Three prints, three claims from the worked example, each reproducible without any statistics library.
Watch Out For
Differencing a series that was already steady
The steps start alternating plus, minus, plus around zero and lag 1 autocorrelation dives toward negative 0.5. The symptom is a model that was fine at and got worse at , with the moving average term working overtime to cancel the damage.
Each difference manufactures a zigzag the model must then unlearn. Difference to achieve a steady mean, confirmed by the stationarity check, and stop there. In practice above 2 is a smell, not a setting.
Ordering seasonality with non-seasonal knobs
A monthly series spikes every December and starts looking tempting. The symptom is a long tail of significant lags at 12, 24, 36 that no small or absorbs without dozens of parameters.
That rhythm needs seasonal orders, not bigger . Reach for sarima, which differences at lag 12 and adds seasonal memory on top of this page machinery. Let ARIMA own the short memory and give the calendar its own terms.
The Quick Version
- ARIMA forecasts the next value from recent steps plus recent mistakes, after differencing the series steady.
- Orders , and count past values used, differencing rounds applied, and past errors used.
- Series 5, 7, 9 and 11 differences once into steady 2s, so is enough.
- With weights 0.6 and 0.3 and a last miss of 0.4, the next step is 1.32 and the next level is 12.32.
- Momentum alone would call 12.2, so the 0.12 nudge is the error memory doing its only job.
- Differencing past steadiness injects fake zigzag, and calendar rhythm needs seasonal orders instead.