Reflex
period = 20 Overview
Reflex detects turning points in price cycles by measuring the difference between smoothed prices and a linear projection, then normalizing this deviation to produce a dimensionless oscillator. The indicator applies a two pole SuperSmoother filter to reduce noise, computes the expected slope over the period window, and divides the difference by an exponentially smoothed variance measure. Values oscillate around zero with spikes appearing at market inflection points while staying flat during steady trends. The normalization ensures readings remain bounded regardless of price scale, making Reflex especially useful for identifying cycle reversals in advance. Traders watch for crossovers through zero as potential entry signals, with positive values suggesting upward momentum and negative values indicating downward pressure. The default 20 period setting balances responsiveness with stability across most timeframes.
Implementation Examples
Get started with Reflex using price slices or candles:
use vectorta::indicators::reflex::{reflex, ReflexInput, ReflexParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};
// Using with price data slice
let prices = vec![100.0, 101.2, 100.7, 102.1, 103.0, 102.4];
let params = ReflexParams { period: Some(20) }; // Default is 20 if None
let input = ReflexInput::from_slice(&prices, params);
let out = reflex(&input)?; // ReflexOutput { values: Vec<f64> }
// Using with Candles (defaults: source="close", period=20)
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = ReflexInput::with_default_candles(&candles);
let out = reflex(&input)?;
// Access values
for v in out.values { println!("Reflex: {}", v); } API Reference
Input Methods ▼
// From price slice
ReflexInput::from_slice(&[f64], ReflexParams) -> ReflexInput
// From candles with custom source
ReflexInput::from_candles(&Candles, &str, ReflexParams) -> ReflexInput
// From candles with default params (close, period=20)
ReflexInput::with_default_candles(&Candles) -> ReflexInput Parameters Structure ▼
pub struct ReflexParams {
pub period: Option<usize>, // Default: 20
} Output Structure ▼
pub struct ReflexOutput {
pub values: Vec<f64>, // Reflex values
} Validation, Warmup & NaNs ▼
period >= 2;NoDataon empty input;AllValuesNaNif no finite values.- Requires at least
periodvalid points after the first finite value; elseNotEnoughData { needed, found }. - Warmup: the first
periodoutputs are0.0by contract (batch); streaming yieldsNoneuntil warmed. - Normalization uses
mst = 0.04·my_sumt2 + 0.96·mst-1; typical values remain within about ±5.
Error Handling ▼
#[derive(Debug, Error)]
pub enum ReflexError {
NoData,
InvalidPeriod { period: usize },
NotEnoughData { needed: usize, found: usize },
AllValuesNaN,
}
// Example handling
match reflex(&input) {
Ok(out) => {/* use out.values */},
Err(ReflexError::InvalidPeriod { period }) => {/* fix params */},
Err(e) => {/* log or bail */},
} Python Bindings
Basic Usage ▾
Operate on NumPy arrays; optionally pin the kernel.
import numpy as np
from vectorta import reflex
prices = np.asarray([100.0, 101.2, 100.7, 102.1, 103.0], dtype=np.float64)
values = reflex(prices, period=20)
values_scalar = reflex(prices, period=20, kernel="scalar") Batch Sweeps ▾
Test multiple period values and analyze results:
from vectorta import reflex_batch
result = reflex_batch(prices, periods=(5, 50, 5), kernel="auto")
values = result["values"] # shape: (rows, len(prices))
periods = result["periods"] # vector of tested periods CUDA Acceleration ▾
CUDA-backed Python APIs for Reflex are available in the library behind a feature flag. Public packaging for this site is planned.
# Coming soon: CUDA-accelerated Reflex utilities
# from vectorta import reflex_cuda_batch_dev, reflex_cuda_many_series_one_param_dev
#
# # Example: sweep periods on GPU (float32 input)
# gpu = reflex_cuda_batch_dev(prices.astype(np.float32), (5, 50, 1), device_id=0)
#
# # Example: many series, one parameter set
# out = reflex_cuda_many_series_one_param_dev(matrix_tm_f32, period=20, device_id=0) JavaScript/WASM Bindings
Basic Usage ▼
Calculate Reflex in JavaScript/TypeScript:
import { reflex_js } from 'vectorta-wasm';
const prices = new Float64Array([100.0, 101.2, 100.7, 102.1, 103.0]);
const result = reflex_js(prices, 20); // period=20
console.log('Reflex values:', result); Memory-Efficient Operations ▼
Use zero-copy operations for better performance with large datasets:
import { reflex_alloc, reflex_free, reflex_into, memory } from 'vectorta-wasm';
const length = prices.length;
const inPtr = reflex_alloc(length);
const outPtr = reflex_alloc(length);
new Float64Array(memory.buffer, inPtr, length).set(prices);
reflex_into(inPtr, outPtr, length, 20);
const values = new Float64Array(memory.buffer, outPtr, length).slice();
reflex_free(inPtr, length);
reflex_free(outPtr, length); Batch Processing ▼
Test multiple period values efficiently:
import { reflex_batch_js, reflex_batch_metadata_js } from 'vectorta-wasm';
const prices = new Float64Array([/* historical prices */]);
const start = 5, end = 50, step = 5;
const meta = reflex_batch_metadata_js(start, end, step); // [p1, p2, ...]
const flat = reflex_batch_js(prices, start, end, step);
const block = prices.length;
const rows = meta.length;
const matrix = [];
for (let i = 0; i < rows; i++) {
matrix.push(flat.slice(i * block, (i + 1) * block));
} Performance Analysis
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05
CUDA note
In our benchmark workload, the Rust CPU implementation is faster than CUDA for this indicator. Prefer the Rust/CPU path unless your workload differs.
Related Indicators
Arnaud Legoux Moving Average
Moving average indicator
Compound Ratio Moving Average (CoRa Wave)
Moving average indicator
Centered Weighted Moving Average
Moving average indicator
Double Exponential Moving Average
Moving average indicator
Ehlers Distance Coefficient Filter
Moving average indicator
Ehlers Error-Correcting EMA (ECEMA)
Moving average indicator