Weighted Moving Average (WMA)

Parameters: period = 30

Overview

The Weighted Moving Average (WMA) applies linearly increasing weights to price data across the lookback window, assigning the highest weight to the most recent price and progressively smaller weights to older prices. Each position in the period receives a weight equal to its distance from the start, so in a 30-period WMA, today gets weight 30, yesterday gets 29, and the oldest bar gets weight 1. These weights sum to n(n+1)/2, providing the divisor that normalizes the weighted sum into the final average. This linear weighting scheme makes WMA significantly more responsive to recent price changes than Simple Moving Average while maintaining greater smoothness than pure momentum indicators. The graduated weighting naturally emphasizes current market conditions without completely discarding historical context, striking a practical balance for trend identification. Traders favor WMA when they need quicker reaction to price shifts than SMA provides but want to avoid the exponential weighting assumptions of EMA. The default 30-period setting produces smooth trend lines suitable for intermediate term analysis, with VectorTA optimizations delivering high performance through SIMD acceleration and efficient streaming updates.

Formula: WMAt = \dfrac{\sum_{i=1}^{n} i\,x_{t-n+i}}{n(n+1)/2}, where n = period and the most recent bar has weight n. Default (VectorTA): period = 30.

See also

Interpretation & Use

  • Trend filter: Rising WMA suggests bullish bias; falling WMA suggests bearish bias.
  • Crossovers: Price/WMA cross or multi-WMA stacks can signal momentum shifts.
  • Lag vs responsiveness: Larger period smooths more but lags; smaller reacts faster with more noise.
  • Warmup: First first + period − 1 indices are NaN until the window is fully seeded.

Implementation Examples

Compute WMA from a slice or candles:

use vector_ta::indicators::wma::{wma, WmaInput, WmaParams};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};

// Using with a price slice
let prices = vec![100.0, 102.0, 101.5, 103.0, 105.0, 104.5];
let params = WmaParams { period: Some(30) };
let input = WmaInput::from_slice(&prices, params);
let out = wma(&input)?;

// Using with Candles (default source="close", period=30)
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = WmaInput::from_candles(&candles, "close", WmaParams::default());
let out = wma(&input)?;

for v in out.values { println!("WMA: {}", v); }

API Reference

Input Methods
// From price slice
WmaInput::from_slice(&[f64], WmaParams) -> WmaInput

// From candles with custom source
WmaInput::from_candles(&Candles, &str, WmaParams) -> WmaInput

// With defaults (source="close", period=30)
WmaInput::with_default_candles(&Candles) -> WmaInput
Parameters Structure
pub struct WmaParams {
    pub period: Option<usize>, // Default: 30
}
Output Structure
pub struct WmaOutput {
    pub values: Vec<f64>, // WMA values
}
Validation, Warmup & Errors
  • period > 0 and period ≤ data.len(); else WmaError::InvalidPeriod.
  • All-NaN input → WmaError::AllValuesNaN.
  • Require at least period valid points after first finite; else WmaError::NotEnoughValidData.
  • Warmup: indices [0 .. first+period-2] are NaN; first valid output at first+period-1.

Python CUDA Bindings

CUDA helpers are available when the Python package is built with CUDA support. Inputs must be float32; outputs are device arrays (DLPack / __cuda_array_interface__ compatible).

import numpy as np
from vector_ta import wma_cuda_batch_dev, wma_cuda_many_series_one_param_dev

# One series (float32)
data_f32 = np.asarray(load_prices(), dtype=np.float32)
dev = wma_cuda_batch_dev(data_f32=data_f32, period_range=(5, 50, 5), device_id=0)

# Many series (time-major matrix, float32)
data_tm_f32 = np.asarray(load_time_major_matrix(), dtype=np.float32)  # shape: (rows, cols)
dev_tm = wma_cuda_many_series_one_param_dev(data_tm_f32=data_tm_f32, period=30, device_id=0)

CUDA Bindings (Rust)

use vector_ta::cuda::CudaWma;
use vector_ta::indicators::moving_averages::wma::WmaBatchRange;

let cuda = CudaWma::new(0)?;

let data_f32: [f32] = /* ... */;
let sweep = WmaBatchRange::default();

let out = cuda.wma_batch_dev(&data_f32, &sweep)?;
let _ = out;

Export Code

use vector_ta::indicators::wma;

// Calculate WMA with custom parameters
let result = wma(&data, 30);

// Or using the builder pattern
let result = indicators::wma::new()
    .period(30)
    .calculate(&data);

This code snippet shows how to use the WMA indicator with your current parameter settings.

Performance Analysis

Comparison:
View:

Across sizes, Rust CPU runs about 1.00× faster than Tulip C in this benchmark.

Loading chart...

AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-02-28

Related Indicators