Neighboring Trailing Stop
buffer_size = 200 | k = 50 | percentile = 90 | smooth = 5 Overview
Neighboring Trailing Stop maintains a sorted rolling buffer of recent closes, looks outward from the current close, and estimates nearby bullish and bearish bands from percentile samples of that local neighborhood. Those candidate bands are then smoothed separately and used to decide when directional discovery occurs.
The indicator returns a trailing stop, smoothed bullish and bearish bands, a directional state, and two discovery flags showing whether the latest update discovered a new bullish or bearish condition. Once direction flips, the trailing stop resets to the opposing band or the current bar extreme, then ratchets in the active direction.
Defaults: `buffer_size = 200`, `k = 50`, `percentile = 90.0`, and `smooth = 5`.
Implementation Examples
Run the indicator on candle highs, lows, and closes or on aligned slices.
use vector_ta::indicators::neighboring_trailing_stop::{
neighboring_trailing_stop,
NeighboringTrailingStopInput,
NeighboringTrailingStopParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let output = neighboring_trailing_stop(&NeighboringTrailingStopInput::from_slices(
&high,
&low,
&close,
NeighboringTrailingStopParams {
buffer_size: Some(200),
k: Some(50),
percentile: Some(90.0),
smooth: Some(5),
},
))?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_output = neighboring_trailing_stop(
&NeighboringTrailingStopInput::with_default_candles(&candles),
)?;
println!("trailing stop = {:?}", output.trailing_stop.last());
println!("direction = {:?}", candle_output.direction.last());
println!("discovery bull = {:?}", candle_output.discovery_bull.last()); API Reference
Input Methods ▼
// From candles
NeighboringTrailingStopInput::from_candles(&Candles, NeighboringTrailingStopParams)
-> NeighboringTrailingStopInput
// From aligned high/low/close slices
NeighboringTrailingStopInput::from_slices(&[f64], &[f64], &[f64], NeighboringTrailingStopParams)
-> NeighboringTrailingStopInput
// From candles with default parameters
NeighboringTrailingStopInput::with_default_candles(&Candles)
-> NeighboringTrailingStopInput Parameters Structure ▼
pub struct NeighboringTrailingStopParams {
pub buffer_size: Option<usize>, // default 200
pub k: Option<usize>, // default 50
pub percentile: Option<f64>, // default 90.0
pub smooth: Option<usize>, // default 5
} Output Structure ▼
pub struct NeighboringTrailingStopOutput {
pub trailing_stop: Vec<f64>,
pub bullish_band: Vec<f64>,
pub bearish_band: Vec<f64>,
pub direction: Vec<f64>,
pub discovery_bull: Vec<f64>,
pub discovery_bear: Vec<f64>,
} Validation, Warmup & NaNs ▼
- The high, low, and close inputs must be non-empty and have matching lengths.
buffer_sizemust be at least100.kmust be at least5.percentilemust be finite and stay within1.0..=99.0.smoothmust be greater than0.- All-nonfinite input is rejected up front, and any non-finite bar resets the stream state.
- The stream exposes
get_warmup_period() -> 0, but the smoothed bands still returnNaNuntil the SMA buffers fill. - Batch mode rejects unsupported kernels through
InvalidKernelForBatch.
Builder, Streaming & Batch APIs ▼
// Builder
NeighboringTrailingStopBuilder::new()
.buffer_size(usize)
.k(usize)
.percentile(f64)
.smooth(usize)
.kernel(Kernel)
.apply(&Candles)
NeighboringTrailingStopBuilder::new()
.apply_slices(&[f64], &[f64], &[f64])
NeighboringTrailingStopBuilder::new()
.into_stream()
// Stream
NeighboringTrailingStopStream::try_new(NeighboringTrailingStopParams)
NeighboringTrailingStopStream::update(f64, f64, f64)
-> Option<NeighboringTrailingStopPoint>
NeighboringTrailingStopStream::reset()
NeighboringTrailingStopStream::get_warmup_period() -> usize
// Batch
NeighboringTrailingStopBatchBuilder::new()
.buffer_size_range(usize, usize, usize)
.k_range(usize, usize, usize)
.percentile_range(f64, f64, f64)
.smooth_range(usize, usize, usize)
.kernel(Kernel)
.apply_slices(&[f64], &[f64], &[f64])
NeighboringTrailingStopBatchBuilder::new()
.apply(&Candles) Error Handling ▼
pub enum NeighboringTrailingStopError {
EmptyInputData,
AllValuesNaN,
MismatchedInputLengths { high_len: usize, low_len: usize, close_len: usize },
InvalidBufferSize { buffer_size: usize, min: usize },
InvalidK { k: usize, min: usize },
InvalidPercentile { percentile: f64 },
InvalidSmooth { smooth: usize },
OutputLengthMismatch { expected: usize },
InvalidRange { start: String, end: String, step: String },
InvalidKernelForBatch(Kernel),
} Python Bindings
Python exposes a scalar function, a streaming class, and a batch sweep. The scalar function returns six NumPy arrays, the stream returns a six-value tuple or `None`, and batch returns six row-major matrices plus the tested parameter axes and output dimensions.
from vector_ta import (
neighboring_trailing_stop,
neighboring_trailing_stop_batch,
NeighboringTrailingStopStream,
)
trailing_stop, bullish_band, bearish_band, direction, discovery_bull, discovery_bear = (
neighboring_trailing_stop(
highs,
lows,
closes,
buffer_size=200,
k=50,
percentile=90.0,
smooth=5,
kernel="auto",
)
)
stream = NeighboringTrailingStopStream(
buffer_size=200,
k=50,
percentile=90.0,
smooth=5,
)
print(stream.update(highs[-1], lows[-1], closes[-1]))
batch = neighboring_trailing_stop_batch(
highs,
lows,
closes,
buffer_size_range=(160, 240, 40),
k_range=(30, 50, 10),
percentile_range=(80.0, 95.0, 5.0),
smooth_range=(3, 7, 2),
kernel="auto",
)
print(batch["trailing_stop"].shape)
print(batch["buffer_sizes"])
print(batch["percentiles"]) JavaScript/WASM Bindings
The WASM surface exposes scalar, batch, allocation, free, and into-buffer entry points. Scalar output returns six arrays directly. Batch output returns those six flattened row-major outputs plus `combos`, the tested axes, and the row and column counts.
import init, {
neighboring_trailing_stop_js,
neighboring_trailing_stop_batch_js,
} from "@vectoralpha/vector_ta";
await init();
const single = neighboring_trailing_stop_js(
highs,
lows,
closes,
200,
50,
90.0,
5,
);
console.log(single.trailing_stop);
console.log(single.bullish_band);
console.log(single.direction);
const batch = neighboring_trailing_stop_batch_js(highs, lows, closes, {
buffer_size_range: [160, 240, 40],
k_range: [30, 50, 10],
percentile_range: [80.0, 95.0, 5.0],
smooth_range: [3, 7, 2],
});
console.log(batch.trailing_stop);
console.log(batch.buffer_sizes);
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)
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