211. Weighted Moving Average
211.1. WMA (Weighted Moving Average)
Same finite-window structure as SMA, but each observation in the window gets a custom weight — usually with more weight on more recent observations.
where is the weight on the observation steps before (so weights the most recent value, the oldest in the window).
The denominator normalizes the weights so the WMA is on the same scale as the data; if the weights already sum to 1, the denominator drops out.
211.1.1. Common weight schemes
- Linearly decreasing (most common): . So , , …, . Most weight on the most recent.
- Triangular: linearly increasing then decreasing — emphasizes the middle of the window.
- Custom: any non-negative weights you choose.
211.1.2. Comparison to SMA
- SMA: equal weight on every observation in the window.
- WMA: more weight on recent observations (with linearly-decreasing weights).
WMA is more responsive to recent changes than SMA at the same window size , because the new observation gets a relatively large weight (e.g., for linearly decreasing — compared to for SMA).
211.1.3. Comparison to SES
WMA with linearly-decreasing weights is conceptually similar to SES, with two differences:
- WMA truncates at ; SES uses the entire history (with geometrically-decaying weights).
- WMA’s most-recent weight depends on (e.g., ); SES uses the explicit smoothing parameter .
For with linearly-decreasing weights, WMA approaches a geometric-weighted form similar to SES — but with polynomially-decaying tails rather than exponentially-decaying.
Example
Data
- Day 1: $10
- Day 2: $12
- Day 3: $14
- Day 4: $13
- Day 5: $15
Weights (linearly decreasing, ):
- (most recent)
- (oldest in window)
Denominator: .
Forecasts:
Compare to SMA with on the same data:
WMA values are slightly higher than SMA because the most-recent (and largest) observations get more weight. On a trending up series, WMA tracks the trend better; on a random series, both are similar.
wma.py
weights = [3, 2, 1]
pl.col('X').rolling_map(
lambda s: sum(w * x for w, x in zip(weights, s)) / sum(weights),
window_size=len(weights),
)