Variable Power Weighted Moving Average (VPWMA)
period = 14 | power = 0.382 Overview
The Variable Power Weighted Moving Average employs an exponential weighting scheme where each past price point receives a weight calculated as the distance from the current period raised to a configurable power. This approach creates a moving average that can be fine-tuned between aggressive responsiveness and stable smoothing by adjusting the power parameter. Lower power values near zero distribute weights more evenly across the lookback period, producing behavior similar to a simple moving average, while higher powers concentrate weight on the most recent prices for faster reaction to changes. The default power of 0.382, derived from Fibonacci ratios, provides a balanced compromise between noise reduction and trend following. Unlike volume-weighted averages that depend on trading activity, VPWMA purely focuses on temporal relationships, making it effective across all market conditions including low volume periods. The indicator excels in trending markets where its adjustable responsiveness allows traders to match the averaging behavior to the prevailing market speed. By experimenting with different power values, traders can optimize the balance between capturing genuine price moves and filtering out market noise.
Defaults: period=14, power=0.382.
Implementation Examples
Get started with VPWMA in a few lines:
use vectorta::indicators::vpwma::{vpwma, VpwmaInput, VpwmaParams};
use vectorta::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 = VpwmaParams { period: Some(14), power: Some(0.382) };
let input = VpwmaInput::from_slice(&prices, params);
let result = vpwma(&input)?;
// Using with Candles (defaults: period=14, power=0.382; source="close")
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = VpwmaInput::with_default_candles(&candles);
let result = vpwma(&input)?;
// Access the values
for value in result.values {
println!("VPWMA: {}", value);
} API Reference
Input Methods ▼
// From price slice
VpwmaInput::from_slice(&[f64], VpwmaParams) -> VpwmaInput
// From candles with custom source
VpwmaInput::from_candles(&Candles, &str, VpwmaParams) -> VpwmaInput
// From candles with defaults (close, period=14, power=0.382)
VpwmaInput::with_default_candles(&Candles) -> VpwmaInput Parameters Structure ▼
pub struct VpwmaParams {
pub period: Option<usize>, // Default: 14
pub power: Option<f64>, // Default: 0.382
} Output Structure ▼
pub struct VpwmaOutput {
pub values: Vec<f64>, // VPWMA values
} Validation, Warmup & NaNs ▼
period \u2265 2; errorVpwmaError::InvalidPeriodifperiod < 2or exceeds data length.- Must have at least
periodvalid points after the first finite input; elseVpwmaError::NotEnoughValidData. powermust be finite (not NaN/inf); otherwiseVpwmaError::InvalidPower.- Warmup: indices
[0 .. first + period - 2]areNaN; first valid output atfirst + period - 1. - Streaming: returns
Noneuntil the buffer fills; subsequentNaNinputs propagate to outputs. - Batch: passing a non-batch kernel yields
VpwmaError::InvalidBatchKernel.
Error Handling ▼
use vectorta::indicators::vpwma::{vpwma, VpwmaError};
match vpwma(&input) {
Ok(output) => process(output.values),
Err(VpwmaError::EmptyInputData) => eprintln!("empty input"),
Err(VpwmaError::AllValuesNaN) => eprintln!("all values are NaN"),
Err(VpwmaError::InvalidPeriod { period, data_len }) => {
eprintln!("invalid period: {} for len {}", period, data_len)
}
Err(VpwmaError::NotEnoughValidData { needed, valid }) => {
eprintln!("need {}, have {}", needed, valid)
}
Err(VpwmaError::InvalidPower { power }) => eprintln!("invalid power: {}", power),
Err(VpwmaError::InvalidOutLen { out_len, data_len }) => {
eprintln!("out length {} != {}", out_len, data_len)
}
Err(VpwmaError::InvalidBatchKernel { kernel }) => {
eprintln!("invalid batch kernel: {:?}", kernel)
}
} Python Bindings ▼
Single series, streaming, and batch are available:
import numpy as np
from vectorta import vpwma, VpwmaStream, vpwma_batch
# Single series
prices = np.array([...], dtype=np.float64)
values = vpwma(prices, period=14, power=0.382, kernel="auto")
# Streaming
stream = VpwmaStream(period=14, power=0.382)
out = [stream.update(x) for x in prices] # None until warmup is met
# Batch sweep
results = vpwma_batch(
prices,
period_range=(5, 20, 5),
power_range=(0.2, 1.0, 0.2),
kernel="auto",
)
print(results["values"].shape) # (num_combinations, len(prices))
print(results["periods"])
print(results["powers"]) CUDA Acceleration ▼
CUDA APIs are available for VPWMA:
import numpy as np
from vectorta import (
vpwma_cuda_batch_dev,
vpwma_cuda_many_series_one_param_dev,
)
# One series, many parameter combos (device float32)
prices = np.array([...], dtype=np.float32)
out_dev, meta = vpwma_cuda_batch_dev(
prices,
period_range=(5, 20, 5),
power_range=(0.2, 1.0, 0.2),
device_id=0,
)
# Many series (time-major), one parameter set
data_tm = np.array([...], dtype=np.float32) # shape: [T, N]
dev_arr = vpwma_cuda_many_series_one_param_dev(
data_tm, period=14, power=0.382, device_id=0
) JavaScript/WASM Bindings
Basic Usage ▼
Calculate VPWMA in JavaScript/TypeScript:
import { vpwma_js } from 'vectorta-wasm';
const prices = new Float64Array([100, 102, 101.5, 103, 105, 104.5]);
const out = vpwma_js(prices, 14, 0.382);
console.log('VPWMA:', out); Memory-Efficient Operations ▼
Use zero-copy operations with manual buffers:
import { vpwma_alloc, vpwma_free, vpwma_into, memory } from 'vectorta-wasm';
const prices = new Float64Array([/* your data */]);
const n = prices.length;
const inPtr = vpwma_alloc(n);
const outPtr = vpwma_alloc(n);
new Float64Array(memory.buffer, inPtr, n).set(prices);
vpwma_into(inPtr, outPtr, n, 14, 0.382);
const out = new Float64Array(memory.buffer, outPtr, n).slice();
vpwma_free(inPtr, n);
vpwma_free(outPtr, n); Batch Processing ▼
Test multiple (period, power) combinations efficiently:
import { vpwma_batch_js, vpwma_batch_metadata_js } from 'vectorta-wasm';
const prices = new Float64Array([/* data */]);
const pStart=5, pEnd=20, pStep=5;
const pwStart=0.2, pwEnd=1.0, pwStep=0.2;
const meta = vpwma_batch_metadata_js(pStart, pEnd, pStep, pwStart, pwEnd, pwStep);
const combos = meta.length / 2;
const flat = vpwma_batch_js(prices, pStart, pEnd, pStep, pwStart, pwEnd, pwStep);
const rows = combos, cols = prices.length;
const matrix: number[][] = [];
for (let r = 0; r < rows; r++) {
const start = r * cols;
matrix.push(Array.from(flat.slice(start, start + cols)));
} Performance Analysis
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05
Related Indicators
Arnaud Legoux Moving Average
Moving average indicator
Compound Ratio Moving Average (CoRa Wave)
Moving average indicator
Centered Weighted Moving Average
Moving average indicator
Double Exponential Moving Average
Moving average indicator
Ehlers Distance Coefficient Filter
Moving average indicator
Ehlers Error-Correcting EMA (ECEMA)
Moving average indicator