quantedge-ta
A streaming technical analysis library for Rust. Correct, tested, documented.
Features
Type-safe convergence
Indicators return Option<Self::Output>. No value until there's enough data.
No silent NaN, no garbage early values. The type system enforces correctness.
For indicators with infinite memory (EMA), convergence enforcement is
configurable: opt in to suppress values until the seed's influence has decayed
below 1%.
Bring your own data
Indicators accept any type implementing the Ohlcv trait. No forced conversion
to a library-specific struct. Implement five required methods on your existing
type and you're done. Volume has a default implementation for data sources that
don't provide it.
O(1) incremental updates
Indicators maintain running state and update in constant time per tick. No re-scanning the window.
Live repainting
Indicators track bar boundaries using open_time. A kline with a new
open_time advances the window; same open_time replaces the current value.
Useful for trading terminals and real-time systems that need indicator values
on forming bars.
Typed outputs
Each indicator defines its own output type via an associated type on the
Indicator trait. SMA and EMA return f64. Bollinger Bands returns
BbValue { upper, middle, lower }. No downcasting, no enums, full type
safety.
Usage
use ;
use NonZero;
let mut sma = new;
for kline in stream
Bollinger Bands returns a struct:
use ;
use NonZero;
let config = builder
.length
.build;
let mut bb = new;
for kline in stream
Custom standard deviation multiplier:
use ;
use NonZero;
let config = builder
.length
.std_dev
.build;
Live data with repainting:
// Open kline arrives (open_time = 1000)
sma.compute; // computes with current bar
// Same bar, new trade (open_time = 1000, updated close)
sma.compute; // replaces current bar value
// Next bar (open_time = 2000)
sma.compute; // advances the window
The caller controls bar boundaries. The library handles the rest.
Indicator Trait
Each indicator defines its output type. No downcasting needed:
// Sma: Output = f64
// Ema: Output = f64
// Bb: Output = BbValue { upper: f64, middle: f64, lower: f64 }
Ohlcv Trait
Implement the Ohlcv trait on your own data type:
use ;
Convergence
SMA and BB converge as soon as the window fills (length bars). EMA has
infinite memory; the SMA seed influences all subsequent values. EmaConfig
provides methods to control this:
enforce_convergence()-- whentrue,compute()returnsNoneuntil the seed's contribution decays below 1%.required_bars_to_converge()-- returns the number of bars needed.
use ;
use NonZero;
let config = builder
.length
.enforce_convergence // None until ~63 bars
.build;
config.required_bars_to_converge; // 63 = 3 * (20 + 1)
Use required_bars_to_converge() to determine how much history to fetch before
going live.
Price Sources
Each indicator is configured with a PriceSource that determines which value
to extract from the Ohlcv input:
| Source | Formula |
|---|---|
| Close | close |
| Open | open |
| High | high |
| Low | low |
| HL2 | (high + low) / 2 |
| HLC3 | (high + low + close) / 3 |
| OHLC4 | (open + high + low + close) / 4 |
| HLCC4 | (high + low + close + close) / 4 |
| TrueRange | max(high - low, |high - prev_close|, |low - prev_close|) |
Indicators
v0.1
| Indicator | Output | Description |
|---|---|---|
| SMA | f64 |
Simple Moving Average |
| EMA | f64 |
Exponential Moving Average |
| BB | BbValue |
Bollinger Bands (upper, mid, lower) |
Planned
RSI, MACD, ATR, CHOP, and more.
Benchmarks
Measured with Criterion.rs on 744 BTC/USDT 1-hour bars from Binance.
Stream measures end-to-end throughput including window fill. Tick isolates steady-state per-bar cost on a fully converged indicator.
Hardware: Apple M3 Max (16 cores), 48 GB RAM, macOS 26.3, rustc 1.93.1,
--release profile.
Stream — process 744 bars from cold start
| Indicator | Period | Time (median) | Throughput |
|---|---|---|---|
| SMA | 20 | 3.05 µs | 243 Melem/s |
| SMA | 200 | 2.89 µs | 257 Melem/s |
| EMA | 20 | 3.26 µs | 228 Melem/s |
| EMA | 200 | 3.24 µs | 229 Melem/s |
| BB | 20 | 5.47 µs | 136 Melem/s |
| BB | 200 | 4.19 µs | 177 Melem/s |
Tick — single compute() on a converged indicator
| Indicator | Period | Time (median) |
|---|---|---|
| SMA | 20 | 21.8 ns |
| SMA | 200 | 29.5 ns |
| EMA | 20 | 19.2 ns |
| EMA | 200 | 18.4 ns |
| BB | 20 | 23.7 ns |
| BB | 200 | 32.7 ns |
Run locally:
Minimum Supported Rust Version
1.93
Licence
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contributing
Contributions welcome. Please open an issue before submitting large changes.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 licence, shall be dual-licensed as above, without any additional terms or conditions.