The Weighted Moving Average (WMA) addresses the lag issue inherent in Simple Moving Averages (SMA) by assigning linearly decreasing weights to historical prices. Recent data points carry significantly more influence than older ones, resulting in a trend indicator that reacts faster to price changes while maintaining better smoothness than exponential alternatives. It strikes a balance between responsiveness and noise reduction.
While moving averages have been a staple of financial analysis since the early 20th century, the Weighted Moving Average gained prominence as traders sought a middle ground between the significant lag of the SMA and the potential hypersensitivity of the EMA. It became a standard tool in technical analysis packages in the 1980s, offering a mathematically straightforward way to prioritize recent market action without the infinite memory tail of exponential smoothing.
Imagine a 5-day WMA. Today's price is the most important, so it gets a weight of 5. Yesterday's price gets a weight of 4, and so on, back to the oldest price in the window which gets a weight of 1. You sum up all these weighted prices and divide by the sum of the weights (1+2+3+4+5 = 15). As the window moves forward, the oldest price drops off completely, and every other price effectively "slides down" in importance, with the new price taking the top weight.
A naive WMA implementation recalculates the entire weighted sum for each new bar, resulting in O(n) complexity. As the period grows, the calculation gets slower.
This reduces the calculation to two subtractions, two additions, and one multiplication, regardless of the period length. To prevent floating-point drift from accumulating over millions of updates, we perform a full recalculation every 10,000 ticks.
| Streaming update | O(1) | Constant time regardless of period length |
| Bar correction | O(1) | Efficient state rollback for real-time feeds |
| Batch processing | O(n) | SIMD-optimized (AVX2/AVX512/Neon) for high throughput |
| Memory footprint | O(period) | Uses a RingBuffer to store the lookback window |
**Note:** The batch implementation automatically selects the best available SIMD instruction set (AVX512, AVX2, or ARM Neon) for the running hardware, falling back to a scalar implementation if necessary.
## Interpretation
### Trading Signals
#### Trend Identification
- **Uptrend:** Price is consistently above the WMA, and the WMA slope is positive.
- **Downtrend:** Price is consistently below the WMA, and the WMA slope is negative.
#### Crossovers
- **Price Crossover:** Price crossing above the WMA suggests a potential bullish reversal. Price crossing below suggests a bearish reversal.
- **Dual WMA:** Using two WMAs (e.g., 20 and 50). Fast crossing above Slow is a "Golden Cross" (bullish). Fast crossing below Slow is a "Death Cross" (bearish).
### When It Works Best
- **Trending Markets:** WMA excels in clearly defined trends where its reduced lag allows traders to enter and exit positions earlier than with an SMA.
- **Swing Trading:** The linear weighting aligns well with swing trading timeframes, capturing momentum shifts effectively.
### When It Struggles
- **Choppy/Sideways Markets:** Like all moving averages, WMA will generate false signals in range-bound markets.
- **Drop-off Effect:** Because the oldest price drops off the calculation entirely (weight goes from 1 to 0), a large price spike exiting the window can cause the WMA to move counter-intuitively, though less severely than an SMA.
## Architecture Notes
This implementation makes specific trade-offs:
### Choice: Dual Running Sums for O(1)
- **Alternative:** Recalculate weighted sum every bar (O(n)).
- **Trade-off:** Requires maintaining two state variables ($S$ and $W$) and a RingBuffer.
- **Rationale:** Critical for performance in real-time systems monitoring thousands of assets with long periods.
### Choice: Periodic Resync
- **Alternative:** Never resync.
- **Trade-off:** Small CPU cost every 10,000 ticks.
- **Rationale:** Floating-point errors accumulate in running sums. Periodic recalculation ensures long-running server stability.