Master Moving Average & Exponential Smoothing for Time Series Forecasting
This article explains the principles, formulas, and Python implementations of simple and double moving averages, as well as single, double, and Holt's exponential smoothing methods, illustrating each technique with real data cases and code samples.
Moving Average Method
Moving average is a common time‑series forecasting method valued for its simplicity and practical usefulness.
Simple Moving Average
Given an observation series \(y_t\) and a window size \(N\), the forecast for period \(t+1\) is the average of the last \(N\) observations. The standard error of the forecast can be computed accordingly. Because forecast error grows with horizon, simple moving average is usually applied only to one‑step‑ahead predictions.
Case Study
Predict the next January carburetor sales using a 3‑month moving average based on the provided monthly sales data. The table (omitted) shows the original sales and the computed 3‑month and 5‑month averages.
Modeling
Apply the forecast formula \(\hat{y}_{t+1}=\frac{1}{N}\sum_{i=t-N+1}^{t} y_i\).
Computation
Compute the 3‑month and 5‑month moving‑average forecasts; the corresponding standard errors are reported. The data exhibit large fluctuations, and the forecast standard errors remain relatively high, so simple moving average is rarely used for highly volatile series.
Code
<code>import numpy as np
y = np.array([423, 358, 434, 445, 527, 429, 426, 502, 480, 384, 427, 446])
def MoveAverage(y, N):
Mt = ['*'] * N
for i in range(N + 1, len(y) + 2):
M = y[i - (N + 1):i - 1].mean()
Mt.append(round(M))
return Mt
yt3 = MoveAverage(y, 3)
s3 = np.sqrt(((y[3:] - yt3[3:-1]) ** 2).mean())
yt5 = MoveAverage(y, 5)
s5 = np.sqrt(((y[5:] - yt5[5:-1]) ** 2).mean())
print('N=3 forecast values:', yt3, 'standard error:', s3)
print('N=5 forecast values:', yt5, 'standard error:', s5)
</code>Double Moving Average
When the series shows a linear trend, a double moving average (trend‑adjusted moving average) can be used. The method first smooths the data with a simple moving average and then applies a second moving average to the smoothed series. The resulting forecast reduces lag compared with a single moving average.
Exponential Smoothing
Exponential smoothing assigns exponentially decreasing weights to older observations, overcoming the equal‑weight limitation of simple moving average.
Simple Exponential Smoothing (SES)
The forecast formula is \(\hat{y}_{t+1}=\alpha y_t + (1-\alpha)\hat{y}_t\), where \(0\le\alpha\le1\) is the smoothing parameter. Small \(\alpha\) yields smoother forecasts; \(\alpha=0\) reduces to the mean method, and \(\alpha=1\) to the naive method.
Choosing \(\alpha\)
If the series is stable, choose a small \(\alpha\) (e.g., 0.1‑0.5) to incorporate long‑term information.
If the series changes rapidly, choose a larger \(\alpha\) (e.g., 0.6‑0.9) to give more weight to recent observations.
In practice, several \(\alpha\) values are tried and the one with the smallest forecast error is selected.
Code
<code>import numpy as np, pandas as pd
y = np.array([4.81, 4.8, 4.73, 4.7, 4.7, 4.73, 4.75, 4.75, 5.43, 5.78, 5.85])
def ExpMove(y, a):
n = len(y)
M = np.zeros(n)
M[0] = (y[0] + y[1]) / 2
for i in range(1, n):
M[i] = a * y[i-1] + (1 - a) * M[i-1]
return M
yt1 = ExpMove(y, 0.2)
yt2 = ExpMove(y, 0.5)
yt3 = ExpMove(y, 0.8)
s1 = np.sqrt(((y - yt1) ** 2).mean())
s2 = np.sqrt(((y - yt2) ** 2).mean())
s3 = np.sqrt(((y - yt3) ** 2).mean())
print('Standard errors:', s1, s2, s3)
</code>Holt’s Linear Trend Method (Double Exponential Smoothing)
Holt extends simple exponential smoothing to capture a linear trend by introducing a trend component. The model includes level \(l_t\) and trend \(b_t\) updates: \[l_t = \alpha y_t + (1-\alpha)(l_{t-1}+b_{t-1})\] \[b_t = \beta (l_t - l_{t-1}) + (1-\beta) b_{t-1}\] The forecast is \(\hat{y}_{t+m}=l_t + m b_t\). A damped version adds a damping factor \(\phi\) (0<\phi<1) to prevent explosive forecasts.
Code example using statsmodels :
<code>import matplotlib.pyplot as plt
from statsmodels.tsa.holtwinters import SimpleExpSmoothing, Holt
data = [253993, 275396.2, 315229.5, 356949.6, 400158.2, 442431.7, 495102.9,
570164.8, 640993.1, 704250.4, 767455.4, 781807.8, 776332.3, 794161.7,
834177.7, 931651.5, 1028390, 1114914]
# Simple Exponential Smoothing with fixed alphas
fit1 = SimpleExpSmoothing(data).fit(smoothing_level=0.2, optimized=False)
fit2 = SimpleExpSmoothing(data).fit(smoothing_level=0.6, optimized=False)
fit3 = SimpleExpSmoothing(data).fit() # automatic alpha
# Holt's linear trend
holt_fit = Holt(data).fit(smoothing_level=0.8, smoothing_slope=0.2, optimized=False)
# Plot (omitted for brevity)
</code>Appendix – Parameter Calculation for Smoothing Models
The appendix derives the formulas for estimating the smoothing parameters and initial values of linear exponential smoothing models based on minimizing the sum of squared forecast errors.
References:
https://www.cnblogs.com/harrylyx/p/11852149.html
https://zhuanlan.zhihu.com/p/410812961
Model Perspective
Insights, knowledge, and enjoyment from a mathematical modeling researcher and educator. Hosted by Haihua Wang, a modeling instructor and author of "Clever Use of Chat for Mathematical Modeling", "Modeling: The Mathematics of Thinking", "Mathematical Modeling Practice: A Hands‑On Guide to Competitions", and co‑author of "Mathematical Modeling: Teaching Design and Cases".
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.