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 vectorta::indicators::stddev::{stddev, StdDevInput, StdDevParams};
use vectorta::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 vectorta::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 vectorta 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 vectorta 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 vectorta 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 support for STDDEV is currently under development. The API will follow the same pattern as other CUDA-enabled indicators.
# Coming soon: CUDA-accelerated STDDEV calculations
# from vectorta import stddev_cuda_batch, stddev_cuda_many_series_one_param
# ... 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
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-01-05