Kase Peak Oscillator With Divergences
deviations = 2 | short_cycle = 8 | long_cycle = 65 | sensitivity = 40 | all_peaks_mode = true | lb_r = 5 | lb_l = 5 | range_upper = 60 | range_lower = 5 | plot_bull = true | plot_hidden_bull = | plot_bear = true | plot_hidden_bear = Overview
Kase Peak Oscillator With Divergences computes a volatility-normalized oscillator from OHLC data and then layers in threshold, peak, and divergence signals. Internally it builds a log-return based oscillator, smooths the strongest upside and downside cycle responses across the short_cycle to long_cycle scan, and then turns that structure into the main oscillator and histogram outputs. The current implementation sets histogram equal to the oscillator, then derives dynamic peak bands, market-extreme markers, bullish and bearish divergence markers, and go_long or go_short flags when a market extreme occurs.
Defaults: deviations = 2.0, short_cycle = 8, long_cycle = 65, sensitivity = 40.0, all_peaks_mode = true, lb_r = 5, lb_l = 5, range_upper = 60, range_lower = 5, plot_bull = true, plot_hidden_bull = false, plot_bear = true, and plot_hidden_bear = false. Candle input uses built-in high, low, and close values directly.
Implementation Examples
Use explicit OHLC slices or candle data:
use vector_ta::indicators::kase_peak_oscillator_with_divergences::{
kase_peak_oscillator_with_divergences,
KasePeakOscillatorWithDivergencesInput,
KasePeakOscillatorWithDivergencesParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let high = vec![101.0, 103.0, 104.2, 105.6, 106.1, 107.4];
let low = vec![99.5, 100.8, 101.7, 103.0, 103.9, 104.8];
let close = vec![100.2, 102.4, 103.6, 104.7, 105.2, 106.9];
let input = KasePeakOscillatorWithDivergencesInput::from_slices(
&high,
&low,
&close,
KasePeakOscillatorWithDivergencesParams::default(),
);
let out = kase_peak_oscillator_with_divergences(&input)?;
// Candles path uses candles.high / candles.low / candles.close
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_out = kase_peak_oscillator_with_divergences(
&KasePeakOscillatorWithDivergencesInput::with_default_candles(&candles),
)?;
println!("oscillator last = {:?}", out.oscillator.last());
println!("go_long last = {:?}", out.go_long.last());
println!("regular_bearish last = {:?}", out.regular_bearish.last()); API Reference
Input Methods ▼
// From candles (uses candles.high, candles.low, candles.close)
KasePeakOscillatorWithDivergencesInput::from_candles(
&Candles,
KasePeakOscillatorWithDivergencesParams,
) -> KasePeakOscillatorWithDivergencesInput
// From explicit OHLC slices
KasePeakOscillatorWithDivergencesInput::from_slices(
&[f64],
&[f64],
&[f64],
KasePeakOscillatorWithDivergencesParams,
) -> KasePeakOscillatorWithDivergencesInput
// From candles with defaults
KasePeakOscillatorWithDivergencesInput::with_default_candles(&Candles)
-> KasePeakOscillatorWithDivergencesInput Parameters and Outputs ▼
pub struct KasePeakOscillatorWithDivergencesParams {
pub deviations: Option<f64>,
pub short_cycle: Option<usize>,
pub long_cycle: Option<usize>,
pub sensitivity: Option<f64>,
pub all_peaks_mode: Option<bool>,
pub lb_r: Option<usize>,
pub lb_l: Option<usize>,
pub range_upper: Option<usize>,
pub range_lower: Option<usize>,
pub plot_bull: Option<bool>,
pub plot_hidden_bull: Option<bool>,
pub plot_bear: Option<bool>,
pub plot_hidden_bear: Option<bool>,
}
pub struct KasePeakOscillatorWithDivergencesOutput {
pub oscillator: Vec<f64>,
pub histogram: Vec<f64>,
pub max_peak_value: Vec<f64>,
pub min_peak_value: Vec<f64>,
pub market_extreme: Vec<f64>,
pub regular_bullish: Vec<f64>,
pub hidden_bullish: Vec<f64>,
pub regular_bearish: Vec<f64>,
pub hidden_bearish: Vec<f64>,
pub go_long: Vec<f64>,
pub go_short: Vec<f64>,
} Builder, Stream, and Batch Surface ▼
KasePeakOscillatorWithDivergencesBuilder::new()
.deviations(f64)
.short_cycle(usize)
.long_cycle(usize)
.sensitivity(f64)
.all_peaks_mode(bool)
.lb_r(usize)
.lb_l(usize)
.range_upper(usize)
.range_lower(usize)
.plot_bull(bool)
.plot_hidden_bull(bool)
.plot_bear(bool)
.plot_hidden_bear(bool)
.kernel(Kernel)
.apply(&Candles) -> Result<KasePeakOscillatorWithDivergencesOutput, _>
KasePeakOscillatorWithDivergencesBuilder::new()
.apply_slices(&[f64], &[f64], &[f64]) -> Result<KasePeakOscillatorWithDivergencesOutput, _>
KasePeakOscillatorWithDivergencesBuilder::new()
.into_stream() -> Result<KasePeakOscillatorWithDivergencesStream, _>
KasePeakOscillatorWithDivergencesStream::update(high, low, close)
-> Option<(f64, f64, f64, f64, f64, f64, f64, f64, f64, f64, f64)>
KasePeakOscillatorWithDivergencesBatchBuilder::new()
.deviations_range((f64, f64, f64))
.short_cycle_range((usize, usize, usize))
.long_cycle_range((usize, usize, usize))
.sensitivity_range((f64, f64, f64))
.kernel(Kernel)
.apply_slices(&[f64], &[f64], &[f64])
-> Result<KasePeakOscillatorWithDivergencesBatchOutput, _> Warmup, NaNs, and Validation ▼
- Inputs must be non-empty equal-length
high,low, andcloseseries. - Valid OHLC values must be finite and strictly positive. Invalid bars reset the stream and yield
Nonefor that update. - Parameter validation rejects negative or non-finite
deviations, non-finitesensitivity, zerolb_l/lb_r, zerorange_lower/range_upper,range_lower > range_upper, and anyshort_cycle >= long_cycle. prepare_inputrequires at leastmain_warmup(short_cycle, long_cycle) + 1valid bars, wheremain_warmup = max(long_cycle, 39) + 1.- For the batch API, leading NaN prefixes are allocated separately for main oscillator outputs, peak outputs, and divergence outputs.
- Main oscillator and histogram warmup prefix:
first_valid + main_warmup. - Peak and market-extreme warmup prefix:
first_valid + main_warmup + 49, because the threshold logic uses 50-bar rolling stats of|oscillator|. - Divergence warmup prefix:
first_valid + main_warmup + lb_l + lb_r.
Peak and Divergence Semantics ▼
histogramcurrently mirrorsoscillator.max_peak_valueandmin_peak_valuecome fromabs_avg + deviations * abs_stdwith a 90.0 floor/ceiling, then signed to match oscillator direction.market_extrememarks a local turning point based on the previous two oscillator values. Withall_peaks_mode = false, the prior peak must also exceed the threshold band.go_long = 1.0whenmarket_extreme < 0;go_short = 1.0whenmarket_extreme > 0; otherwise both stay0.0once their warmup has passed.- Regular bullish divergence requires a lower price low and a higher oscillator low; hidden bullish requires a higher price low and a lower oscillator low.
- Regular bearish divergence requires a higher price high and a lower oscillator high; hidden bearish requires a lower price high and a higher oscillator high.
- Divergence pivots must be separated by a number of bars inside
[range_lower, range_upper]and the correspondingplot_*toggle must be enabled.
Batch Output and Errors ▼
pub struct KasePeakOscillatorWithDivergencesBatchOutput {
pub oscillator: Vec<f64>,
pub histogram: Vec<f64>,
pub max_peak_value: Vec<f64>,
pub min_peak_value: Vec<f64>,
pub market_extreme: Vec<f64>,
pub regular_bullish: Vec<f64>,
pub hidden_bullish: Vec<f64>,
pub regular_bearish: Vec<f64>,
pub hidden_bearish: Vec<f64>,
pub go_long: Vec<f64>,
pub go_short: Vec<f64>,
pub deviations: Vec<f64>,
pub short_cycles: Vec<usize>,
pub long_cycles: Vec<usize>,
pub sensitivities: Vec<f64>,
pub rows: usize,
pub cols: usize,
}
// Common errors:
// - EmptyInputData / AllValuesNaN
// - InconsistentSliceLengths
// - InvalidDeviations / InvalidShortCycle / InvalidLongCycle / InvalidCycleOrder
// - InvalidSensitivity / InvalidLbR / InvalidLbL
// - InvalidRangeUpper / InvalidRangeLower / InvalidDivergenceRange
// - NotEnoughValidData
// - OutputLengthMismatch
// - InvalidRange
// - InvalidKernelForBatch Python Bindings
Basic Usage ▼
The Python scalar function returns 11 NumPy arrays in output-struct order:
import numpy as np
from vector_ta import kase_peak_oscillator_with_divergences
oscillator, histogram, max_peak_value, min_peak_value, market_extreme, regular_bullish, hidden_bullish, regular_bearish, hidden_bearish, go_long, go_short = kase_peak_oscillator_with_divergences(
high,
low,
close,
deviations=2.0,
short_cycle=8,
long_cycle=65,
sensitivity=40.0,
all_peaks_mode=True,
lb_r=5,
lb_l=5,
range_upper=60,
range_lower=5,
plot_bull=True,
plot_hidden_bull=False,
plot_bear=True,
plot_hidden_bear=False,
kernel="auto",
) Streaming Real-time Updates ▼
The Python stream class exposes the same 11-value tuple plus a warmup_period getter:
from vector_ta import KasePeakOscillatorWithDivergencesStream
stream = KasePeakOscillatorWithDivergencesStream()
print(stream.warmup_period)
for high_i, low_i, close_i in live_feed:
result = stream.update(high_i, low_i, close_i)
if result is not None:
(
oscillator,
histogram,
max_peak_value,
min_peak_value,
market_extreme,
regular_bullish,
hidden_bullish,
regular_bearish,
hidden_bearish,
go_long,
go_short,
) = result Batch Processing ▼
Batch results are returned as a dict of 2D outputs plus parameter columns:
from vector_ta import kase_peak_oscillator_with_divergences_batch
result = kase_peak_oscillator_with_divergences_batch(
high,
low,
close,
deviations_range=(1.5, 2.5, 0.5),
short_cycle_range=(8, 10, 1),
long_cycle_range=(55, 65, 5),
sensitivity_range=(30.0, 40.0, 10.0),
all_peaks_mode=True,
lb_r=5,
lb_l=5,
range_upper=60,
range_lower=5,
plot_bull=True,
plot_hidden_bull=False,
plot_bear=True,
plot_hidden_bear=False,
kernel="auto",
)
oscillator = result["oscillator"]
histogram = result["histogram"]
max_peak_value = result["max_peak_value"]
min_peak_value = result["min_peak_value"]
market_extreme = result["market_extreme"]
regular_bullish = result["regular_bullish"]
hidden_bullish = result["hidden_bullish"]
regular_bearish = result["regular_bearish"]
hidden_bearish = result["hidden_bearish"]
go_long = result["go_long"]
go_short = result["go_short"]
deviations = result["deviations"]
short_cycles = result["short_cycles"]
long_cycles = result["long_cycles"]
sensitivities = result["sensitivities"]
rows = result["rows"]
cols = result["cols"] JavaScript/WASM Bindings
Basic Usage ▼
The JS/WASM scalar function returns an object with 11 typed arrays:
import { kase_peak_oscillator_with_divergences_js } from 'vectorta-wasm';
const result = kase_peak_oscillator_with_divergences_js(
high,
low,
close,
2.0,
8,
65,
40.0,
true,
5,
5,
60,
5,
true,
false,
true,
false,
) as {
oscillator: Float64Array;
histogram: Float64Array;
max_peak_value: Float64Array;
min_peak_value: Float64Array;
market_extreme: Float64Array;
regular_bullish: Float64Array;
hidden_bullish: Float64Array;
regular_bearish: Float64Array;
hidden_bearish: Float64Array;
go_long: Float64Array;
go_short: Float64Array;
};
console.log(result.oscillator);
console.log(result.market_extreme);
console.log(result.go_long); Host Buffer API ▼
Low-level WASM writes into 11 separate output buffers. Allocate one buffer per output with kase_peak_oscillator_with_divergences_alloc(len):
import {
kase_peak_oscillator_with_divergences_alloc,
kase_peak_oscillator_with_divergences_free,
kase_peak_oscillator_with_divergences_into,
} from 'vectorta-wasm';
const len = close.length;
const oscillatorPtr = kase_peak_oscillator_with_divergences_alloc(len);
const histogramPtr = kase_peak_oscillator_with_divergences_alloc(len);
// ... allocate max_peak_value, min_peak_value, market_extreme,
// regular_bullish, hidden_bullish, regular_bearish, hidden_bearish,
// go_long, and go_short the same way ...
try {
kase_peak_oscillator_with_divergences_into(
highPtr,
lowPtr,
closePtr,
oscillatorPtr,
histogramPtr,
maxPeakPtr,
minPeakPtr,
marketExtremePtr,
regularBullishPtr,
hiddenBullishPtr,
regularBearishPtr,
hiddenBearishPtr,
goLongPtr,
goShortPtr,
len,
2.0,
8,
65,
40.0,
true,
5,
5,
60,
5,
true,
false,
true,
false,
);
} finally {
kase_peak_oscillator_with_divergences_free(oscillatorPtr, len);
kase_peak_oscillator_with_divergences_free(histogramPtr, len);
} Batch Processing ▼
The JS batch config accepts optional ranges and optional fixed booleans/lookbacks:
import { kase_peak_oscillator_with_divergences_batch_js } from 'vectorta-wasm';
const batch = kase_peak_oscillator_with_divergences_batch_js(high, low, close, {
deviations_range: [1.5, 2.5, 0.5],
short_cycle_range: [8, 10, 1],
long_cycle_range: [55, 65, 5],
sensitivity_range: [30.0, 40.0, 10.0],
all_peaks_mode: true,
lb_r: 5,
lb_l: 5,
range_upper: 60,
range_lower: 5,
plot_bull: true,
plot_hidden_bull: false,
plot_bear: true,
plot_hidden_bear: false,
}) as {
oscillator: number[];
histogram: number[];
max_peak_value: number[];
min_peak_value: number[];
market_extreme: number[];
regular_bullish: number[];
hidden_bullish: number[];
regular_bearish: number[];
hidden_bearish: number[];
go_long: number[];
go_short: number[];
deviations: number[];
short_cycles: number[];
long_cycles: number[];
sensitivities: number[];
rows: number;
cols: number;
};
console.log(batch.rows, batch.cols);
console.log(batch.deviations);
console.log(batch.short_cycles); 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)