Absolute Strength Index Oscillator
ema_length = 21 | signal_length = 34 Overview
Absolute Strength Index Oscillator tracks directional pressure by separating advancing moves, declining moves, and unchanged bars into running accumulators and collapsing them into a bounded absolute-strength ratio. That ratio is then smoothed with an EMA, and the final oscillator is the distance between the live ratio and its EMA. A second smoothing pass produces the signal line, while the histogram measures the spread between oscillator and signal.
In practice, the oscillator reacts to the balance between persistent advances and declines rather than to price level alone. Positive histogram expansion means the live strength ratio is outrunning its signal, while negative histogram expansion means the directional impulse is cooling. Because the implementation resets on invalid values and starts calculating as soon as the first finite bar appears, this indicator behaves more like a stateful breadth oscillator than a long warmup momentum study.
Defaults: Absolute Strength Index Oscillator uses `ema_length = 21` and `signal_length = 34`.
Implementation Examples
Compute the oscillator from a single source slice or from candle data with a chosen source field.
use vector_ta::indicators::absolute_strength_index_oscillator::{
absolute_strength_index_oscillator,
AbsoluteStrengthIndexOscillatorInput,
AbsoluteStrengthIndexOscillatorParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let close = vec![100.0, 101.4, 101.1, 102.8, 102.2, 103.6];
let params = AbsoluteStrengthIndexOscillatorParams {
ema_length: Some(21),
signal_length: Some(34),
};
let output = absolute_strength_index_oscillator(
&AbsoluteStrengthIndexOscillatorInput::from_slice(&close, params)
)?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_output = absolute_strength_index_oscillator(
&AbsoluteStrengthIndexOscillatorInput::from_candles(
&candles,
"close",
AbsoluteStrengthIndexOscillatorParams::default(),
)
)?;
println!("{:?}", output.oscillator.last());
println!("{:?}", output.signal.last());
println!("{:?}", candle_output.histogram.last()); API Reference
Input Methods ▼
// From candles with explicit source
AbsoluteStrengthIndexOscillatorInput::from_candles(
&Candles,
&str,
AbsoluteStrengthIndexOscillatorParams,
) -> AbsoluteStrengthIndexOscillatorInput
// From a single source slice
AbsoluteStrengthIndexOscillatorInput::from_slice(
&[f64],
AbsoluteStrengthIndexOscillatorParams,
) -> AbsoluteStrengthIndexOscillatorInput
// From candles with defaults and close source
AbsoluteStrengthIndexOscillatorInput::with_default_candles(&Candles)
-> AbsoluteStrengthIndexOscillatorInput Parameters Structure ▼
pub struct AbsoluteStrengthIndexOscillatorParams {
pub ema_length: Option<usize>, // default 21
pub signal_length: Option<usize>, // default 34
} Output Structure ▼
pub struct AbsoluteStrengthIndexOscillatorOutput {
pub oscillator: Vec<f64>,
pub signal: Vec<f64>,
pub histogram: Vec<f64>,
} Validation, Warmup & NaNs ▼
- The input slice must not be empty, and there must be at least one finite value after any leading NaNs.
ema_lengthandsignal_lengthmust both be at least1; invalid values raiseInvalidEmaLengthorInvalidSignalLength.- Leading invalid values remain
NaNin the output. Once the first finite bar appears, the indicator begins producing values immediately. - Encountering a non-finite value later resets the running state in streaming mode, so the next valid bar starts a fresh accumulation.
- Batch mode only accepts batch-capable kernels; otherwise it returns
InvalidKernelForBatch.
Builder, Streaming & Batch APIs ▼
// Builder
AbsoluteStrengthIndexOscillatorBuilder::new()
.ema_length(usize)
.signal_length(usize)
.kernel(Kernel)
.apply_slice(&[f64])
AbsoluteStrengthIndexOscillatorBuilder::new()
.apply(&Candles, &str)
AbsoluteStrengthIndexOscillatorBuilder::new()
.into_stream()
// Stream
AbsoluteStrengthIndexOscillatorStream::try_new(AbsoluteStrengthIndexOscillatorParams)
AbsoluteStrengthIndexOscillatorStream::update(f64)
-> Option<(f64, f64, f64)>
// Batch
AbsoluteStrengthIndexOscillatorBatchBuilder::new()
.ema_length_range(start, end, step)
.signal_length_range(start, end, step)
.kernel(Kernel)
.apply_slice(&[f64]) Error Handling ▼
pub enum AbsoluteStrengthIndexOscillatorError {
EmptyInputData,
AllValuesNaN,
InvalidEmaLength { ema_length: usize },
InvalidSignalLength { signal_length: usize },
OutputLengthMismatch { expected: usize, oscillator_got: usize, signal_got: usize, histogram_got: usize },
InvalidRange { start: String, end: String, step: String },
InvalidKernelForBatch(Kernel),
} Python Bindings
Python exposes a single-run function, a batch function, and a streaming class. The single-run call returns three NumPy arrays as a tuple. Batch returns a dictionary with 2D oscillator, signal, and histogram arrays plus the swept EMA and signal lengths. The streaming class returns a three-value tuple on each valid update and exposes a zero warmup period.
import numpy as np
from vector_ta import (
absolute_strength_index_oscillator,
absolute_strength_index_oscillator_batch,
AbsoluteStrengthIndexOscillatorStream,
)
data = np.asarray(close_values, dtype=np.float64)
oscillator, signal, histogram = absolute_strength_index_oscillator(
data,
ema_length=21,
signal_length=34,
kernel="auto",
)
batch = absolute_strength_index_oscillator_batch(
data,
ema_length_range=(14, 28, 7),
signal_length_range=(20, 40, 10),
kernel="auto",
)
stream = AbsoluteStrengthIndexOscillatorStream(21, 34)
bar = stream.update(float(data[-1])) JavaScript/WASM Bindings
The WASM layer exposes object-returning and pointer-oriented entry points. The normal JS call returns three
typed arrays named oscillator, signal, and
histogram. Batch returns those same families as flattened arrays plus
combos, rows, and cols.
import init, {
absolute_strength_index_oscillator_js,
absolute_strength_index_oscillator_batch_js,
} from "/pkg/vector_ta.js";
await init();
const data = new Float64Array(closeValues);
const out = absolute_strength_index_oscillator_js(data, 21, 34);
console.log(out.oscillator.at(-1), out.signal.at(-1), out.histogram.at(-1));
const batch = absolute_strength_index_oscillator_batch_js(data, {
ema_length_range: [14, 28, 7],
signal_length_range: [20, 40, 10],
});
console.log(batch.rows, batch.cols, batch.oscillator.slice(0, 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)