A Shopkeeper's Question
Rekha runs a provision store in Kothrud, Pune. In July 2025 she started noting one number at the end of every month: the total amount her customers paid through UPI — Google Pay, PhonePe, and Paytm, added together. Fourteen months later, standing at the end of August 2026, that spreadsheet has become genuinely useful. She needs to decide how many extra sacks of atta and rice to pre-order for September, and how much loose change to keep in her cash box for the customers who still pay in notes and coins. Both decisions come down to the same question: how much money is likely to flow through her UPI account next month?
Rekha's spreadsheet is what statisticians call a time series: a sequence of numbers tied to specific points in time, in an order that matters. Guessing the next number in such a sequence, using only the sequence itself, is one of the oldest and most commercially useful problems in statistics. ARIMA — AutoRegressive Integrated Moving Average — is the classical model built specifically for this job. Versions of it sit behind demand forecasts at e-commerce warehouses, cash-planning at banks, and traffic predictions at ride-hailing apps. By the end of this chapter you will have built one by hand, forecast Rekha's September number with nothing but a calculator, and then checked that arithmetic against real Python code.
What Makes Time Series Data Different
Picture two spreadsheets. The first lists the exam marks of forty students in a class. The second lists Rekha's fourteen monthly UPI totals. Both are columns of numbers, but they behave completely differently. In the marks sheet you could shuffle the rows — swap student 12 with student 30 — and nothing about the data's meaning changes; each row stands on its own. In Rekha's sheet, shuffling the rows would destroy the data. August's number is connected to July's, which is connected to June's, in a way that one student's marks are not connected to another's.
This connectedness between consecutive values is called autocorrelation — a series correlated with a shifted copy of itself. A month with unusually high sales tends to be followed by another decent month, not by a value drawn at random from the whole history. Tools built for independent data, such as a simple average or a best-fit straight line through a scatter plot, quietly assume there is no such connection between rows. They will still produce an answer for Rekha's data, but they throw away the very structure that makes forecasting possible: the fact that recent months carry information about the next one. ARIMA is built to use exactly that structure. The daily closing value of the BSE Sensex, the daily maximum temperature recorded by the IMD for a city, and the number of Tatkal tickets booked on IRCTC each morning are all time series with the same property — today depends, at least partly, on yesterday.
Stationarity: A Fair Target to Aim At
Before ARIMA can measure how one value depends on earlier ones, the series needs to hold still in a specific statistical sense. A time series is called stationary when its average value, its spread, and the way it correlates with its own past stay the same no matter which time window you look at. A stationary series can wobble up and down, but it wobbles around a fixed centre, with a fixed amount of noise, indefinitely.
Rekha's raw collections are not stationary. Early in the series the numbers sit near ₹1,00,000–1,30,000; by the last few months they sit near ₹1,55,000–1,65,000. The average itself keeps climbing, so there is no single centre the series wobbles around. Fitting a dependency model to a moving target is misleading — an autoregressive model would mistake the climbing trend for a strong link to the past, when it is really just the business growing over time. Statisticians usually confirm non-stationarity formally with the Augmented Dickey-Fuller (ADF) test, which checks whether a series needs adjustment before modelling; for this chapter, a visibly climbing average is evidence enough. The fix is the "I" in ARIMA.
Differencing — The "I" in ARIMA
The standard fix for a drifting average is to stop modelling the raw values and start modelling the change from one period to the next: Z(t) = Y(t) - Y(t-1). Instead of asking how much Rekha collected this month, Z asks how much more or less she collected than last month. A steadily climbing Y often turns into a Z that hovers around a roughly constant number — its drift — with no trend left in it.
This operation is called differencing, and d, the number of times it is applied, is the "Integrated" order in ARIMA(p, d, q). Most business series need d = 0 (already stationary) or d = 1 (a simple trend); d = 2 shows up occasionally when the growth rate itself is accelerating. Differencing more times than necessary is a real mistake — an over-differenced series develops artificial back-and-forth wobbles that make the next steps harder, not easier — so d is chosen as the smallest number of differences that removes the trend, and no more. In plain Python, one round of differencing on any list is a one-line operation:
values = [100, 108, 118, 130, 136, 134, 129]
differenced = [values[i] - values[i - 1] for i in range(1, len(values))]
print(differenced) # [8, 10, 12, 6, -2, -5]
AutoRegression — The "AR" in ARIMA
Once the series is stationary, ARIMA looks for structure in it using two complementary ideas. The first is AutoRegression, the "AR" in ARIMA: today's value as a weighted sum of the last p values, plus a constant and some unpredictable noise. For the simplest case, AR(1), where only the previous period matters:
Z(t) = c + phi1 * Z(t-1) + error(t)
Here phi1 (read "phi-one") is a number, usually between -1 and 1, measuring how strongly one period's change carries into the next. A phi1 near 0.6 means roughly 60% of last month's above- or below-average change tends to reappear this month; a phi1 near zero means last month tells you almost nothing about this month. AR(p) extends the idea to the last p values at once: Z(t) = c + phi1 * Z(t-1) + phi2 * Z(t-2) + ... + phip * Z(t-p) + error(t). The coefficients are not guessed — they are fitted from the data, in the same spirit as fitting a best-fit line in ordinary regression: some procedure — a computer, or shortly, a student with a calculator — chooses the values of phi that make the model's own past predictions match the actual past data as closely as possible.
Moving Average — The "MA" in ARIMA
The second idea is easy to misname. A Moving Average model — ARIMA's "MA" — has nothing to do with the rolling averages you may have used to smooth a noisy chart. It is a model of shocks, not values. Suppose one evening a last-ball cricket finish sends a burst of customers into Rekha's shop for cold drinks, a rush that has nothing to do with her usual trend or with what she sold the day before. That spike is a shock — also called an error or residual, written error(t) — the part of the series that no amount of looking at past values could have predicted. Shocks like this rarely vanish without a trace: a few of the customers drawn in that night come back once more before the novelty wears off, so a shrinking echo of the shock shows up the following day too.
MA(q) models exactly this echo: today's value depends on today's fresh shock plus a weighted share of the last q shocks.
Z(t) = mu + error(t) + theta1 * error(t-1) + ... + thetaq * error(t-q)
where mu is the series' long-run average. AR remembers past levels; MA remembers past surprises. A model can use either building block alone, or both together. Combining AR and MA without any differencing gives an ARMA model; adding differencing back in for a trending series gives the full ARIMA(p, d, q) this chapter is named for.
ARIMA(p, d, q) and Choosing the Right Numbers
Putting the three pieces together: ARIMA(p, d, q) means "difference the series d times, then fit an AR(p) and an MA(q) model on what's left." ARIMA(1, 1, 0), the model this chapter fits by hand, means one round of differencing, one autoregressive term, and no moving-average term. ARIMA(0, 1, 1) would mean one round of differencing followed by a pure MA(1) model instead. Setting p = d = q = 0 leaves nothing but random noise around a constant, with no forecastable structure at all.
Choosing d is usually done first, by differencing until the series looks flat, or by running the ADF test formally. Choosing p and q traditionally uses two companion plots, the autocorrelation function (ACF) and partial autocorrelation function (PACF), which show how strongly a series correlates with itself at each lag. This visual approach, called the Box-Jenkins method after the statisticians George Box and Gwilym Jenkins who popularised it, relies on a rule of thumb: a pure AR(p) process has a PACF that drops sharply to near zero after lag p, while a pure MA(q) process has an ACF that drops sharply to near zero after lag q. In modern practice it is just as common to skip the plots and let software search instead: Python's pmdarima library provides an auto_arima() function that fits many (p, d, q) combinations and keeps the one with the lowest Akaike Information Criterion (AIC) — a score that rewards a close fit to the data while penalising unnecessary extra parameters, so a model is never rewarded for memorising noise.
Worked Example: Forecasting Rekha's September Collections
Here is Rekha's full fourteen-month history, in thousands of rupees (100 means ₹1,00,000):
Month UPI collections (Rs '000)
Jul 2025 100
Aug 2025 108
Sep 2025 118
Oct 2025 130
Nov 2025 136
Dec 2025 134
Jan 2026 129
Feb 2026 129
Mar 2026 133
Apr 2026 142
May 2026 153
Jun 2026 160
Jul 2026 163
Aug 2026 165
Step 1 — Check stationarity. The average clearly drifts upward: roughly 100–130 in the first half of the table, roughly 130–165 in the second, with a dip through the winter months. This is not stationary, so d must be at least 1.
Step 2 — Difference once. Compute Z(t) = Y(t) - Y(t-1) for every month:
Month Z = Y(t) - Y(t-1)
Aug 2025 +8
Sep 2025 +10
Oct 2025 +12
Nov 2025 +6
Dec 2025 -2
Jan 2026 -5
Feb 2026 +0
Mar 2026 +4
Apr 2026 +9
May 2026 +11
Jun 2026 +7
Jul 2026 +3
Aug 2026 +2
Z hovers between -5 and +12 with no obvious drift left, so one differencing is enough: d = 1. Its average is (8+10+12+6-2-5+0+4+9+11+7+3+2) / 13 = 65 / 13 = 5.0 — Rekha's collections grow, on average, by ₹5,000 a month.
Step 3 — Choose p and q. With only fourteen months of history, a formal ACF/PACF reading would be too noisy to trust — reliable Box-Jenkins identification generally wants several dozen observations before those plots settle down. For this worked example we keep the structure simple and deliberately fit ARIMA(1, 1, 0): one autoregressive lag, no moving-average term. AR has a closed-form estimate computable with nothing but a calculator, shown next; MA coefficients need iterative numerical fitting with no such shortcut, which is exactly the kind of job real projects hand to software rather than a worked example.
Step 4 — Estimate phi1. The standard formula for an AR(1) coefficient comes from the Yule-Walker equations, named after the statistician George Udny Yule and the statistician Sir Gilbert Walker, who spent the early 1900s running India's meteorological observatories while trying to forecast the monsoon. The formula compares each deviation from the mean with the deviation right before it:
phi1 = [sum of (Z(t) - mean) * (Z(t-1) - mean)] / [sum of (Z(t) - mean)^2]
With mean = 5.0, here is every term:
Month Z dev=Z-5 dev^2 dev(t) x dev(t-1)
Aug 2025 +8 3 9 --
Sep 2025 +10 5 25 3 x 5 = 15
Oct 2025 +12 7 49 5 x 7 = 35
Nov 2025 +6 1 1 7 x 1 = 7
Dec 2025 -2 -7 49 1 x -7 = -7
Jan 2026 -5 -10 100 -7 x -10 = 70
Feb 2026 +0 -5 25 -10 x -5 = 50
Mar 2026 +4 -1 1 -5 x -1 = 5
Apr 2026 +9 4 16 -1 x 4 = -4
May 2026 +11 6 36 4 x 6 = 24
Jun 2026 +7 2 4 6 x 2 = 12
Jul 2026 +3 -2 4 2 x -2 = -4
Aug 2026 +2 -3 9 -2 x -3 = 6
TOTAL 328 209
So phi1 = 209 / 328 = 0.637. About 64% of any month's above- or below-average change carries forward into the next month.
Step 5 — Forecast the next difference. August's difference was +2, which is 3 below the mean of 5. Applying the AR(1) formula:
Z_hat(Sep) = mean + phi1 * (Z_Aug - mean)
= 5.0 + 0.637 * (2 - 5.0)
= 5.0 + 0.637 * (-3.0)
= 5.0 - 1.91
= 3.09
Step 6 — Undo the differencing. This is the "Integrated" step in reverse: add the forecast change back onto the last known level.
Y_hat(Sep 2026) = Y(Aug 2026) + Z_hat(Sep)
= 165 + 3.09
= 168.09
ARIMA's forecast for September 2026 is ₹1,68,090. Notice this sits a little below the "naive" forecast of simply adding the average change (165 + 5.0 = ₹1,70,000): because August's own change (+2) came in under the recent average and phi1 is positive, the model expects a touch of that softness to persist into September rather than snapping straight back to the long-run average. Reading the most recent surprise, not just the long-run average, is precisely what the AR term buys you.
Checking the Work in Python
Hand-fitting an AR(1) model is a useful exercise to do once; in practice this is code's job, especially once a model needs more than one AR or MA term. The statsmodels library implements the same mathematics, with a proper numerical optimiser instead of the simplified Yule-Walker formula used above:
import pandas as pd
from statsmodels.tsa.arima.model import ARIMA
months = pd.date_range("2025-07-01", periods=14, freq="MS")
collections = [100, 108, 118, 130, 136, 134, 129,
129, 133, 142, 153, 160, 163, 165]
sales = pd.Series(collections, index=months)
# order=(p, d, q) -> AR(1), differenced once, no MA term
# trend="t" tells statsmodels the differenced series has a
# non-zero average drift (the shop grows about Rs 5,000/month)
model = ARIMA(sales, order=(1, 1, 0), trend="t")
fitted = model.fit()
print(fitted.params.round(3))
forecast = fitted.get_forecast(steps=1)
print("Sep-2026 forecast (Rs '000):", round(forecast.predicted_mean.iloc[0], 2))
Running this prints:
x1 5.000
ar.L1 0.626
sigma2 14.447
dtype: float64
Sep-2026 forecast (Rs '000): 168.12
The fitted drift (x1) matches our hand-computed mean exactly, and the fitted AR coefficient, 0.626, sits close to the 0.637 computed by hand — the small gap exists because statsmodels fits by maximum likelihood, a more refined technique than the Yule-Walker shortcut, not because either calculation is wrong. The forecast, ₹1,68,120, differs from the hand answer by about ₹30, well within rounding. The library also reports a 95% confidence interval for that forecast, roughly ₹1.61 lakh to ₹1.76 lakh, which is worth taking seriously: a forecast is a best estimate with a margin of uncertainty attached, never a promise.
When One Series Has a Season
Plain ARIMA has no notion of the calendar. If Rekha's sales jumped every year around Diwali because of gift and sweet purchases, and dipped every year during the same monsoon week, a plain AR(1) or AR(2) term would miss that repeating rhythm entirely — it only looks a few months back, not a full year back. The extension for this is Seasonal ARIMA (SARIMA), written ARIMA(p, d, q)(P, D, Q)m, which adds a second set of AR, differencing, and MA terms operating at a lag of m — 12, for monthly data with a yearly cycle — alongside the ordinary ones. The underlying ideas are the same ones this chapter has already covered; SARIMA just applies AutoRegression, differencing, and Moving Average twice, once for the short-term rhythm and once for the seasonal one.
What ARIMA Cannot See
ARIMA extrapolates statistical patterns that already exist in the numbers fed into it. It has no idea that a new provision store might open two lanes down from Rekha's, that a UPI outage could freeze collections for a day, or that a major festival's date moves around the Gregorian calendar from year to year. Every forecast it produces is really a conditional statement: if the next month behaves statistically like recent months, expect this number. When that condition breaks — because a real event changes the underlying business — the confidence interval around the forecast is the honest part of the answer, not the single predicted number. Treating an ARIMA forecast as a well-reasoned starting point, to be adjusted with real-world judgment, is the difference between using the tool well and trusting it blindly.
Back to the Shop
Rekha now has a real number for September: about ₹1,68,000, a touch above August's ₹1,65,000, with the model itself flagging that growth has softened slightly rather than accelerated. That is enough to plan a modest restocking order rather than an aggressive one, and to keep a cash float sized for a similar month, not a booming one. Nothing in the arithmetic she just worked through by hand — a difference here, a sum of products there, a division — is exotic; it is the same machinery, scaled up, behind an e-commerce platform predicting next week's warehouse demand, a bank forecasting how much cash its ATMs will need before a long weekend, or a railway booking system anticipating traffic before a festival rush. A look at what changed, a look at what tends to repeat, and a look at what recently surprised you: those three ideas, spelled AR, I, and MA, turn out to be enough to make a genuinely useful guess about tomorrow, whether tomorrow belongs to a Kothrud kirana shop or a national payments network.
Think About It
Think about this: How would you explain arima: time series forecasting to a friend who has never seen a computer? What real-world analogy would you use? Imagine you had to build a system using these concepts — what would be your first step? Try this: before moving on, write down three things you learned and one question you still have.
Key Takeaways — Summary and Recap
Let us recap what we covered: the core ideas behind arima: time series forecasting, how they connect to real-world applications, and why they matter for your journey in computer science. Remember these key points as you move forward. For competitive exam preparation (CBSE, JEE, BITSAT), focus on understanding the WHY behind each concept, not just the WHAT.