Here is an experiment you can run in your head. Take two spreadsheets. Sheet A is TCS's closing share price on the NSE for the last 250 trading days, one number per row. Sheet B is New Delhi's maximum temperature for the last 250 days, also one number per row. Now do something that felt perfectly harmless in every regression problem you've solved so far: shuffle the rows into random order before you train a model on them.
For house-price prediction or exam-score prediction, shuffling changes nothing. House 47 has no relationship to House 48 sitting next to it in the spreadsheet — the order was arbitrary to begin with, an accident of how the data was typed in. That's the i.i.d. assumption (independent and identically distributed) that linear regression, and almost every model you've built until now, quietly leans on.
Shuffle Sheet A or Sheet B, though, and you've destroyed the one thing that made the data useful. Wednesday's temperature is not independent of Tuesday's — warm air masses don't vanish overnight. Today's share price is not independent of yesterday's — it's mathematically built from yesterday's price plus one day's worth of change. Order isn't incidental to this data. Order is the data. That single fact — that observations are chained to their neighbours in time — is what makes time series forecasting a genuinely different problem from every regression chapter before this one, with its own definitions, its own failure modes, and (as you'll see) its own very different levels of difficulty depending on what you're trying to predict.
What a Time Series Actually Is
A time series is a sequence of observations Y₁, Y₂, ..., Yₙ recorded at successive, evenly-spaced time points, where the index (1, 2, 3, ...) represents time and cannot be reordered without changing the meaning of the data. Forecasting means estimating Yₙ₊₁ (or several steps further ahead) using only Y₁ through Yₙ — the past, never the future. That last clause looks obvious written down, but as you'll see later in this chapter, it is the single most common way students and even professionals accidentally cheat when evaluating a forecasting model.
The Anatomy of a Time Series: Trend, Seasonality, Noise
Most real time series can be thought of as a sum of three ingredients:
- Trend — a slow, long-run drift upward or downward (a warming climate, a company's multi-year growth).
- Seasonality — a pattern that repeats at a fixed, known period (temperature peaks every June, UPI transaction volume spikes every festival season, ice-cream sales peak every summer).
- Noise (residual) — everything left over: short-term randomness that no model can predict, whether it's a freak dust storm or a single trader's impulsive sell order.
The diagram below is a synthetic (constructed, not real IMD data) two-year temperature-like series built by literally adding these three pieces together, so you can see the decomposition with your own eyes: Raw(t) = Trend(t) + Seasonal(t) + Noise(t), where Trend(t) = 25 + 0.3t (a gentle warming drift) and Seasonal(t) = 10·sin(30°·(t−3)) (a 12-month cycle peaking mid-year).
Notice how the smooth navy line runs straight through the middle of the noisy red swings, ignoring the yearly up-down cycle entirely — it's the slow-moving average behaviour buried inside the noisy data. That is exactly the intuition behind the moving average method you'll derive numerically in a few paragraphs: averaging over a full seasonal cycle cancels the seasonal swing and much of the noise, leaving the trend exposed.
Autocorrelation: How Much Does the Past Predict the Present?
To make "the past predicts the present" precise, we need a number. The autocorrelation function (ACF) at lag k measures the correlation between the series and a copy of itself shifted by k steps:
rₖ = [ Σₜ₌ₖ₊₁ⁿ (Yₜ − Ȳ)(Yₜ₋ₖ − Ȳ) ] ÷ [ Σₜ₌₁ⁿ (Yₜ − Ȳ)² ]
This should look familiar — it's the same Pearson correlation-coefficient formula from your Class 11–12 statistics chapter, r = Σ(x−x̄)(y−ȳ) ÷ √(Σ(x−x̄)²Σ(y−ȳ)²), applied to a series and its own lagged self, with the denominator simplified because both "variables" have the same variance. It's a genuinely useful formula in JEE/BITSAT data-interpretation sets too.
Let's compute r₁ by hand on a concrete example: a fictional stock's closing price (in rupees) over 7 trading days: 100, 102, 101, 104, 103, 106, 105.
Mean Ȳ = (100+102+101+104+103+106+105) / 7 = 721 / 7 = 103.
Deviations from the mean, day by day: −3, −1, −2, +1, 0, +3, +2.
Denominator (sum of squared deviations): (−3)² + (−1)² + (−2)² + 1² + 0² + 3² + 2² = 9+1+4+1+0+9+4 = 28.
Numerator (sum of consecutive products of deviations, dₜ·dₜ₋₁): (−1)(−3) + (−2)(−1) + (1)(−2) + (0)(1) + (3)(0) + (2)(3) = 3+2−2+0+0+6 = 9.
r₁ = 9 / 28 ≈ 0.32.
A modest positive lag-1 autocorrelation: knowing today's price gives you a little information about tomorrow's, but not a lot — the series isn't perfectly random, but it isn't strongly predictable from its own past either. Hold onto this number; it's about to explain a very important asymmetry between weather and stock prices.
Stationarity, Differencing, and the Random Walk
A time series is (weakly) stationary if its mean is constant over time, its variance is constant over time, and the covariance between Yₜ and Yₜ₊ₖ depends only on the lag k, never on t itself. Most forecasting theory is built for stationary series, so the first question you ask of any real series is whether it's stationary — and stock prices, famously, are not.
The simplest honest model of a stock's daily closing price is the random walk: Yₜ = Yₜ₋₁ + εₜ, where εₜ is unpredictable noise with mean 0 and constant variance σ². Unroll the recursion back to a starting price Y₀: Yₜ = Y₀ + ε₁ + ε₂ + ... + εₜ. Because the ε's are independent, variances add: Var(Yₜ) = Var(ε₁) + Var(ε₂) + ... + Var(εₜ) = tσ². The variance grows linearly with t — it is never constant — so a random walk is, by definition, not stationary. This is exactly why a stock chart looks like it "wanders" over years instead of oscillating around a fixed level: the uncertainty band around any long-run forecast keeps widening forever.
The standard fix is differencing: work with ΔYₜ = Yₜ − Yₜ₋₁ instead of Yₜ itself. For a true random walk, ΔYₜ = εₜ, which — being plain noise — is stationary by construction. For our 7-day price example, the first differences are: 2, −1, 3, −1, 3, −1. (Check: 102−100=2, 101−102=−1, 104−101=3, 103−104=−1, 106−103=3, 105−106=−1.) You'll recognise these numbers again shortly — they are exactly the errors you get from the simplest possible forecasting rule.
Four Forecasting Models, in Increasing Sophistication
We'll forecast day 8's price for the same 7-day series (100, 102, 101, 104, 103, 106, 105), using four methods of increasing complexity, so you can compare what each one actually buys you.
1. Naive (persistence) forecast: Ŷₜ₊₁ = Yₜ. It simply says "tomorrow will look like today." Forecast for day 8 = Y₇ = 105. This is not a strawman — for a series close to a random walk, this is a genuinely hard baseline to beat, and every serious forecasting result must be compared against it.
2. Moving average (window k=3): Ŷₜ₊₁ = average of the last 3 observed values. Forecast for day 8 = (Y₅+Y₆+Y₇)/3 = (103+106+105)/3 = 314/3 ≈ 104.67. Averaging smooths out one-off noise, at the cost of reacting slowly to genuine recent shifts.
3. Simple exponential smoothing (SES): instead of a hard cutoff at 3 days, weight every past observation, with recent ones weighted more. Define a "level" recursively: Lₜ = αYₜ + (1−α)Lₜ₋₁, with smoothing parameter 0<α<1 and L₁ = Y₁. The forecast for the next period is simply the latest level. Let's derive what this recursion actually means by substituting it into itself:
Lₜ = αYₜ + (1−α)Lₜ₋₁ = αYₜ + (1−α)[αYₜ₋₁ + (1−α)Lₜ₋₂] = αYₜ + α(1−α)Yₜ₋₁ + (1−α)²Lₜ₋₂
Repeating the substitution, the weight on the observation j steps back is α(1−α)ʲ — a geometric decay. Because 0<α<1, we have |1−α|<1, so this is exactly the convergent geometric series from your Class 11 Sequences and Series chapter, and its infinite sum is α · [1/(1−(1−α))] = α · (1/α) = 1. The weights are a proper weighted average that sums to 1 — SES is precisely "a moving average where the influence of the past decays smoothly instead of cutting off abruptly at a fixed window."
Computing it with α=0.5 on our data: L₁=100; L₂=0.5(102)+0.5(100)=101; L₃=0.5(101)+0.5(101)=101; L₄=0.5(104)+0.5(101)=102.5; L₅=0.5(103)+0.5(102.5)=102.75; L₆=0.5(106)+0.5(102.75)=104.375; L₇=0.5(105)+0.5(104.375)=104.69 (rounded), which is the forecast for day 8.
4. Autoregressive model AR(1): the most "model-like" of the four. It proposes Xₜ = c + φXₜ₋₁ + εₜ, and fits c and φ by ordinary least squares — the exact same line-of-best-fit machinery from your regression chapter, except the "x" and "y" columns are the same series, offset by one day. Using the 6 pairs (Yₜ₋₁, Yₜ) from our data:
Σx=616, Σy=621, Σxy=63766, Σx²=63266, n=6.
φ = [nΣxy − ΣxΣy] / [nΣx² − (Σx)²] = [6(63766) − 616(621)] / [6(63266) − 616²] = [382596 − 382536] / [379596 − 379456] = 60/140 = 3/7 ≈ 0.429.
c = ȳ − φx̄ = 103.5 − (3/7)(102.667) = 103.5 − 44.0 = 59.5.
Forecast for day 8 = 59.5 + (3/7)(105) = 59.5 + 45.0 = 104.50.
Line up all four forecasts for day 8: naive 105.00, moving average 104.67, SES 104.69, AR(1) 104.50. Four methods of wildly different sophistication — one of them literally just "least-squares regression" — landed within 50 paise of each other. That clustering is not a coincidence, and it's the key insight of this chapter.
Why Weather Is (Somewhat) Predictable and Stocks Are (Almost) Not
The physical atmosphere obeys continuous, deterministic laws — pressure gradients, moisture transport, heat exchange — that connect today's weather causally to tomorrow's. A hot, moist air mass over the Bay of Bengal doesn't teleport away overnight; it takes time to move, cool, or rain itself out. That physical continuity is exactly what a high lag-1 ACF measures, and real daily-temperature data typically shows autocorrelations well above 0.8–0.9 at lag 1, plus a strong, exactly-periodic seasonal ACF spike at lag 12 (months) or lag 365 (days). This is why the India Meteorological Department's short-range forecasts (1–3 days) are quite reliable, and why "tomorrow will resemble today, adjusted for the season" is a genuinely strong baseline for weather. Skill does degrade with horizon, though — the atmosphere is a chaotic system in the mathematical sense (small errors in today's measurement amplify over time, the "butterfly effect" first described by meteorologist Edward Lorenz), which is why forecast accuracy falls off sharply beyond about 7–10 days and why IMD's monsoon-season outlook leans on statistical and dynamical climate models rather than pure short-term time-series extrapolation.
A stock's closing price has no comparable physical inertia. Its lag-1 ACF here came out to a modest 0.32 — some memory, not much — and that's typical, not a defect of our toy example. This is the empirical heart of the weak-form efficient-market hypothesis, formalised by the economist Eugene Fama in the 1960s: in a liquid, widely-traded market, any predictable pattern in past prices gets discovered and traded away almost immediately by people trying to profit from it, which pushes prices toward behaving like a random walk. That's precisely why our AR(1) fit — which is mathematically the "best possible" linear function of yesterday's price — barely beat the naive guess: there just isn't much linear signal left in the price history alone to extract. (This does not mean stock prices are literally unpredictable in every sense — news, fundamentals, and order-flow data carry information — only that forecasting a price purely from its own past values, the subject of this chapter, has a very low ceiling.)
Evaluating Forecasts Correctly: Walk-Forward, Never Random Split
Common misconception: "I'll do what I always do — shuffle the data and take a random 80/20 train-test split, same as any other ML problem." This is wrong, and it's wrong in a way that silently inflates your reported accuracy. If a shuffled split puts day 200 in your training set and day 150 in your test set, your model effectively gets to "see the future" (day 200) while being scored on "predicting the past" (day 150) — this is called lookahead bias or data leakage, and it produces test accuracy numbers that are fiction.
The correct procedure is walk-forward validation: train only on data up to time t, forecast t+1, record the error, then advance the window by one step and repeat — always chronological, never shuffled. Let's do this properly on our 7-day price series, comparing naive against moving-average(3) over the four days (day 4 through day 7) where both methods have enough history to produce a forecast:
- Day 4: naive forecasts Y₃=101 (actual 104, error 3); MA3 forecasts avg(100,102,101)=101 (actual 104, error 3).
- Day 5: naive forecasts Y₄=104 (actual 103, error 1); MA3 forecasts avg(102,101,104)=102.33 (actual 103, error 0.67).
- Day 6: naive forecasts Y₅=103 (actual 106, error 3); MA3 forecasts avg(101,104,103)=102.67 (actual 106, error 3.33).
- Day 7: naive forecasts Y₆=106 (actual 105, error 1); MA3 forecasts avg(104,103,106)=104.33 (actual 105, error 0.67).
Mean Absolute Error, MAE = (1/n)Σ|Yₜ − Ŷₜ|: naive MAE = (3+1+3+1)/4 = 2.00; MA3 MAE = (3+0.67+3.33+0.67)/4 = 1.92. Root Mean Squared Error, RMSE = √[(1/n)Σ(Yₜ−Ŷₜ)²], penalises large errors more heavily and is worth computing whenever a single bad miss matters more than several small ones. MA3 edges out naive here — by a small margin, exactly as the theory predicts for a near-random-walk series. A model report that never states this comparison to the naive baseline is not showing you evidence of real forecasting skill.
A Second Misconception: "More Complex Always Means More Accurate"
Look again at the day-8 forecasts from earlier: naive 105.00, MA3 104.67, SES 104.69, AR(1) — the most "statistically sophisticated" of the four, fit by proper least squares — 104.50. The fancy model did not win. This is not a rigged example; it's the typical experience of anyone who has tried to forecast a genuinely liquid, efficiently-traded price series using only its own history. Complexity helps when there is real structure left to extract (as with weather's strong seasonality and high autocorrelation); it does nothing but fit noise when there isn't (as with near-random-walk prices), and a model that "fits" noise well in-sample often forecasts worse out-of-sample — a phenomenon called overfitting, which you may already recognise from earlier ML chapters and which time series makes especially easy to fall into, because a shuffled or in-sample evaluation hides it perfectly.
Code: Fitting SES and AR(1) in Python
import numpy as np
# Daily closing prices (rupees) - illustrative example
prices = [100, 102, 101, 104, 103, 106, 105]
# ---- Simple Exponential Smoothing ----
alpha = 0.5
level = prices[0] # L1 = Y1
for y in prices[1:]:
level = alpha * y + (1 - alpha) * level
print(f"SES forecast for day 8: {level:.2f}")
# -> SES forecast for day 8: 104.69
# ---- AR(1) via least squares: X_t = c + phi * X_(t-1) ----
x = np.array(prices[:-1]) # X_1 ... X_6
y = np.array(prices[1:]) # X_2 ... X_7
phi, c = np.polyfit(x, y, 1) # degree-1 fit returns [slope, intercept]
forecast_ar1 = c + phi * prices[-1]
print(f"AR(1): phi={phi:.3f}, c={c:.2f}")
print(f"AR(1) forecast for day 8: {forecast_ar1:.2f}")
# -> AR(1): phi=0.429, c=59.50
# -> AR(1) forecast for day 8: 104.50
Trace it: level starts at 100, then updates once per remaining price exactly as we hand-computed above, ending at 104.6875 (printed as 104.69). np.polyfit(x, y, 1) solves the same least-squares normal equations we solved by hand, returning the highest-degree coefficient first — slope then intercept — which is why the unpacking order is phi, c. Both outputs match our hand calculation exactly, which is the whole point of doing the algebra first: you should never trust a library call you can't verify by hand on a small example.
One More Stationarity Result Worth Deriving
Why does AR(1) require |φ|<1 to be a sensible model at all? Assume a stationary solution exists, so Var(Xₜ) = Var(Xₜ₋₁) = γ₀ for every t. Taking the variance of both sides of Xₜ = c + φXₜ₋₁ + εₜ (and using that εₜ is independent of Xₜ₋₁):
γ₀ = φ²γ₀ + σ²ε ⟹ γ₀(1 − φ²) = σ²ε ⟹ γ₀ = σ²ε / (1 − φ²)
This is only a valid (positive, finite) variance when 1−φ² > 0, i.e. |φ|<1. Set φ=1 exactly and the formula divides by zero — precisely the random walk case, whose variance we showed earlier grows without bound as tσ² instead of settling at a constant γ₀. Our fitted φ ≈ 0.429 is safely inside (−1, 1), so the AR(1) model is at least internally consistent as a stationary model — even though, as we saw, it barely improves on persistence for this particular series.
Summary
A time series is data whose order carries meaning, which breaks the independence assumption behind ordinary regression and demands its own toolkit. Real series decompose into trend, seasonality, and noise. Autocorrelation quantifies how strongly the past predicts the present, using the same correlation-coefficient machinery from your statistics syllabus. Stationarity — constant mean, variance, and lag-dependent covariance — is the property most forecasting math assumes, and a random walk (the honest baseline model for a traded stock price) provably fails it, because its variance grows linearly with time. Naive persistence, moving averages, exponential smoothing (a geometrically-weighted moving average, provably summing to weight 1), and AR(p) regression form a natural ladder of increasingly sophisticated forecasters — but the ladder only pays off when the series has real autocorrelation structure to exploit, which physically-driven weather series have far more of than efficiently-traded prices do. Forecasts must always be evaluated with chronological walk-forward validation, never a random split, and always against the naive baseline — otherwise you cannot tell genuine skill from noise dressed up as accuracy.
Test Yourself
Illustrative daily IRCTC ticket bookings, in thousands, over 5 days: 40, 44, 42, 47, 45. Using this data:
- Compute the naive forecast for day 6.
- Compute the 2-day moving average forecast for day 6.
- Compute the SES forecast for day 6 using α=0.6 and L₁=Y₁.
- Fit an AR(1) model by least squares on the four (Yₜ₋₁, Yₜ) pairs and forecast day 6. Is the fitted φ close to 1 (random-walk-like, strong persistence) or close to 0 (weak persistence)?
- Explain, in your own words, why evaluating this model with a random 80/20 train-test split would give a misleadingly optimistic accuracy number, and describe what walk-forward validation would do instead.
- State the stationarity condition on φ for an AR(1) model, and explain why a random walk (φ=1) violates it.
Answer key. (1) Naive: Ŷ₆=Y₅=45. (2) MA2: (Y₄+Y₅)/2=(47+45)/2=46. (3) SES: L₁=40; L₂=0.6(44)+0.4(40)=42.4; L₃=0.6(42)+0.4(42.4)=42.16; L₄=0.6(47)+0.4(42.16)=45.064; L₅=0.6(45)+0.4(45.064)≈45.03 — the day-6 forecast. (4) Pairs (40,44),(44,42),(42,47),(47,45): Σx=173, Σy=178, Σxy=7697, Σx²=7509, n=4. φ = [4(7697)−173(178)]/[4(7509)−173²] = [30788−30794]/[30036−29929] = −6/107 ≈ −0.056; c = 44.5−(−0.056)(43.25) ≈ 46.93; forecast = 46.93+(−0.056)(45) ≈ 44.40. φ came out slightly negative and very close to zero — with only 4 data pairs this estimate is extremely noisy (one unusual value can flip its sign); the honest lesson is that you need dozens of observations, not four, before trusting a fitted AR coefficient at all. (5) A random split can place a later day in training and an earlier day in the test set, letting the model implicitly "see the future" it's being scored on — this is lookahead bias/data leakage, and it inflates reported accuracy. Walk-forward validation instead trains only on data up to day t, forecasts day t+1, records the error, then rolls the window forward one step and repeats — always respecting chronological order. (6) Stationarity of AR(1) requires |φ|<1, since the derived variance γ₀ = σ²ε/(1−φ²) is only finite and positive in that range; a random walk has φ=1 exactly, making that formula divide by zero, consistent with its variance growing without bound as tσ² instead of staying constant.
Think About It
Think about this: How would you explain time series forecasting: predicting stock prices and weather 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.
Practice Exercises
Now it is time to practice! Complete these challenges to solidify your understanding:
- Exercise 1: Write a short program that demonstrates the core concept from this chapter. Test it with at least 3 different inputs.
- Exercise 2: Find a real-world example where time series forecasting: predicting stock prices and weather is used in an Indian company (like TCS, Infosys, Flipkart, or ISRO). Write a paragraph explaining the connection.
- Exercise 3: Create a mind-map connecting time series forecasting: predicting stock prices and weather to at least 3 other topics you have studied.