WMA

This function computes a rolling weighted moving average (WMA) where each window position uses a specified weight.

For window length m and weights w_0,\dots,w_{m-1}, each output value is:

\text{WMA}_t = \frac{\sum_{i=0}^{m-1} w_i x_{t-m+1+i}}{\sum_{i=0}^{m-1} w_i}

The function returns values only for complete windows, beginning at the first index where all weights can be applied.

Excel Usage

=WMA(data, weights)
  • data (list[list], required): Time-series observations as a 2D range (data points).
  • weights (list[list], required): Weight coefficients as a 2D range (relative weights).

Returns (list[list]): Column vector of rolling weighted moving-average values for complete windows.

Example 1: WMA with linearly increasing weights

Inputs:

data weights
1 2 3 4 5 1 2 3

Excel formula:

=WMA({1,2,3,4,5}, {1,2,3})

Expected output:

Result
2.33333
3.33333
4.33333
Example 2: WMA with equal weights matches rolling mean

Inputs:

data weights
2 4 6 8 1 1

Excel formula:

=WMA({2,4,6,8}, {1,1})

Expected output:

Result
3
5
7
Example 3: Single weight returns original series

Inputs:

data weights
7 9 11 5

Excel formula:

=WMA({7,9,11}, {5})

Expected output:

Result
7
9
11
Example 4: Scalar input with scalar weight

Inputs:

data weights
10 1

Excel formula:

=WMA(10, 1)

Expected output:

10

Python Code

import numpy as np

def wma(data, weights):
    """
    Compute a rolling weighted moving average using user-supplied weights.

    See: https://en.wikipedia.org/wiki/Moving_average#Weighted_moving_average

    This example function is provided as-is without any representation of accuracy.

    Args:
        data (list[list]): Time-series observations as a 2D range (data points).
        weights (list[list]): Weight coefficients as a 2D range (relative weights).

    Returns:
        list[list]: Column vector of rolling weighted moving-average values for complete windows.
    """
    try:
        def to2d(x):
            return [[x]] if not isinstance(x, list) else x

        data = to2d(data)
        weights = to2d(weights)

        if not isinstance(data, list) or not all(isinstance(row, list) for row in data):
            return "Error: Invalid input - data must be a 2D list"
        if not isinstance(weights, list) or not all(isinstance(row, list) for row in weights):
            return "Error: Invalid input - weights must be a 2D list"

        series = []
        for row in data:
            for item in row:
                try:
                    series.append(float(item))
                except (TypeError, ValueError):
                    continue

        win = []
        for row in weights:
            for item in row:
                try:
                    win.append(float(item))
                except (TypeError, ValueError):
                    continue

        if not series:
            return "Error: data must contain at least one numeric value"
        if not win:
            return "Error: weights must contain at least one numeric value"

        weight_sum = float(np.sum(win))
        if weight_sum == 0:
            return "Error: weights must sum to a nonzero value"

        window = len(win)
        if len(series) < window:
            return "Error: data length must be at least as large as the number of weights"

        out = []
        for end_idx in range(window - 1, len(series)):
            segment = series[end_idx - window + 1:end_idx + 1]
            val = float(np.dot(segment, win) / weight_sum)
            out.append([val])

        return out
    except Exception as e:
        return f"Error: {str(e)}"

Online Calculator

Time-series observations as a 2D range (data points).
Weight coefficients as a 2D range (relative weights).