Garman-Klass Volatility
lookback = 14 Overview
Garman-Klass Volatility is a realized-volatility estimator that uses the full OHLC bar instead of relying only on closing returns. The core variance term combines the logarithmic high-low range with the open-to-close move, then averages those terms across a rolling window before taking the square root. That gives a smoother estimate of recent volatility while still responding to bars that expand intraday range.
In VectorTA, the indicator works on complete OHLC candles and expects all four fields to stay finite and positive. The batch API sweeps multiple lookbacks, and the streaming API maintains the same rolling estimator online with O(1) updates once the warmup window has filled.
Defaults: Garman-Klass Volatility uses `lookback = 14`.
Implementation Examples
Compute the rolling Garman-Klass volatility series from OHLC slices or candle data.
use vector_ta::indicators::garman_klass_volatility::{
garman_klass_volatility,
GarmanKlassVolatilityInput,
GarmanKlassVolatilityParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let open = vec![100.0, 101.0, 100.8, 102.3, 101.9, 103.1];
let high = vec![101.2, 102.4, 101.9, 103.5, 103.0, 104.2];
let low = vec![99.5, 100.2, 99.9, 101.4, 101.0, 102.5];
let close = vec![100.7, 101.9, 101.1, 102.8, 102.4, 103.9];
let output = garman_klass_volatility(&GarmanKlassVolatilityInput::from_slices(
&open,
&high,
&low,
&close,
GarmanKlassVolatilityParams { lookback: Some(14) },
))?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_output = garman_klass_volatility(
&GarmanKlassVolatilityInput::with_default_candles(&candles),
)?;
println!("latest volatility = {:?}", output.values.last());
println!("series length = {}", candle_output.values.len()); API Reference
Input Methods ▼
// From candles
GarmanKlassVolatilityInput::from_candles(&Candles, GarmanKlassVolatilityParams)
-> GarmanKlassVolatilityInput
// From OHLC slices
GarmanKlassVolatilityInput::from_slices(&[f64], &[f64], &[f64], &[f64], GarmanKlassVolatilityParams)
-> GarmanKlassVolatilityInput
// From candles with default parameters
GarmanKlassVolatilityInput::with_default_candles(&Candles)
-> GarmanKlassVolatilityInput Parameters Structure ▼
pub struct GarmanKlassVolatilityParams {
pub lookback: Option<usize>, // default 14
} Output Structure ▼
pub struct GarmanKlassVolatilityOutput {
pub values: Vec<f64>,
} Validation, Warmup & NaNs ▼
- All OHLC inputs must be non-empty and have matching lengths.
- Every valid bar must have finite, strictly positive
open,high,low, andclosevalues. lookbackmust be greater than0and must not exceed the available series length.- The indicator requires at least
lookbackvalid OHLC bars; otherwise it returnsNotEnoughValidData. - One-shot output is NaN-prefixed until the first full valid rolling window has been observed.
- Streaming returns
Noneuntil the window is fully populated with valid bars, and invalid bars break the all-valid requirement for the current window. - Batch mode validates sweep ranges and rejects non-batch kernels through
InvalidKernelForBatch.
Builder, Streaming & Batch APIs ▼
// Builder
GarmanKlassVolatilityBuilder::new()
.lookback(usize)
.kernel(Kernel)
.apply(&Candles)
GarmanKlassVolatilityBuilder::new()
.apply_slices(&[f64], &[f64], &[f64], &[f64])
GarmanKlassVolatilityBuilder::new()
.into_stream()
// Stream
GarmanKlassVolatilityStream::try_new(GarmanKlassVolatilityParams)
GarmanKlassVolatilityStream::update(f64, f64, f64, f64) -> Option<f64>
GarmanKlassVolatilityStream::get_warmup_period() -> usize
// Batch
GarmanKlassVolatilityBatchBuilder::new()
.kernel(Kernel)
.lookback_range(start, end, step)
.lookback_static(value)
.apply_slices(&[f64], &[f64], &[f64], &[f64])
GarmanKlassVolatilityBatchBuilder::new()
.apply_candles(&Candles)
GarmanKlassVolatilityBatchBuilder::with_default_candles(&Candles) Error Handling ▼
pub enum GarmanKlassVolatilityError {
EmptyInputData,
AllValuesNaN,
InvalidLookback { lookback: usize, data_len: usize },
NotEnoughValidData { needed: usize, valid: usize },
InconsistentSliceLengths {
open_len: usize,
high_len: usize,
low_len: usize,
close_len: usize,
},
OutputLengthMismatch { expected: usize, got: usize },
InvalidRange { start: String, end: String, step: String },
InvalidKernelForBatch(Kernel),
} Python Bindings
Python exposes a scalar OHLC function, a streaming class, and a batch sweep. The scalar path returns one NumPy volatility array. Streaming returns one floating-point volatility estimate or `None`, while batch returns the flattened volatility matrix together with the tested lookback values and output dimensions.
import numpy as np
from vector_ta import (
garman_klass_volatility,
garman_klass_volatility_batch,
GarmanKlassVolatilityStream,
)
open_ = np.asarray(open_values, dtype=np.float64)
high = np.asarray(high_values, dtype=np.float64)
low = np.asarray(low_values, dtype=np.float64)
close = np.asarray(close_values, dtype=np.float64)
values = garman_klass_volatility(
open_,
high,
low,
close,
lookback=14,
kernel="auto",
)
stream = GarmanKlassVolatilityStream(lookback=14)
print(stream.update(open_[-1], high[-1], low[-1], close[-1]))
batch = garman_klass_volatility_batch(
open_,
high,
low,
close,
lookback_range=(10, 30, 10),
kernel="auto",
)
print(batch["values"].shape)
print(batch["lookbacks"])
print(batch["rows"], batch["cols"]) JavaScript/WASM Bindings
The WASM surface includes a direct array-returning function, a batch function, and raw allocation and into-buffer helpers for preallocated memory workflows. The scalar binding returns a single volatility array. The batch binding returns the flattened values matrix plus the tested parameter combinations and output dimensions.
import init, {
garman_klass_volatility_js,
garman_klass_volatility_batch_js,
} from "@vectoralpha/vector_ta";
await init();
const values = garman_klass_volatility_js(open, high, low, close, 14);
console.log(values);
const batch = garman_klass_volatility_batch_js(open, high, low, close, {
lookback_range: [10, 30, 10],
});
console.log(batch.values);
console.log(batch.combos);
console.log(batch.rows, batch.cols); CUDA Bindings (Rust)
Additional details for the CUDA bindings can be found inside the VectorTA repository.
Performance Analysis
Across sizes, Rust CPU runs about 1.14× faster than Tulip C in this benchmark.
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU)