Statistical Trailing Stop
data_length = 10 | normalization_length = 100 | base_level = level2 Overview
Statistical Trailing Stop turns recent high, low, and close behavior into a volatility-aware stop level. The indicator keeps track of the active stop level, the underlying anchor used to place that stop, a bias line that reflects directional state, and a change flag that marks bars where the stop regime flips.
In VectorTA the indicator works directly on high, low, and close slices or on candle collections, supports a streaming state machine for live updates, and exposes batch sweeps across both lookback lengths and the named base-level presets. That makes it useful both for end-of-day stop studies and for live trailing logic that has to react to changing range conditions without rebuilding state on every bar.
Defaults: `data_length = 10`, `normalization_length = 100`, and `base_level = "level2"`.
Implementation Examples
Run the indicator on direct high/low/close slices or on candle data with the default stop profile.
use vector_ta::indicators::statistical_trailing_stop::{
statistical_trailing_stop,
StatisticalTrailingStopInput,
StatisticalTrailingStopParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let direct = statistical_trailing_stop(&StatisticalTrailingStopInput::from_slices(
&high,
&low,
&close,
StatisticalTrailingStopParams {
data_length: Some(10),
normalization_length: Some(100),
base_level: Some("level2".to_string()),
},
))?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let from_candles = statistical_trailing_stop(
&StatisticalTrailingStopInput::with_default_candles(&candles),
)?;
println!("latest level = {:?}", direct.level.last());
println!("latest anchor = {:?}", direct.anchor.last());
println!("latest bias = {:?}", direct.bias.last());
println!("latest changed = {:?}", direct.changed.last());
println!("candle level = {:?}", from_candles.level.last()); API Reference
Input Methods ▼
StatisticalTrailingStopInput::from_candles(&Candles, StatisticalTrailingStopParams)
-> StatisticalTrailingStopInput
StatisticalTrailingStopInput::from_slices(&[f64], &[f64], &[f64], StatisticalTrailingStopParams)
-> StatisticalTrailingStopInput
StatisticalTrailingStopInput::with_default_candles(&Candles)
-> StatisticalTrailingStopInput Parameters Structure ▼
pub struct StatisticalTrailingStopParams {
pub data_length: Option<usize>, // default 10
pub normalization_length: Option<usize>, // default 100
pub base_level: Option<String>, // default "level2"
} Output Structure ▼
pub struct StatisticalTrailingStopOutput {
pub level: Vec<f64>,
pub anchor: Vec<f64>,
pub bias: Vec<f64>,
pub changed: Vec<f64>,
} Validation, Base Levels & NaNs ▼
high,low, andclosemust have matching lengths and contain at least one finite region.- The resolved periods must satisfy the indicator validation rules, including
data_length + normalization_length + 1 <= data_len. base_levelmust resolve to one oflevel0,level1,level2, orlevel3.- Direct and candle paths reject empty or all-NaN input and return the documented period, level, or output-length errors when validation fails.
- The stream path resets itself when a non-finite bar arrives and returns
Noneuntil enough valid data accumulates again. - Batch mode validates all sweep axes and rejects non-batch kernels.
Builder, Streaming & Batch APIs ▼
StatisticalTrailingStopBuilder::new()
.data_length(usize)
.normalization_length(usize)
.base_level("level2")
.kernel(Kernel)
.apply(&Candles)
.apply_slices(&[f64], &[f64], &[f64])
.into_stream()
StatisticalTrailingStopStream::try_new(params)
stream.update(high, low, close) -> Option<(f64, f64, f64, f64)>
StatisticalTrailingStopBatchBuilder::new()
.data_length_range(start, end, step)
.normalization_length_range(start, end, step)
.base_level_range("level1", "level3", step)
.kernel(Kernel)
.apply(&Candles)
.apply_slices(&[f64], &[f64], &[f64]) Python Bindings
Python exposes a direct function, a stream class, and a batch helper that returns the four output matrices plus the resolved sweep axes.
from vector_ta import (
statistical_trailing_stop,
statistical_trailing_stop_batch,
StatisticalTrailingStopStream,
)
level, anchor, bias, changed = statistical_trailing_stop(
high,
low,
close,
data_length=10,
normalization_length=100,
base_level="level2",
)
stream = StatisticalTrailingStopStream(
data_length=10,
normalization_length=100,
base_level="level2",
)
point = stream.update(high[-1], low[-1], close[-1])
batch = statistical_trailing_stop_batch(
high,
low,
close,
data_length_range=(8, 14, 2),
normalization_length_range=(80, 120, 20),
base_level_range=("level1", "level3", 1),
)
print(batch["level"].shape)
print(batch["base_levels"]) JavaScript/WASM Bindings
The WASM layer exposes a high-level object-returning call, an explicit batch entry point, and low-level allocation and into-buffer APIs for caller-managed memory.
import init, {
statistical_trailing_stop_js,
statistical_trailing_stop_batch,
statistical_trailing_stop_alloc,
statistical_trailing_stop_free,
statistical_trailing_stop_into,
statistical_trailing_stop_batch_into,
} from "vector-ta-wasm";
await init();
const single = statistical_trailing_stop_js(high, low, close, 10, 100, "level2");
console.log(single.level, single.anchor, single.bias, single.changed);
const batch = statistical_trailing_stop_batch(high, low, close, {
data_length_range: [8, 14, 2],
normalization_length_range: [80, 120, 20],
base_level_range: ["level1", "level3", 1],
});
const ptrHigh = statistical_trailing_stop_alloc(high.length);
const ptrLow = statistical_trailing_stop_alloc(low.length);
const ptrClose = statistical_trailing_stop_alloc(close.length);
const ptrLevel = statistical_trailing_stop_alloc(close.length);
const ptrAnchor = statistical_trailing_stop_alloc(close.length);
const ptrBias = statistical_trailing_stop_alloc(close.length);
const ptrChanged = statistical_trailing_stop_alloc(close.length);
statistical_trailing_stop_into(
ptrHigh,
ptrLow,
ptrClose,
ptrLevel,
ptrAnchor,
ptrBias,
ptrChanged,
close.length,
10,
100,
"level2",
);
statistical_trailing_stop_free(ptrHigh, high.length);
statistical_trailing_stop_free(ptrLow, low.length);
statistical_trailing_stop_free(ptrClose, close.length); 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
Average Directional Index
Technical analysis indicator
Average Directional Movement Index Rating
Technical analysis indicator
Alligator
Technical analysis indicator
Aroon
Technical analysis indicator
Aroon Oscillator
Technical analysis indicator
Chande Momentum Oscillator
Technical analysis indicator