Reversal Signals
lookback_period = 12 | confirmation_period = 3 | use_volume_confirmation = true | trend_ma_period = 50 | trend_ma_type = EMA | ma_step_period = 33 Overview
Reversal Signals looks for turning points inside structured price action instead of treating every crossover as a standalone event. It tracks rolling swing highs and lows, checks whether price is attempting a local reversal, and then confirms that reversal with a configurable number of bars and, optionally, above-average volume.
Alongside the discrete buy and sell markers, the indicator maintains a trend moving average and a stepped version of that average that only advances after a configurable bar interval. The state output reflects the relationship between price and the stepped trend context, making the indicator usable as both a trigger and a trend filter.
Defaults: `lookback_period = 12`, `confirmation_period = 3`, `use_volume_confirmation = true`, `trend_ma_period = 50`, `trend_ma_type = "EMA"`, and `ma_step_period = 33`.
Implementation Examples
Run the indicator on candles or explicit OHLCV slices and inspect the four output series.
use vector_ta::indicators::reversal_signals::{
reversal_signals,
ReversalSignalsInput,
ReversalSignalsParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let output = reversal_signals(&ReversalSignalsInput::from_slices(
&open,
&high,
&low,
&close,
&volume,
ReversalSignalsParams {
lookback_period: Some(12),
confirmation_period: Some(3),
use_volume_confirmation: Some(true),
trend_ma_period: Some(50),
trend_ma_type: Some("EMA".to_string()),
ma_step_period: Some(33),
},
))?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_output = reversal_signals(&ReversalSignalsInput::with_default_candles(&candles))?;
println!("buy = {:?}", output.buy_signal.last());
println!("sell = {:?}", output.sell_signal.last());
println!("stepped ma = {:?}", candle_output.stepped_ma.last());
println!("state = {:?}", candle_output.state.last()); API Reference
Input Methods ▼
ReversalSignalsInput::from_candles(&Candles, ReversalSignalsParams)
-> ReversalSignalsInput
ReversalSignalsInput::from_slices(
&[f64],
&[f64],
&[f64],
&[f64],
&[f64],
ReversalSignalsParams,
) -> ReversalSignalsInput
ReversalSignalsInput::with_default_candles(&Candles)
-> ReversalSignalsInput Parameters Structure ▼
pub struct ReversalSignalsParams {
pub lookback_period: Option<usize>,
pub confirmation_period: Option<usize>,
pub use_volume_confirmation: Option<bool>,
pub trend_ma_period: Option<usize>,
pub trend_ma_type: Option<String>,
pub ma_step_period: Option<usize>,
} Output Structure ▼
pub struct ReversalSignalsOutput {
pub buy_signal: Vec<f64>,
pub sell_signal: Vec<f64>,
pub stepped_ma: Vec<f64>,
pub state: Vec<f64>,
} Validation, Warmup & Modes ▼
- The open, high, low, close, and volume slices must all be non-empty, share the same length, and contain a long enough valid OHLCV run to satisfy the lookback and trend-average requirements.
lookback_periodandtrend_ma_periodmust be greater than0.- The supported trend moving-average types are
SMA,EMA,WMA, andVWMA. - If volume confirmation is enabled, the stream maintains a 20-bar volume SMA and requires the live bar volume to exceed that average before confirmation succeeds.
- Invalid or non-finite OHLCV bars reset the streaming runtime and yield
Nonefor that update. - Batch mode validates every numeric sweep axis and rejects unsupported kernels.
Builder, Streaming & Batch APIs ▼
ReversalSignalsBuilder::new()
.lookback_period(usize)
.confirmation_period(usize)
.use_volume_confirmation(bool)
.trend_ma_period(usize)
.trend_ma_type(&str)?
.ma_step_period(usize)
.kernel(Kernel)
.apply(&Candles)
.into_stream()
ReversalSignalsStream::try_new(params)
stream.update(f64, f64, f64, f64, f64) -> Option<(f64, f64, f64, f64)>
ReversalSignalsBatchBuilder::new()
.lookback_period_range(start, end, step)
.confirmation_period_range(start, end, step)
.trend_ma_period_range(start, end, step)
.ma_step_period_range(start, end, step)
.use_volume_confirmation(bool)
.trend_ma_type(&str)?
.kernel(Kernel)
.apply_slices(&[f64], &[f64], &[f64], &[f64], &[f64])
.apply_candles(&Candles) Error Handling ▼
pub enum ReversalSignalsError {
EmptyInputData,
InputLengthMismatch {
open_len: usize,
high_len: usize,
low_len: usize,
close_len: usize,
volume_len: usize,
},
AllValuesNaN,
InvalidLookbackPeriod { lookback_period: usize },
InvalidTrendMaPeriod { trend_ma_period: usize },
InvalidTrendMaType { value: String },
NotEnoughValidData { needed: usize, valid: usize },
OutputLengthMismatch { expected: usize, got: usize },
MismatchedOutputLen { dst_len: usize, expected_len: usize },
InvalidRange { start: String, end: String, step: String },
InvalidKernel(Kernel),
InvalidKernelForBatch(Kernel),
InvalidInput { msg: String },
} Python Bindings
Python exposes a scalar function, a stream class, and a batch helper. The scalar call returns four NumPy arrays, the stream emits a four-value tuple or None, and the batch helper returns flattened matrices plus the parameter combinations that were tested.
from vector_ta import (
reversal_signals,
reversal_signals_batch,
ReversalSignalsStream,
)
buy_signal, sell_signal, stepped_ma, state = reversal_signals(
open,
high,
low,
close,
volume,
lookback_period=12,
confirmation_period=3,
use_volume_confirmation=True,
trend_ma_period=50,
trend_ma_type="EMA",
ma_step_period=33,
kernel="auto",
)
stream = ReversalSignalsStream(trend_ma_type="VWMA")
print(stream.update(open[-1], high[-1], low[-1], close[-1], volume[-1]))
batch = reversal_signals_batch(
open,
high,
low,
close,
volume,
lookback_period_range=(10, 14, 2),
confirmation_period_range=(2, 4, 1),
trend_ma_period_range=(34, 50, 8),
ma_step_period_range=(20, 33, 13),
use_volume_confirmation=True,
trend_ma_type="EMA",
kernel="auto",
)
print(batch["rows"], batch["cols"]) JavaScript/WASM Bindings
The WASM surface exposes scalar, batch, allocation, and into-buffer helpers. The high-level calls return plain JS objects containing the four output arrays, and the low-level APIs write those arrays into caller-managed memory.
import init, {
reversal_signals_js,
reversal_signals_batch_js,
reversal_signals_alloc,
reversal_signals_free,
reversal_signals_into,
reversal_signals_batch_into,
} from "vector-ta-wasm";
await init();
const out = reversal_signals_js(
open,
high,
low,
close,
volume,
12,
3,
true,
50,
"EMA",
33,
);
console.log(out.buy_signal, out.state);
const batch = reversal_signals_batch_js(open, high, low, close, volume, {
lookback_period_range: [10, 14, 2],
confirmation_period_range: [2, 4, 1],
trend_ma_period_range: [34, 50, 8],
ma_step_period_range: [20, 33, 13],
use_volume_confirmation: true,
trend_ma_type: "EMA",
});
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)
Related Indicators
Average Directional Index
Technical analysis indicator
Average Directional Movement Index Rating
Technical analysis indicator
Alligator
Technical analysis indicator
Aroon
Technical analysis indicator
Aroon Oscillator
Technical analysis indicator
Chande Momentum Oscillator
Technical analysis indicator