Files
Miha Kralj 86fe32a682 SIMD Refactor: Merge simd-dev into dev (#55)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: aider (openrouter/anthropic/claude-sonnet-4) <aider@aider.chat>
Co-authored-by: Warp <agent@warp.dev>
2026-01-18 19:02:03 -08:00

8.0 KiB

Glossary

Reference for QuanTAlib terminology and types. Terms that confuse newcomers and occasionally even veterans.

Term Definition
Accuracy How well an indicator preserves meaningful structure of the original price series while filtering noise. A tension exists: more smoothness removes zigzagging noise but eventually erases meaningful swings and cycles. Finding the balance separates useful indicators from pretty lines that lie.
Array of Structs (AoS) Memory layout where each element is a full record: struct Bar { double Open, High, Low, Close; } stored as Bar[]. Simple to model but cache-inefficient for single-field operations and resistant to SIMD vectorization. QuanTAlib avoids this pattern. Structure of Arrays (SoA) performs better for numerical workloads.
AVX2 256-bit SIMD extension for x86-64 CPUs. Processes 4 doubles per instruction. Available on Intel Haswell (2013) and newer, AMD Excavator (2015) and newer. The baseline for modern vectorization.
AVX-512 512-bit SIMD extension. Processes 8 doubles per instruction. Available on Intel Skylake-X (2017) and newer server/desktop parts, AMD Zen 4 (2022) and newer. Doubles throughput over AVX2 for vectorizable workloads. Not universally available; code must fallback gracefully.
Batch Mode Indicators operating on TSeries objects instead of raw spans. Handles timestamps, resizing, and time alignment while using span-based implementations internally. Best for historical analysis where time-awareness matters but manual array management does not appeal.
Eventing Mode Reactive usage where indicators implement ITValuePublisher and raise events as values change or warmup completes. Used for indicator chains and trading logic that reacts to state changes instead of polling. More allocation overhead than streaming mode; justified when reactive architecture simplifies system design.
FIR Filter Finite Impulse Response filter. Output depends only on a finite window of past inputs with no feedback. Always stable. SMA, WMA, and HMA are FIR filters. The impulse response (output when given a single spike input) eventually reaches zero and stays there.
Hot Path Code that executes for every incoming tick or bar during live trading. In QuanTAlib, hot paths (Update, span-based Calculate loops) must avoid heap allocations, run in O(1) time where mathematically possible, and exploit SIMD when the algorithm permits. Everything else is commentary.
IIR Filter Infinite Impulse Response filter. Output depends on both current input and past outputs via feedback. More responsive for a given smoothness level but requires care for numerical stability. EMA, KAMA, and VIDYA are IIR filters. The impulse response theoretically never reaches exactly zero.
IsHot Boolean property that becomes true after sufficient data has been processed (typically once the warmup period completes). Before IsHot is true, output values are mathematically incomplete. Trust them at own risk.
isNew Flag Boolean parameter on Update(TValue input, bool isNew = true) controlling bar-correction behavior. isNew = true advances state to the next bar. isNew = false updates the most recent bar in-place for streaming feeds where the latest bar changes before closing. Getting this wrong produces subtle bugs that surface only in production.
NEON 128-bit SIMD architecture for ARM CPUs (Apple Silicon, Raspberry Pi, most mobile devices). .NET exposes NEON via System.Runtime.Intrinsics.Arm. Same span-based indicator code vectorizes on ARM without modification.
O(1) Constant-time complexity. Work per update does not grow with time series length or lookback window. Target complexity for streaming Update methods. When mathematics refuses to cooperate (median calculations, sorting), document the exception and accept the cost.
O(n) Linear-time complexity in input count. Acceptable for batch processing that walks the series once. Not acceptable for hot-path streaming updates.
O(n log n) Linearithmic complexity. Appears in sorting-based operations like median calculation. Unavoidable for some algorithms; the cost of mathematical necessity.
Overshoot Degree to which an indicator overreacts around turning points, swinging past the underlying price before settling. High overshoot produces dramatic signals that often mislead, especially near reversals. The excitement is rarely worth the false entries.
Period Configuration parameter describing how many bars an indicator considers. Critical for FIR filters (SMA-20 literally averages 20 bars). Less direct for IIR filters (EMA-20 has infinite memory but effective lookback roughly matches period).
RingBuffer Fixed-size circular buffer for sliding-window calculations. New values overwrite oldest entries once full. Keeps time and memory constant regardless of history length. Fundamental building block for O(1) streaming indicators.
SIMD Single Instruction, Multiple Data. Hardware feature allowing one instruction to process multiple values simultaneously. QuanTAlib exploits SIMD (AVX2, AVX-512, NEON) for span-based calculations. The difference between processing 1 million bars in 300 ¼s versus 3 ms.
Smoothness How visually and numerically calm an indicator's line appears. More smoothness filters random noise but increases lag. Less smoothness responds faster but exposes short-term fluctuation. No free lunch; the trade-off is fundamental.
Span Mode Lowest-level, zero-allocation mode operating on Span<double> / ReadOnlySpan<double>. Maximum SIMD acceleration, no object overhead. Designed for backtesting and research processing large arrays. The fastest path through the code.
Streaming Mode Real-time update mode using Update(TValue input, bool isNew = true). Maintains internal state between calls, distinguishes new bars from intra-bar corrections. Intended for live feeds and tick-by-tick data. The mode that matters when money is on the line.
Structure of Arrays (SoA) Memory layout where each field of a logical record is stored in its own contiguous buffer. Prices and timestamps live in separate arrays. Improves cache locality, enables vectorized operations across large segments of a single field. QuanTAlib's TSeries uses this layout.
TBar Struct representing an OHLCV bar: time, open, high, low, close, and volume. 48 bytes. Used when indicators need full bar context instead of a single price value.
Throughput Ticks or bars processed per second on given hardware. Driven by per-update complexity (target O(1)), SIMD utilization, and zero-allocation discipline. The metric that determines whether backtesting takes seconds or hours.
Timeliness How much an indicator lags behind the underlying price. Excessive lag pushes entries and exits late, cutting profits. Classic moving averages (SMA, WMA, EMA) trade smoothness for lag. Designs like DEMA, HMA, and JMA attempt to cheat this trade-off with varying success.
TSeries Primary time series container. Structure-of-arrays layout: timestamps and values in separate buffers, exposed as ReadOnlySpan<T> for SIMD-friendly access. The workhorse data structure for batch operations.
TValue Struct pairing a DateTime with a single double value. 16 bytes. Standard input and output type for streaming mode. Simple but sufficient for most indicator calculations.
Warmup Period Number of bars required before an indicator produces fully reliable output. During warmup, IsHot is false. Varies by indicator: SMA-20 needs 20 bars, some IIR filters need more. Ignoring warmup produces garbage outputs that look plausible.
Zero-Allocation Design Design rule that hot paths must not allocate on the managed heap. Achieved using Span<T>, stackalloc for small temporaries, and reusing internal state instead of creating new objects per update. The garbage collector cannot ruin latency if nothing creates garbage.