Range Oscillator
length = 50 | mult = 2 Overview
Range Oscillator starts from a weighted moving center line, measures the largest recent deviation from that line, and then projects upper and lower bands around it using a configurable multiplier. The resulting state bundle does more than show one oscillator value: it also tracks whether price remains inside the active range, which direction the current regime favors, and whether a fresh upside or downside break has occurred.
In VectorTA the indicator returns the oscillator itself, the weighted mean, range width, in-range flag, trend state, and breakout markers. It supports candles or explicit high-low-close slices, streaming updates, and two-axis batch sweeps across both the lookback window and band multiplier.
Defaults: `length = 50` and `mult = 2.0`.
Implementation Examples
Run the indicator from candles or from explicit high, low, and close slices.
use vector_ta::indicators::range_oscillator::{
range_oscillator,
RangeOscillatorInput,
RangeOscillatorParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let direct = range_oscillator(&RangeOscillatorInput::from_slices(
&high,
&low,
&close,
RangeOscillatorParams {
length: Some(50),
mult: Some(2.0),
},
))?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let from_candles = range_oscillator(&RangeOscillatorInput::with_default_candles(&candles))?;
println!("osc = {:?}", direct.oscillator.last());
println!("in_range = {:?}", from_candles.in_range.last());API Reference
Input Methods▼
RangeOscillatorInput::from_candles(&Candles, RangeOscillatorParams)
-> RangeOscillatorInput
RangeOscillatorInput::from_slices(&[f64], &[f64], &[f64], RangeOscillatorParams)
-> RangeOscillatorInput
RangeOscillatorInput::with_default_candles(&Candles)
-> RangeOscillatorInputParameters Structure▼
pub struct RangeOscillatorParams {
pub length: Option<usize>, // default 50
pub mult: Option<f64>, // default 2.0
}Output Structure▼
pub struct RangeOscillatorOutput {
pub oscillator: Vec<f64>,
pub ma: Vec<f64>,
pub upper_band: Vec<f64>,
pub lower_band: Vec<f64>,
pub range_width: Vec<f64>,
pub in_range: Vec<f64>,
pub trend: Vec<f64>,
pub break_up: Vec<f64>,
pub break_down: Vec<f64>,
}Validation & Warmup▼
- High, low, and close arrays must be non-empty, equal in length, and contain at least one valid triple.
lengthmust be greater than0.multmust be finite and at least0.1.- The vector path uses a long warmup driven by the larger of the chosen length and the internal ATR fallback period.
- Non-finite stream input clears the ATR state, close history, and trend flag, then returns
None. - Batch mode validates both sweep axes and rejects non-batch kernels.
Builder, Streaming & Batch APIs▼
RangeOscillatorBuilder::new()
.length(usize)
.mult(f64)
.kernel(Kernel)
.apply(&Candles)
.apply_slices(&[f64], &[f64], &[f64])
.into_stream()
RangeOscillatorStream::try_new(params)
stream.update(high, low, close) -> Option<RangeOscillatorStreamOutput>
RangeOscillatorBatchBuilder::new()
.range(RangeOscillatorBatchRange)
.kernel(Kernel)
.apply(&Candles)
.apply_slices(&[f64], &[f64], &[f64])Python Bindings
Python exposes scalar and batch helpers that return dictionaries keyed by each output field, plus a stream class for incremental bar-by-bar updates.
from vector_ta import (
range_oscillator,
range_oscillator_batch,
RangeOscillatorStream,
)
single = range_oscillator(high, low, close, length=50, mult=2.0)
stream = RangeOscillatorStream(length=50, mult=2.0)
point = stream.update(high[-1], low[-1], close[-1])
batch = range_oscillator_batch(
high,
low,
close,
length_range=(50, 70, 10),
mult_range=(2.0, 3.0, 0.5),
)
print(single["oscillator"][-1], single["break_up"][-1])
print(batch["rows"], batch["cols"])JavaScript/WASM Bindings
The WASM layer exposes object-returning scalar and batch helpers that cover every output series in the range state bundle.
import init, {
range_oscillator_js,
range_oscillator_batch,
} from "vector-ta-wasm";
await init();
const single = range_oscillator_js(high, low, close, 50, 2.0);
const batch = range_oscillator_batch(high, low, close, {
length_range: [50, 70, 10],
mult_range: [2.0, 3.0, 0.5],
});
console.log(single.oscillator, single.break_up, batch.rows);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)