# API Reference QuanTAlib employs a Tri-Modal Architecture to unify high-performance batch processing with low-latency streaming updates. This design addresses the fundamental tension in quantitative finance: backtesting requires processing millions of bars quickly, while live trading requires sub-microsecond updates with zero allocation. All indicators inherit from `AbstractBase` and implement `ITValuePublisher`. The API is consistent across every indicator in the library. ## Core Interface Every indicator exposes these properties and methods: ### Properties | Property | Type | Description | | :------- | :--- | :---------- | | `Name` | `string` | Descriptive identifier (e.g., `"Sma(14)"`) | | `Last` | `TValue` | Most recent calculated value (timestamp + value) | | `IsHot` | `bool` | True when enough data has accumulated for valid output | | `WarmupPeriod` | `int` | Samples required before `IsHot` becomes true | | `Pub` | `event` | Fires when a new value is calculated (reactive mode) | ### Methods | Method | Signature | Purpose | | :----- | :-------- | :------ | | `Update` | `TValue Update(TValue input, bool isNew = true)` | Process single value (streaming) | | `Batch` | `static void Batch(ReadOnlySpan, Span, int)` | Bulk calculation (batch) | | `Prime` | `void Prime(ReadOnlySpan source)` | Initialize state from history | | `Reset` | `void Reset()` | Clear state, return to initial condition | ## Mode A: Batch Processing **Use case:** Backtesting, historical analysis, optimization runs. Batch mode provides stateless, SIMD-accelerated processing. Zero heap allocation. Maximum throughput. ### Span-Based (Zero Allocation) The fastest path. Operates directly on memory spans. Uses AVX2/AVX-512/NEON instructions where available. ```csharp double[] prices = LoadHistoricalData(); // 1,000,000 bars double[] results = new double[prices.Length]; // In-place calculation, zero allocation Sma.Batch(prices.AsSpan(), results.AsSpan(), period: 14); ``` Performance: 500,000 bars in ~320 ¼s on modern hardware. ### TSeries-Based (Convenience) Wrapper for timestamp-aligned series. Slightly slower, but handles metadata. ```csharp TSeries history = LoadTimeSeriesData(); TSeries smaValues = Sma.Batch(history, period: 14); // Timestamps preserved and aligned Console.WriteLine($"SMA at {smaValues[100].Time}: {smaValues[100].Value}"); ``` ## Mode B: Streaming Updates **Use case:** Live trading, real-time charting, tick-by-tick processing. Streaming mode handles sequential data with O(1) complexity per update. Internal state (circular buffers, running sums) enables sub-microsecond latency. ### Standard Update ```csharp var sma = new Sma(period: 14); foreach (var bar in liveDataFeed) { TValue result = sma.Update(new TValue(bar.Time, bar.Close)); if (result.IsHot) { // Valid output, safe to use for trading decisions ProcessSignal(result.Value); } } ``` ### Bar Correction (isNew Parameter) Markets send corrections. The `isNew` parameter distinguishes between new bars and updates to the current bar. ```csharp var indicator = new Sma(14); // Bar opens at 09:30:00 indicator.Update(new TValue(time_0930, 100.0), isNew: true); // Ticks update current bar (same timestamp) indicator.Update(new TValue(time_0930, 100.5), isNew: false); // Correction indicator.Update(new TValue(time_0930, 101.2), isNew: false); // Correction indicator.Update(new TValue(time_0930, 100.8), isNew: false); // Correction // New bar opens at 09:31:00 indicator.Update(new TValue(time_0931, 101.0), isNew: true); ``` When `isNew: false`, the indicator rolls back to the previous state before applying the new value. No cumulative drift from repeated corrections. ### Reactive Chaining Indicators subscribe to `ITValuePublisher` sources. Updates propagate automatically. ```csharp var source = new TSeries(); var sma = new Sma(source, period: 14); // Subscribes to source var ema = new Ema(sma, period: 5); // Subscribes to sma // Single add triggers cascade: source ’ sma ’ ema source.Add(new TValue(DateTime.UtcNow, 100.0)); ``` Event-based chaining enables complex indicator pipelines without manual orchestration. ## Mode C: Priming **Use case:** Transitioning from historical data to live streaming. Priming hydrates a streaming instance using the minimal tail of historical data. The indicator processes only enough history to fill its internal buffers, then becomes ready for live updates. ```csharp var indicator = new Sma(period: 14); double[] history = LoadHistoricalData(); // 100,000 bars // Processes only the last ~14 bars needed for state // O(warmup) initialization instead of O(history) indicator.Prime(history.AsSpan()); Console.WriteLine(indicator.IsHot); // true Console.WriteLine(indicator.Last); // Contains valid value // Ready for live data indicator.Update(nextLiveTick); ``` ## One-Shot Hybrid (Calculate) Combines batch processing with priming. Returns both the complete historical results and a warmed-up instance ready for streaming. ```csharp TSeries history = LoadTimeSeriesData(); // Single call: batch process history + prime indicator var (results, indicator) = Sma.Calculate(history, period: 14); // 'results' contains full calculated history PlotChart(results); // 'indicator' is warmed up, ready for live updates indicator.Update(nextLiveTick); ``` This pattern eliminates the common mistake of running batch calculation, then creating a separate streaming instance that starts cold. ## Validity and Convergence ### IsHot Property `IsHot` indicates whether the indicator has accumulated enough data for mathematically valid output. | Indicator Type | Warmup Period | IsHot Becomes True | | :------------- | :------------ | :----------------- | | Fixed-window (SMA, RSI) | `period` | After `period` bars | | Recursive (EMA, MACD) | `~3 × period` | After convergence threshold | | Multi-component (Bollinger) | `max(period, stddev_period)` | After longest component | ### Streaming Context ```csharp var sma = new Sma(10); for (int i = 0; i < 15; i++) { var result = sma.Update(new TValue(DateTime.UtcNow, prices[i])); Console.WriteLine($"Bar {i}: IsHot = {result.IsHot}"); } // Bars 0-8: IsHot = false // Bars 9-14: IsHot = true ``` ### Batch Context Batch output contains "cold" values at the beginning. The number of cold values equals `WarmupPeriod`. ```csharp TSeries results = Sma.Batch(history, period: 14); // Skip cold values when analyzing for (int i = 13; i < results.Count; i++) // Start at index 13 (period - 1) { ProcessValidValue(results[i]); } ``` For recursive indicators (EMA, DEMA, T3), the warmup extends beyond the nominal period. A 14-period EMA requires approximately 42 bars (3 × period) to converge within 1% of the true value. ## Architecture Diagram ```text   QuanTAlib Tri-Modal API  $    Historical Data Live Data       ¼         Batch       Mode      ,           Results     ¼ ¼ ¼       Backtest   Streaming     Output   Mode     ,      $       ¼ ¼        Prime  ¶ IsHot     Mode  Hydrate State  = true          ``` ## Error Handling ### Invalid Parameters Constructors validate parameters and throw `ArgumentException` with the parameter name. ```csharp try { var sma = new Sma(period: 0); // Invalid } catch (ArgumentException ex) { // ex.ParamName == "period" // ex.Message contains "must be greater than 0" } ``` ### NaN and Infinity Handling When input contains non-finite values (`NaN`, `+`, `-`), QuanTAlib substitutes the last valid value. This prevents NaN propagation through indicator chains. ```csharp var sma = new Sma(14); sma.Update(new TValue(t1, 100.0)); // Valid sma.Update(new TValue(t2, double.NaN)); // Uses 100.0 internally sma.Update(new TValue(t3, 101.0)); // Valid ``` The output never contains NaN unless all inputs were NaN. ## Thread Safety QuanTAlib indicators are not thread-safe. Each indicator instance should be accessed from a single thread. For multi-threaded scenarios, create separate indicator instances per thread or implement external synchronization.