ATR Percentile
atr_length = 10 | percentile_length = 50 Overview
ATR Percentile answers a different volatility question than raw ATR. Instead of only reporting the current average true range, it compares that ATR reading to a rolling history of previous ATR values and expresses the result as a percentile-style rank. A high reading means current range expansion is large relative to recent history, while a low reading means the market is comparatively quiet even if the absolute ATR value is not near zero.
VectorTA computes true range from high, low, and close, averages it over the ATR window, and then counts how many values inside the ranking window sit below the current ATR. That makes the output useful when you want to normalize volatility across instruments or regimes instead of comparing raw ATR values directly. The indicator needs both the ATR window and the ranking window to be filled before it can emit stable values, so the early bars should be treated as warmup.
Defaults: ATR Percentile uses `atr_length = 10` and `percentile_length = 50`.
Implementation Examples
Compute ATR Percentile from high/low/close slices or from candle data.
use vector_ta::indicators::atr_percentile::{
atr_percentile_with_kernel,
AtrPercentileInput,
AtrPercentileParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
use vector_ta::utilities::enums::Kernel;
let high = vec![101.2, 102.0, 103.4, 102.7, 104.1, 105.0];
let low = vec![99.8, 100.6, 101.5, 101.0, 102.9, 103.6];
let close = vec![100.9, 101.4, 102.8, 101.8, 103.7, 104.4];
let params = AtrPercentileParams {
atr_length: Some(10),
percentile_length: Some(50),
};
let output = atr_percentile_with_kernel(
&AtrPercentileInput::from_slices(&high, &low, &close, params),
Kernel::Auto,
)?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_output = atr_percentile_with_kernel(
&AtrPercentileInput::with_default_candles(&candles),
Kernel::Auto,
)?;
println!("Latest ATR percentile: {:?}", output.values.last());
println!("Candle output length: {}", candle_output.values.len()); API Reference
Input Methods ▼
// From candles
AtrPercentileInput::from_candles(&Candles, AtrPercentileParams) -> AtrPercentileInput
// From high/low/close slices
AtrPercentileInput::from_slices(&[f64], &[f64], &[f64], AtrPercentileParams) -> AtrPercentileInput
// From candles with default parameters
AtrPercentileInput::with_default_candles(&Candles) -> AtrPercentileInput Parameters ▼
atr_length: lookback used to average true range values. Must be greater than zero.percentile_length: number of ATR observations used to rank the current ATR. Must be greater than zero.
Core Functions ▼
atr_percentile_with_kernel(&AtrPercentileInput, Kernel) -> Result<AtrPercentileOutput, AtrPercentileError>
atr_percentile_into(&AtrPercentileInput, &mut [f64]) -> Result<(), AtrPercentileError>
atr_percentile_into_slice(&mut [f64], &AtrPercentileInput, Kernel) -> Result<(), AtrPercentileError> Output Fields ▼
values: percentile-style volatility rank from 0 to 100 for each bar after warmup.
Streaming and Batch APIs ▼
// Streaming
AtrPercentileStream::try_new(AtrPercentileParams) -> Result<AtrPercentileStream, AtrPercentileError>
stream.update(high, low, close) -> Option<f64>
// Batch
AtrPercentileBatchBuilder::new()
.atr_length_range(start, end, step)
.percentile_length_range(start, end, step)
.kernel(Kernel)
.apply_slices(&[f64], &[f64], &[f64])
atr_percentile_batch_with_kernel(&[f64], &[f64], &[f64], &AtrPercentileBatchRange, Kernel) -> Result<AtrPercentileBatchOutput, AtrPercentileError> Validation Notes ▼
- High, low, and close must be non-empty, equal-length slices with at least one finite bar.
- The indicator rejects zero-length ATR or percentile windows.
- It also checks that enough valid bars exist to fill both windows before producing stable output.
- Batch mode validates both parameter ranges and only accepts batch-capable kernels.
Python Bindings
Python exposes the single-run function, the batch helper, and a streaming class. The single-run function returns a NumPy array of percentile values, the batch helper returns a 2D values matrix plus the swept parameter grids, and the stream class yields an optional percentile reading one bar at a time.
from vector_ta import atr_percentile, atr_percentile_batch, AtrPercentileStream
values = atr_percentile(
high,
low,
close,
atr_length=10,
percentile_length=50,
kernel="auto",
)
batch = atr_percentile_batch(
high,
low,
close,
atr_length_range=(10, 20, 5),
percentile_length_range=(50, 100, 25),
kernel="auto",
)
stream = AtrPercentileStream(atr_length=10, percentile_length=50)
for h, l, c in live_bars:
value = stream.update(h, l, c) JavaScript/WASM Bindings
The WASM surface exposes a direct array-returning function, pointer-based in-place helpers, and a batch entry point. For ordinary docs usage the direct function and the config-based batch helper are the most convenient, while the alloc/into/free functions exist for host-managed buffers.
import init, {
atr_percentile_js,
atr_percentile_batch_js,
} from "vector-ta-wasm";
await init();
const values = atr_percentile_js(high, low, close, 10, 50);
console.log(values.at(-1));
const batch = atr_percentile_batch_js(high, low, close, {
atr_length_range: [10, 20, 5],
percentile_length_range: [50, 100, 25],
});
console.log(batch.rows, batch.cols, batch.atr_lengths, batch.percentile_lengths); 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)