Reflex

Parameters: 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; NoData on empty input; AllValuesNaN if no finite values.
  • Requires at least period valid points after the first finite value; else NotEnoughData { needed, found }.
  • Warmup: the first period outputs are 0.0 by contract (batch); streaming yields None until 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

Comparison:
View:
Loading chart...

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