SMA_CONV

This function smooths a time series by applying a simple moving-average kernel through discrete convolution.

For a window length w, the uniform kernel assigns equal weight 1/w to each value in the window. The smoothed value at index t is:

\text{SMA}_t = \frac{1}{w}\sum_{i=0}^{w-1} x_{t-i}

Different convolution modes control output length and boundary behavior.

Excel Usage

=SMA_CONV(data, window, mode)
  • data (list[list], required): Time-series observations as a 2D range (data points).
  • window (int, optional, default: 3): Number of observations per averaging window (points).
  • mode (str, optional, default: “valid”): Convolution output mode controlling boundary handling and output length.

Returns (list[list]): Column vector of simple moving-average values computed from the input series.

Example 1: Valid-mode SMA on increasing series

Inputs:

data window mode
1 2 3 4 5 3 valid

Excel formula:

=SMA_CONV({1,2,3,4,5}, 3, "valid")

Expected output:

Result
2
3
4
Example 2: Same-mode SMA preserves series length

Inputs:

data window mode
10 12 14 16 2 same

Excel formula:

=SMA_CONV({10,12,14,16}, 2, "same")

Expected output:

Result
5
11
13
15
Example 3: Full-mode SMA includes boundary overlap

Inputs:

data window mode
3 6 9 2 full

Excel formula:

=SMA_CONV({3,6,9}, 2, "full")

Expected output:

Result
1.5
4.5
7.5
4.5
Example 4: Scalar input is normalized to 2D range

Inputs:

data window mode
8 1 valid

Excel formula:

=SMA_CONV(8, 1, "valid")

Expected output:

8

Python Code

import numpy as np

def sma_conv(data, window=3, mode='valid'):
    """
    Compute a simple moving average using discrete convolution with a uniform window.

    See: https://numpy.org/doc/stable/reference/generated/numpy.convolve.html

    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).
        window (int, optional): Number of observations per averaging window (points). Default is 3.
        mode (str, optional): Convolution output mode controlling boundary handling and output length. Valid options: Full, Same, Valid. Default is 'valid'.

    Returns:
        list[list]: Column vector of simple moving-average values computed from the input series.
    """
    try:
        def to2d(x):
            return [[x]] if not isinstance(x, list) else x

        data = to2d(data)

        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 mode not in ("full", "same", "valid"):
            return "Error: mode must be one of 'full', 'same', or 'valid'"

        if window < 1:
            return "Error: window must be at least 1"

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

        if not values:
            return "Error: data must contain at least one numeric value"

        if mode == "valid" and len(values) < window:
            return "Error: data length must be at least as large as window for valid mode"

        kernel = np.ones(int(window), dtype=float) / float(window)
        result = np.convolve(np.asarray(values, dtype=float), kernel, mode=mode)
        return [[float(x)] for x in np.asarray(result, dtype=float).tolist()]
    except Exception as e:
        return f"Error: {str(e)}"

Online Calculator

Time-series observations as a 2D range (data points).
Number of observations per averaging window (points).
Convolution output mode controlling boundary handling and output length.