Geometric Bias Oscillator
length = 100 | multiplier = 2 | atr_length = 14 | smooth = 1 Overview
Geometric Bias Oscillator evaluates whether the recent price structure is dominated by upward or downward path segments. It collects a rolling close window, orders that window, and repeatedly splits the ordered curve where an ATR-normalized point deviates far enough from the current line segment. The remaining simplified path is then decomposed into bullish and bearish legs, and those path lengths are converted into a normalized oscillator.
The final reading ranges between negative and positive values, with strong up-structure approaching 100 and strong down-structure approaching -100. ATR controls the geometric tolerance, while optional smoothing stabilizes the finished oscillator. Because the indicator depends on high, low, and close data, the streaming and batch paths both operate on HLC inputs rather than close-only slices.
Defaults: Geometric Bias Oscillator uses `length = 100`, `multiplier = 2.0`, `atr_length = 14`, and `smooth = 1`.
Implementation Examples
Compute the oscillator from HLC slices or candle data.
use vector_ta::indicators::geometric_bias_oscillator::{
geometric_bias_oscillator,
GeometricBiasOscillatorInput,
GeometricBiasOscillatorParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let high = vec![101.2, 102.5, 103.0, 104.0, 104.8, 105.3];
let low = vec![99.8, 100.9, 101.5, 102.1, 103.0, 103.7];
let close = vec![100.7, 101.9, 102.6, 103.7, 104.2, 104.9];
let output = geometric_bias_oscillator(&GeometricBiasOscillatorInput::from_slices(
&high,
&low,
&close,
GeometricBiasOscillatorParams {
length: Some(100),
multiplier: Some(2.0),
atr_length: Some(14),
smooth: Some(1),
},
))?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_output = geometric_bias_oscillator(
&GeometricBiasOscillatorInput::with_default_candles(&candles),
)?;
println!("latest gbo = {:?}", output.values.last());
println!("series length = {}", candle_output.values.len()); API Reference
Input Methods ▼
// From candles
GeometricBiasOscillatorInput::from_candles(&Candles, GeometricBiasOscillatorParams)
-> GeometricBiasOscillatorInput
// From HLC slices
GeometricBiasOscillatorInput::from_slices(&[f64], &[f64], &[f64], GeometricBiasOscillatorParams)
-> GeometricBiasOscillatorInput
// From candles with default parameters
GeometricBiasOscillatorInput::with_default_candles(&Candles)
-> GeometricBiasOscillatorInput Parameters Structure ▼
pub struct GeometricBiasOscillatorParams {
pub length: Option<usize>, // default 100
pub multiplier: Option<f64>, // default 2.0
pub atr_length: Option<usize>, // default 14
pub smooth: Option<usize>, // default 1
} Output Structure ▼
pub struct GeometricBiasOscillatorOutput {
pub values: Vec<f64>,
} Validation, Warmup & NaNs ▼
- Input HLC slices must be non-empty and have matching lengths.
lengthmust stay within10..=500and cannot exceed the available data length.multipliermust be finite and at least0.1.atr_lengthmust be valid for the supplied data, andsmoothmust be positive.- The indicator requires a long enough contiguous valid run to satisfy the geometry window, ATR warmup, and smoothing warmup together.
- NaN input gaps reset the streaming state and restart the warmup process.
- Output is NaN-prefixed until the full warmup requirement has been satisfied.
- Batch mode validates every axis range and rejects non-batch kernels through
InvalidKernelForBatch.
Builder, Streaming & Batch APIs ▼
// Builder
GeometricBiasOscillatorBuilder::new()
.length(usize)
.multiplier(f64)
.atr_length(usize)
.smooth(usize)
.kernel(Kernel)
.apply(&Candles)
GeometricBiasOscillatorBuilder::new()
.apply_slices(&[f64], &[f64], &[f64])
GeometricBiasOscillatorBuilder::new()
.into_stream()
// Stream
GeometricBiasOscillatorStream::try_new(GeometricBiasOscillatorParams)
GeometricBiasOscillatorStream::update(f64, f64, f64) -> Option<f64>
GeometricBiasOscillatorStream::params() -> &GeometricBiasOscillatorParams
// Batch
GeometricBiasOscillatorBatchBuilder::new()
.kernel(Kernel)
.length_range(start, end, step)
.multiplier_range(start, end, step)
.atr_length_range(start, end, step)
.smooth_range(start, end, step)
.apply_slices(&[f64], &[f64], &[f64])
GeometricBiasOscillatorBatchBuilder::new()
.apply(&Candles) Error Handling ▼
pub enum GeometricBiasOscillatorError {
EmptyInputData,
AllValuesNaN,
DataLengthMismatch { high_len: usize, low_len: usize, close_len: usize },
InvalidLength { length: usize, min_length: usize, max_length: usize, data_len: usize },
InvalidAtrLength { atr_length: usize, data_len: usize },
InvalidMultiplier { multiplier: f64 },
InvalidSmooth { smooth: usize },
NotEnoughValidData { needed: usize, valid: usize },
OutputLengthMismatch { expected: usize, got: usize },
InvalidRange { axis: &'static str, start: String, end: String, step: String },
InvalidKernelForBatch(Kernel),
} Python Bindings
Python exposes a scalar HLC function, a streaming class, and a full batch sweep. The scalar path returns one NumPy oscillator array. Streaming returns one floating-point bias reading or `None`, while batch returns the flattened oscillator matrix together with the tested lengths, multipliers, ATR lengths, smoothing values, and output dimensions.
import numpy as np
from vector_ta import (
geometric_bias_oscillator,
geometric_bias_oscillator_batch,
GeometricBiasOscillatorStream,
)
high = np.asarray(high_values, dtype=np.float64)
low = np.asarray(low_values, dtype=np.float64)
close = np.asarray(close_values, dtype=np.float64)
values = geometric_bias_oscillator(
high,
low,
close,
length=100,
multiplier=2.0,
atr_length=14,
smooth=1,
kernel="auto",
)
stream = GeometricBiasOscillatorStream(
length=80,
multiplier=1.5,
atr_length=14,
smooth=2,
)
print(stream.update(high[-1], low[-1], close[-1]))
batch = geometric_bias_oscillator_batch(
high,
low,
close,
length_range=(60, 100, 20),
multiplier_range=(1.0, 2.0, 0.5),
atr_length_range=(10, 14, 4),
smooth_range=(1, 3, 2),
kernel="auto",
)
print(batch["values"].shape)
print(batch["lengths"])
print(batch["multipliers"]) JavaScript/WASM Bindings
The WASM surface includes a direct array-returning function, a unified batch function, and raw allocation and into-buffer helpers for lower-level integration. The scalar binding returns a single oscillator array. The batch binding returns the flattened values matrix plus the tested parameter combinations and matrix dimensions.
import init, {
geometric_bias_oscillator_js,
geometric_bias_oscillator_batch,
} from "@vectoralpha/vector_ta";
await init();
const values = geometric_bias_oscillator_js(high, low, close, 100, 2.0, 14, 1);
console.log(values);
const batch = geometric_bias_oscillator_batch(high, low, close, {
length_range: [60, 100, 20],
multiplier_range: [1.0, 2.0, 0.5],
atr_length_range: [10, 14, 4],
smooth_range: [1, 3, 2],
});
console.log(batch.values);
console.log(batch.combos);
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)