mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-07-28 01:37:43 +00:00
86fe32a682
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>
269 lines
9.6 KiB
Markdown
269 lines
9.6 KiB
Markdown
# 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<double>, Span<double>, int)` | Bulk calculation (batch) |
|
||
| `Prime` | `void Prime(ReadOnlySpan<double> 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
|
||
|