Helpers
rolling_mean/std, ta::sma/ema/rsi/atr_bid_ask, signal helpers (cross_above/below, above/below, between, rising/falling), imbalance/cvd/vwap_band.
ta::sma
ta::smafn sma(prices: &[f64], period: usize) -> Vec<f64>
Simple Moving Average. First period-1 entries are NaN.
Example
let sma_20 = ta::sma(&data.mid, 20);
ta::ema
ta::emafn ema(prices: &[f64], period: usize) -> Vec<f64>
Exponential Moving Average. Seeded with the SMA of the first window.
Example
let ema_50 = ta::ema(&data.mid, 50);
ta::rsi
ta::rsifn rsi(prices: &[f64], period: usize) -> Vec<f64>
Relative Strength Index using Wilder smoothing. First period entries are NaN.
Example
let rsi_14 = ta::rsi(&data.mid, 14);
ta::macd
ta::macdfn macd(prices: &[f64], fast: usize, slow: usize, signal: usize) -> (Vec<f64>, Vec<f64>, Vec<f64>)
MACD line, signal line, histogram.
Example
let (macd_line, signal_line, hist) = ta::macd(&data.mid, 12, 26, 9);
ta::bollinger
ta::bollingerfn bollinger(prices: &[f64], period: usize, std_mult: f64) -> (Vec<f64>, Vec<f64>, Vec<f64>)
Bollinger Bands: (upper, middle, lower).
Example
let (upper, middle, lower) = ta::bollinger(&data.mid, 20, 2.0);
ta::stddev
ta::stddevfn stddev(values: &[f64], period: usize) -> Vec<f64>
Rolling standard deviation (population).
Example
let vol = ta::stddev(&data.mid, 30);
ta::atr_bid_ask
ta::atr_bid_askfn atr_bid_ask(bid: &[f64], ask: &[f64], period: usize) -> Vec<f64>
Tick-native ATR equivalent: per-tick range = ask - bid (spread). ATR = SMA(spread, period).
Use this instead of bar-style ATR on TBBO data. The "true range" of a single tick is the spread itself.
Example
let atr = ta::atr_bid_ask(&data.bid, &data.ask, 30);
rolling_mean
rolling_meanfn rolling_mean(values: &[f64], period: usize) -> Vec<f64>
Sliding-window rolling mean with periodic rebuild to bound FP drift.
O(1) per tick via incremental sum (sum += values[i] - values[i - period]), with a full rebuild every period ticks to keep accumulated FP error from flipping signals at edge thresholds.
Example
let baseline = rolling_mean(&data.spread, 200);
rolling_std
rolling_stdfn rolling_std(values: &[f64], period: usize) -> Vec<f64>
Rolling standard deviation (population). Returns NaN for the warm-up window.
Example
let sd = rolling_std(&data.mid, 30);
imbalance (Rust)
imbalance (Rust)fn imbalance(bid: &[f64], ask: &[f64]) -> Vec<f64>
Per-tick bid / (bid + ask + epsilon). Range [0, 1]; 0.5 = balanced.
Example
let imb = imbalance(&data.bid_size, &data.ask_size);
cvd (Rust)
cvd (Rust)fn cvd(delta: &[f64]) -> Vec<f64>
Cumulative volume delta: running sum of a delta series.
Example
let cum = cvd(&data.col_or("delta", &[]));
vwap_band (Rust)
vwap_band (Rust)fn vwap_band(vwap: &[f64], atr: &[f64], mult: f64) -> (Vec<f64>, Vec<f64>)
VWAP envelope: (upper, lower) at mult * ATR.
Example
let (upper, lower) = vwap_band(&data.vwap, &atr, 1.5);
cross_above / cross_below
cross_above / cross_belowfn cross_above(a: &[f64], b: &[f64]) -> Vec<bool>
Element-wise cross detection between two series.
Returns true at index i when a[i-1] < b[i-1] && a[i] >= b[i] (or the symmetric case for cross_below). First element is always false.
Example
let buy = cross_above(&fast_ma, &slow_ma);
let sell = cross_below(&fast_ma, &slow_ma);
above / below / between
Threshold comparisons returning Vec
above(values, threshold) and below(values, threshold) are strict (> and <); between(values, lo, hi) is inclusive on both ends. NaN entries return false.
Example
let overbought = above(&rsi, 70.0);
let oversold = below(&rsi, 30.0);
let neutral = between(&rsi, 30.0, 70.0);
above_series / below_series
above_series / below_seriesfn above_series(a: &[f64], b: &[f64]) -> Vec<bool>
Element-wise series-vs-series comparison.
Example
let bull = above_series(&data.mid, &ema_200);
rising / falling
rising / fallingfn rising(values: &[f64], length: usize) -> Vec<bool>
True at index i when values[i] > values[i - length] (or < for falling). Warm-up returns false.
Example
let momentum_up = rising(&data.mid, 10);
barssince (Rust)
barssince (Rust)fn barssince(cond: &[bool]) -> Vec<u32>
Ticks since cond[i] was last true. u32::MAX before first occurrence.
Example
let bars_since_signal = barssince(&entry_long);
pad_to_len
pad_to_lenfn pad_to_len(values: &[f64], target_len: usize) -> Vec<f64>
Prepend NaN to a shorter indicator result so it aligns with full tick count.
Some indicator functions return n - period + 1 values starting at index period - 1. pad_to_len pads them back to length n with NaN so signal indexing stays aligned.
Example
let padded = pad_to_len(&truncated_indicator, data.len());