Standard Deviation (STDDEV)
period = 5 | nbdev = 1 Overview
Standard Deviation measures the dispersion of price values around their mean over a rolling window. The indicator calculates how much individual prices deviate from the average by computing the square root of the average squared difference from the mean. Higher values indicate greater volatility and price dispersion, while lower values suggest prices are clustering tightly around the mean. Traders use standard deviation to gauge market volatility, size position risk appropriately, and identify periods of consolidation versus expansion. The indicator often serves as a core component in volatility based strategies like Bollinger Bands, where it defines the width of price channels. Default period is 5 with an nbdev multiplier of 1.0, matching common volatility measurement conventions in technical analysis.
Implementation Examples
Compute rolling standard deviation from slices or candles:
use vector_ta::indicators::stddev::{stddev, StdDevInput, StdDevParams};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
// From a price slice (defaults: period=5, nbdev=1.0)
let prices = vec![100.0, 102.0, 101.5, 103.0, 105.0, 104.5];
let input = StdDevInput::from_slice(&prices, StdDevParams::default());
let out = stddev(&input)?;
// From candles with defaults (source="close")
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = StdDevInput::with_default_candles(&candles);
let out = stddev(&input)?;
// Access values
for v in out.values { println!("stddev: {}", v); } API Reference
Input Methods ▼
// From price slice
StdDevInput::from_slice(&[f64], StdDevParams) -> StdDevInput
// From candles with custom source
StdDevInput::from_candles(&Candles, &str, StdDevParams) -> StdDevInput
// From candles with default params (close prices, period=5, nbdev=1.0)
StdDevInput::with_default_candles(&Candles) -> StdDevInput Parameters Structure ▼
pub struct StdDevParams {
pub period: Option<usize>, // Default: 5
pub nbdev: Option<f64>, // Default: 1.0 (≥ 0)
} Output Structure ▼
pub struct StdDevOutput {
pub values: Vec<f64>, // Rolling stddev × nbdev
} Validation, Warmup & NaNs ▼
period > 0,nbdev ≥ 0,nbdevmust be finite; elseStdDevError::InvalidPeriod/InvalidNbdev.- Finds first finite input index
first; requires at leastperiodvalid points afterfirstorStdDevError::NotEnoughValidData. - Warmup: indices
< first + period − 1areNaN. First finite output at warmup index. - Constant windows yield
0.0(variance ≤ 0). SubsequentNaNinputs propagate toNaNoutputs. - Population variance is used:
σ² = E[x²] − (E[x])²withE[⋅]over the window (divide byn).
Error Handling ▼
use vector_ta::indicators::stddev::{stddev, StdDevInput, StdDevParams, StdDevError};
match stddev(&StdDevInput::from_slice(&prices, StdDevParams::default())) {
Ok(output) => handle(output.values),
Err(StdDevError::EmptyInputData) => eprintln!("Input is empty"),
Err(StdDevError::AllValuesNaN) => eprintln!("All input values are NaN"),
Err(StdDevError::InvalidPeriod { period, data_len }) =>
eprintln!("Invalid period {} for length {}", period, data_len),
Err(StdDevError::NotEnoughValidData { needed, valid }) =>
eprintln!("Need {} valid points, have {}", needed, valid),
Err(StdDevError::InvalidNbdev { nbdev }) =>
eprintln!("nbdev must be non-negative and finite, got {}", nbdev),
Err(StdDevError::MismatchedOutputLen { dst_len, expected_len }) =>
eprintln!("Output len {} != expected {}", dst_len, expected_len),
Err(StdDevError::InvalidKernel { msg }) =>
eprintln!("Kernel error: {}", msg),
} Python Bindings
Basic Usage ▼
Calculate STDDEV in Python (population variance, nbdev scale):
import numpy as np
from vector_ta import stddev
prices = np.array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5], dtype=np.float64)
values = stddev(prices, period=5, nbdev=1.0, kernel='auto')
print(values) Streaming ▼
from vector_ta import StdDevStream
stream = StdDevStream(period=20, nbdev=2.0)
for p in price_stream:
s = stream.update(p) # None until the window is full
if s is not None:
handle(s) Batch Parameter Sweep ▼
import numpy as np
from vector_ta import stddev_batch
prices = np.asarray(prices, dtype=np.float64)
res = stddev_batch(
prices,
period_range=(5, 30, 5), # 5,10,15,20,25,30
nbdev_range=(1.0, 3.0, 0.5),
kernel='auto'
)
# res is a dict with keys: 'values' [rows x cols], 'periods', 'nbdevs'
values = res['values']
periods = res['periods']
nbdevs = res['nbdevs'] CUDA Acceleration ▼
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 stddev_cuda_batch_dev, stddev_cuda_many_series_one_param_dev
# One series (float32)
data_f32 = np.asarray(load_data(), dtype=np.float32)
dev = stddev_cuda_batch_dev(
data_f32=data_f32,
period_range=(5, 30, 5),
nbdev_range=(0.5, 2.0, 0.5),
device_id=0,
)
# Many series (time-major)
data_tm_f32 = np.asarray(load_data_time_major_matrix(), dtype=np.float32)
rows, cols = data_tm_f32.shape
data_tm_f32 = data_tm_f32.ravel()
dev_tm = stddev_cuda_many_series_one_param_dev(
data_tm_f32=data_tm_f32,
cols=cols,
rows=rows,
period=14,
nbdev=1.0,
device_id=0,
) JavaScript/WASM Bindings
Basic Usage ▼
Calculate STDDEV in JavaScript/TypeScript:
import { stddev_js } from 'vectorta-wasm';
const prices = new Float64Array([100, 102, 101.5, 103, 105, 104.5]);
const values = stddev_js(prices, 20, 2.0);
console.log('STDDEV:', values); Memory-Efficient Operations ▼
Use zero-copy operations with preallocated WASM memory:
import { stddev_alloc, stddev_free, stddev_into, memory } from 'vectorta-wasm';
const prices = new Float64Array([/* your data */]);
const n = prices.length;
const inPtr = stddev_alloc(n);
const outPtr = stddev_alloc(n);
new Float64Array(memory.buffer, inPtr, n).set(prices);
// Args: in_ptr, out_ptr, len, period, nbdev
stddev_into(inPtr, outPtr, n, 20, 2.0);
const out = new Float64Array(memory.buffer, outPtr, n).slice();
stddev_free(inPtr, n);
stddev_free(outPtr, n); Batch Processing ▼
Test parameter sweeps via a unified config:
import { stddev_batch } from 'vectorta-wasm';
const prices = new Float64Array([/* historical prices */]);
const config = {
period_range: [5, 30, 5], // start, end, step
nbdev_range: [1.0, 3.0, 0.5]
};
// Returns a JSON-like object with values (flat), periods, nbdevs, rows, cols
const res = stddev_batch(prices, config);
// reshape if desired based on rows/cols
CUDA Bindings (Rust)
use vector_ta::cuda::CudaStddev;
use vector_ta::indicators::stddev::StdDevBatchRange;
let cuda = CudaStddev::new(0)?;
let data_f32: [f32] = /* ... */;
let sweep = StdDevBatchRange::default();
let out = cuda.stddev_batch_dev(&data_f32, &sweep)?;
let _ = out; Performance Analysis
Across sizes, Rust CPU runs about 1.03× faster than Tulip C in this benchmark.
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-02-28