213. Weighted Moving Average

213.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.

WMA𝑡=𝑖=0𝑀1𝑤𝑖𝑥𝑡𝑖𝑖=0𝑀1𝑤𝑖

where 𝑤𝑖 is the weight on the observation 𝑖 steps before 𝑡 (so 𝑤0 weights the most recent value, 𝑤𝑀1 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.

213.1.1. Common weight schemes

213.1.2. Comparison to SMA

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., 𝑀/(𝑀(𝑀+1)/2)=2/(𝑀+1) for linearly decreasing — compared to 1/𝑀 for SMA).

213.1.3. Comparison to SES

WMA with linearly-decreasing weights is conceptually similar to SES, with two differences:

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, 𝑀=3):

  • 𝑤0=3 (most recent)
  • 𝑤1=2
  • 𝑤2=1 (oldest in window)

Denominator: 3+2+1=6.

Forecasts:

WMA3=314+212+1106=42+24+106=12.67WMA4=313+214+1126=39+28+126=13.17WMA5=315+213+1146=45+26+146=14.17

Compare to SMA with 𝑀=3 on the same data:

SMA3=10+12+143=12.00SMA4=12+14+133=13.00SMA5=14+13+153=14.00

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),
)