Range Breakout Signals

Parameters: range_length = 20 | confirmation_length = 5

Overview

Range Breakout Signals looks for periods where candle-body distance compresses below a volatility threshold, turns that compression into an active top-and-bottom range, and then waits for price to break outside the band. When a break occurs, the indicator emits either bullish or bearish markers and can also emit an extra-confirmed version when the recent up-volume or down-volume balance supports the direction of the break.

VectorTA returns the active range boundaries together with four signal streams: bullish, extra bullish, bearish, and extra bearish. The implementation supports full OHLCV candle input, raw open-high-low-close-volume slices, streaming updates, and two-axis parameter sweeps across the range-detection and confirmation windows.

Defaults: `range_length = 20` and `confirmation_length = 5`.

Implementation Examples

Run the indicator from candles or from explicit OHLCV slices when you want direct control of the input arrays.

use vector_ta::indicators::range_breakout_signals::{
    range_breakout_signals,
    RangeBreakoutSignalsInput,
    RangeBreakoutSignalsParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};

let direct = range_breakout_signals(&RangeBreakoutSignalsInput::from_slices(
    &open,
    &high,
    &low,
    &close,
    &volume,
    RangeBreakoutSignalsParams {
        range_length: Some(20),
        confirmation_length: Some(5),
    },
))?;

let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let from_candles = range_breakout_signals(&RangeBreakoutSignalsInput::with_default_candles(&candles))?;

println!("top = {:?}", direct.range_top.last());
println!("bullish = {:?}", from_candles.bullish.last());

API Reference

Input Methods
RangeBreakoutSignalsInput::from_candles(&Candles, RangeBreakoutSignalsParams)
    -> RangeBreakoutSignalsInput

RangeBreakoutSignalsInput::from_slices(&[f64], &[f64], &[f64], &[f64], &[f64], RangeBreakoutSignalsParams)
    -> RangeBreakoutSignalsInput

RangeBreakoutSignalsInput::with_default_candles(&Candles)
    -> RangeBreakoutSignalsInput
Parameters Structure
pub struct RangeBreakoutSignalsParams {
    pub range_length: Option<usize>,         // default 20
    pub confirmation_length: Option<usize>,  // default 5
}
Output Structure
pub struct RangeBreakoutSignalsOutput {
    pub range_top: Vec<f64>,
    pub range_bottom: Vec<f64>,
    pub bullish: Vec<f64>,
    pub extra_bullish: Vec<f64>,
    pub bearish: Vec<f64>,
    pub extra_bearish: Vec<f64>,
}
Validation & Warmup
  • Open, high, low, close, and volume arrays must all be non-empty, equal in length, and contain enough valid bars.
  • range_length must be greater than 0 and no larger than the data length.
  • confirmation_length must be greater than 0.
  • The direct path validates a minimum bar count based on both the range and confirmation windows before signals can appear.
  • Invalid streaming OHLCV updates reset the internal state and return None.
  • Batch mode validates both sweep axes and rejects non-batch kernels.
Builder, Streaming & Batch APIs
RangeBreakoutSignalsBuilder::new()
    .range_length(usize)
    .confirmation_length(usize)
    .kernel(Kernel)
    .apply(&Candles)
    .apply_slices(&[f64], &[f64], &[f64], &[f64], &[f64])
    .into_stream()

RangeBreakoutSignalsStream::try_new(params)
stream.update(open, high, low, close, volume) -> Option<(f64, f64, f64, f64, f64, f64)>
stream.reset()

RangeBreakoutSignalsBatchBuilder::new()
    .range(RangeBreakoutSignalsBatchRange)
    .kernel(Kernel)
    .apply_slices(&[f64], &[f64], &[f64], &[f64], &[f64])
    .apply(&Candles)

Python Bindings

Python exposes a scalar OHLCV function returning six NumPy arrays, a stream class that returns a six-value tuple when an active range or break signal is available, and a batch helper that reshapes each output field into a parameter-grid matrix.

from vector_ta import (
    range_breakout_signals,
    range_breakout_signals_batch,
    RangeBreakoutSignalsStream,
)

single = range_breakout_signals(
    open,
    high,
    low,
    close,
    volume,
    range_length=20,
    confirmation_length=5,
)

stream = RangeBreakoutSignalsStream(range_length=20, confirmation_length=5)
point = stream.update(open[-1], high[-1], low[-1], close[-1], volume[-1])

batch = range_breakout_signals_batch(
    open,
    high,
    low,
    close,
    volume,
    range_length_range=(20, 30, 5),
    confirmation_length_range=(5, 9, 2),
)

print(single["range_top"][-1], single["bullish"][-1])
print(batch["rows"], batch["cols"])

JavaScript/WASM Bindings

The WASM layer exposes object-returning scalar and batch helpers, a stream wrapper, and lower-level allocation and into-buffer functions for caller-managed memory.

import init, {
  range_breakout_signals_js,
  range_breakout_signals_batch,
  range_breakout_signals_alloc,
  range_breakout_signals_free,
  range_breakout_signals_into,
  range_breakout_signals_batch_into,
  RangeBreakoutSignalsStreamWasm,
} from "vector-ta-wasm";

await init();

const single = range_breakout_signals_js(open, high, low, close, volume, 20, 5);

const batch = range_breakout_signals_batch(open, high, low, close, volume, {
  range_length_range: [20, 30, 5],
  confirmation_length_range: [5, 9, 2],
});

const stream = new RangeBreakoutSignalsStreamWasm(20, 5);
const point = await stream.update(
  open[open.length - 1],
  high[high.length - 1],
  low[low.length - 1],
  close[close.length - 1],
  volume[volume.length - 1],
);

console.log(single.range_top, single.bullish, batch.rows, point);

CUDA Bindings (Rust)

Additional details for the CUDA bindings can be found inside the VectorTA repository.

Performance Analysis

Comparison:
View:
Placeholder data (no recorded benchmarks for this indicator)

Across sizes, Rust CPU runs about 1.14× faster than Tulip C in this benchmark.

Loading chart...

AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU)

Related Indicators