Adaptive Bandpass Trigger Oscillator
delta = 0.1 | alpha = 0.07 Overview
Adaptive Bandpass Trigger Oscillator is a cycle-focused study that tries to isolate a tradable oscillation from a raw price stream. The indicator first smooths the input, estimates the dominant cycle adaptively, then feeds that estimate into an adaptive band-pass stage. The primary output is the in-phase component, while the lead line acts as a trigger that is phase-advanced relative to the core cycle readout.
In practice, the in-phase line is the cleaner cycle track and the lead line is the faster companion used for crossings and early turns. Because the implementation needs a minimum amount of valid history before the cycle estimate stabilizes, the first valid bars are warmup rather than actionable output. This is especially true for the lead series, which begins one bar later than the in-phase series.
Defaults: Adaptive Bandpass Trigger Oscillator uses `delta = 0.1` and `alpha = 0.07`.
Implementation Examples
Compute the oscillator from a slice or from a candle source field.
use vector_ta::indicators::adaptive_bandpass_trigger_oscillator::{
adaptive_bandpass_trigger_oscillator,
AdaptiveBandpassTriggerOscillatorInput,
AdaptiveBandpassTriggerOscillatorParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let close = vec![100.0, 100.8, 101.2, 100.9, 101.7, 102.1, 101.6, 102.4];
let output = adaptive_bandpass_trigger_oscillator(
&AdaptiveBandpassTriggerOscillatorInput::from_slice(
&close,
AdaptiveBandpassTriggerOscillatorParams {
delta: Some(0.1),
alpha: Some(0.07),
},
)
)?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_output = adaptive_bandpass_trigger_oscillator(
&AdaptiveBandpassTriggerOscillatorInput::with_default_candles(&candles)
)?;
println!("Latest in-phase: {:?}", output.in_phase.last());
println!("Latest lead: {:?}", candle_output.lead.last()); API Reference
Input Methods ▼
// From candles and a named source field
AdaptiveBandpassTriggerOscillatorInput::from_candles(
&Candles,
&str,
AdaptiveBandpassTriggerOscillatorParams,
) -> AdaptiveBandpassTriggerOscillatorInput
// From a slice
AdaptiveBandpassTriggerOscillatorInput::from_slice(
&[f64],
AdaptiveBandpassTriggerOscillatorParams,
) -> AdaptiveBandpassTriggerOscillatorInput
// From candles with default parameters
AdaptiveBandpassTriggerOscillatorInput::with_default_candles(&Candles)
-> AdaptiveBandpassTriggerOscillatorInput Parameters Structure ▼
pub struct AdaptiveBandpassTriggerOscillatorParams {
pub delta: Option<f64>, // default 0.1
pub alpha: Option<f64>, // default 0.07
} Output Structure ▼
pub struct AdaptiveBandpassTriggerOscillatorOutput {
pub in_phase: Vec<f64>,
pub lead: Vec<f64>,
} Validation, Warmup & NaNs ▼
- The input slice must be non-empty and contain at least one finite value.
deltaandalphamust both be finite numbers strictly between0and1.- The algorithm requires at least
12valid samples. If fewer valid values are present, it returnsNotEnoughValidData. - The in-phase series warms up after
11valid samples. The lead series starts one bar later. - Streaming resets on a non-finite input value.
- Batch range expansion requires valid ascending floating-point ranges, and non-batch kernels are rejected for the batch entry point.
Builder, Streaming & Batch APIs ▼
// Builder
AdaptiveBandpassTriggerOscillatorBuilder::new()
.delta(f64)
.alpha(f64)
.kernel(Kernel)
.apply_slice(&[f64])
AdaptiveBandpassTriggerOscillatorBuilder::new()
.apply(&Candles)
AdaptiveBandpassTriggerOscillatorBuilder::new()
.into_stream()
// Stream
AdaptiveBandpassTriggerOscillatorStream::try_new(AdaptiveBandpassTriggerOscillatorParams)
AdaptiveBandpassTriggerOscillatorStream::update(f64) -> Option<(f64, f64)>
AdaptiveBandpassTriggerOscillatorStream::get_warmup_period() -> usize
// Batch
AdaptiveBandpassTriggerOscillatorBatchBuilder::new()
.delta(start, end, step)
.alpha(start, end, step)
.kernel(Kernel)
.apply_slice(&[f64]) Error Handling ▼
pub enum AdaptiveBandpassTriggerOscillatorError {
EmptyInputData,
AllValuesNaN,
InvalidDelta { delta: f64 },
InvalidAlpha { alpha: f64 },
NotEnoughValidData { needed: usize, valid: usize },
OutputLengthMismatch {
expected: usize,
in_phase_got: usize,
lead_got: usize,
},
InvalidRange { start: String, end: String, step: String },
InvalidKernelForBatch(Kernel),
} Python Bindings
Python exposes a tuple-returning single-run function, a streaming class, and a batch function. The single-run
binding returns two NumPy arrays: in_phase and lead.
Batch returns a dictionary containing both matrices plus the tested delta and alpha axes.
import numpy as np
from vector_ta import (
adaptive_bandpass_trigger_oscillator,
adaptive_bandpass_trigger_oscillator_batch,
AdaptiveBandpassTriggerOscillatorStream,
)
data = np.asarray(close_values, dtype=np.float64)
in_phase, lead = adaptive_bandpass_trigger_oscillator(
data,
delta=0.1,
alpha=0.07,
kernel="auto",
)
batch = adaptive_bandpass_trigger_oscillator_batch(
data,
delta_range=(0.08, 0.16, 0.04),
alpha_range=(0.05, 0.09, 0.02),
kernel="auto",
)
stream = AdaptiveBandpassTriggerOscillatorStream(0.1, 0.07)
print(stream.warmup_period)
print(stream.update(data[-1])) JavaScript/WASM Bindings
The WASM layer exposes object-returning single-run and batch wrappers plus lower-level allocation and in-place
exports. The normal JavaScript path returns an object with in_phase and
lead typed arrays. The batch wrapper adds the tested delta and alpha lists plus the
final matrix shape.
import init, {
adaptive_bandpass_trigger_oscillator_js,
adaptive_bandpass_trigger_oscillator_batch_js,
} from "/pkg/vector_ta.js";
await init();
const data = new Float64Array(closeValues);
const result = adaptive_bandpass_trigger_oscillator_js(data, 0.1, 0.07);
console.log(result.in_phase, result.lead);
const batch = adaptive_bandpass_trigger_oscillator_batch_js(data, {
delta_range: [0.08, 0.16, 0.04],
alpha_range: [0.05, 0.09, 0.02],
});
console.log(batch.deltas, batch.alphas, 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
Acceleration Oscillator
Technical analysis indicator
Accumulation/Distribution
Technical analysis indicator
Awesome Oscillator
Technical analysis indicator
Absolute Price Oscillator
Technical analysis indicator
Bandpass Filter
Technical analysis indicator
Commodity Channel Index
Technical analysis indicator