Normalized Volume True Range
true_range_style = body | outlier_range = 5 | atr_length = 14 | volume_length = 14 Overview
Normalized Volume True Range measures how unusual the current bar is by comparing its volume and true range with rolling baselines. The true-range component can be based on candle body size, full high-low span, or close-to-close delta, and the volume side is normalized against a rolling average and positive deviation estimate.
The output includes normalized volume, normalized true range, a combined baseline, and the underlying ATR and average-volume series that support the normalization. It accepts candles or aligned OHLCV slices, and the stream version returns five values for each update while exposing a full reset path.
Defaults: `true_range_style = "body"`, `outlier_range = 5.0`, `atr_length = 14`, and `volume_length = 14`.
Implementation Examples
Run the indicator on candles or on aligned OHLCV slices.
use vector_ta::indicators::normalized_volume_true_range::{
normalized_volume_true_range,
NormalizedVolumeTrueRangeInput,
NormalizedVolumeTrueRangeParams,
NormalizedVolumeTrueRangeStyle,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let output = normalized_volume_true_range(&NormalizedVolumeTrueRangeInput::from_slices(
&open,
&high,
&low,
&close,
&volume,
NormalizedVolumeTrueRangeParams {
true_range_style: Some(NormalizedVolumeTrueRangeStyle::Body),
outlier_range: Some(5.0),
atr_length: Some(14),
volume_length: Some(14),
},
))?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_output = normalized_volume_true_range(
&NormalizedVolumeTrueRangeInput::with_default_candles(&candles),
)?;
println!("normalized volume = {:?}", output.normalized_volume.last());
println!("baseline = {:?}", candle_output.baseline.last()); API Reference
Input Methods ▼
NormalizedVolumeTrueRangeInput::from_candles(&Candles, NormalizedVolumeTrueRangeParams)
-> NormalizedVolumeTrueRangeInput
NormalizedVolumeTrueRangeInput::from_slices(
&[f64], &[f64], &[f64], &[f64], &[f64],
NormalizedVolumeTrueRangeParams,
) -> NormalizedVolumeTrueRangeInput
NormalizedVolumeTrueRangeInput::with_default_candles(&Candles)
-> NormalizedVolumeTrueRangeInput Parameters Structure ▼
pub enum NormalizedVolumeTrueRangeStyle {
Body,
Hl,
Delta,
}
pub struct NormalizedVolumeTrueRangeParams {
pub true_range_style: Option<NormalizedVolumeTrueRangeStyle>, // default Body
pub outlier_range: Option<f64>, // default 5.0
pub atr_length: Option<usize>, // default 14
pub volume_length: Option<usize>, // default 14
} Output Structure ▼
pub struct NormalizedVolumeTrueRangeOutput {
pub normalized_volume: Vec<f64>,
pub normalized_true_range: Vec<f64>,
pub baseline: Vec<f64>,
pub atr: Vec<f64>,
pub average_volume: Vec<f64>,
} Validation, Warmup & Data Rules ▼
- Open, high, low, close, and volume inputs must have matching lengths and must not be empty.
- At least one full OHLCV row must be finite; otherwise the indicator returns
AllValuesNaN. outlier_rangemust be finite and at least0.5.atr_lengthandvolume_lengthmust each be at least2.- The accepted styles are
body,hl, anddelta. - Batch mode validates the sweep tuples for ATR and volume lengths and rejects unsupported kernels.
- The streaming implementation reuses the same validated parameters and exposes
reset()for a clean restart.
Builder, Streaming & Batch APIs ▼
NormalizedVolumeTrueRangeBuilder::new()
.true_range_style(NormalizedVolumeTrueRangeStyle)
.outlier_range(f64)
.atr_length(usize)
.volume_length(usize)
.kernel(Kernel)
.apply(&Candles)
.apply_slices(&open, &high, &low, &close, &volume)
.into_stream()
NormalizedVolumeTrueRangeStream::try_new(params)
stream.update(open, high, low, close, volume)
-> Option<(f64, f64, f64, f64, f64)>
stream.reset()
NormalizedVolumeTrueRangeBatchBuilder::new()
.outlier_range_range(start, end, step)
.atr_length_range(start, end, step)
.volume_length_range(start, end, step)
.true_range_style(NormalizedVolumeTrueRangeStyle)
.kernel(Kernel)
.apply_slices(&open, &high, &low, &close, &volume)
.apply(&Candles) Python Bindings
Python exposes a scalar OHLCV function, a stream class, and a batch helper. The scalar call returns five NumPy
arrays, the stream yields five scalars or None, and the batch helper returns reshaped matrices along
with the swept outlier, ATR, volume, and style metadata.
from vector_ta import (
normalized_volume_true_range,
normalized_volume_true_range_batch,
NormalizedVolumeTrueRangeStream,
)
normalized_volume, normalized_true_range, baseline, atr, average_volume = (
normalized_volume_true_range(
open,
high,
low,
close,
volume,
true_range_style="body",
outlier_range=5.0,
atr_length=14,
volume_length=14,
)
)
stream = NormalizedVolumeTrueRangeStream("body", 5.0, 14, 14)
point = stream.update(open[-1], high[-1], low[-1], close[-1], volume[-1])
batch = normalized_volume_true_range_batch(
open,
high,
low,
close,
volume,
outlier_range_range=(4.0, 6.0, 1.0),
atr_length_range=(10, 20, 5),
volume_length_range=(10, 20, 5),
true_range_style="body",
)
print(batch.keys())
# dict_keys(['normalized_volume', 'normalized_true_range', 'baseline', 'atr',
# 'average_volume', 'outlier_ranges', 'atr_lengths',
# 'volume_lengths', 'true_range_styles', 'rows', 'cols']) JavaScript/WASM Bindings
The WASM layer includes high-level scalar and batch entry points, low-level allocation helpers, and into-buffer exports for reusing caller memory. The high-level calls return plain JS objects, and the low-level functions write five output arrays into caller-managed memory.
import init, {
normalized_volume_true_range_js,
normalized_volume_true_range_batch,
normalized_volume_true_range_alloc,
normalized_volume_true_range_free,
normalized_volume_true_range_into,
normalized_volume_true_range_batch_into,
} from "vector-ta-wasm";
await init();
const out = normalized_volume_true_range_js(
open,
high,
low,
close,
volume,
"body",
5.0,
14,
14,
);
const batch = normalized_volume_true_range_batch(open, high, low, close, volume, {
true_range_style: "body",
outlier_range_range: [4.0, 6.0, 1.0],
atr_length_range: [10, 20, 5],
volume_length_range: [10, 20, 5],
}); 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)
Related Indicators
Accumulation/Distribution
Technical analysis indicator
Accumulation/Distribution Oscillator
Technical analysis indicator
Balance of Power
Technical analysis indicator
Chaikin Flow Oscillator
Technical analysis indicator
Elder Force Index
Technical analysis indicator
Ease of Movement
Technical analysis indicator