Add Span API for SMA, EMA, and WMA with zero-allocation performance improvements

- Implemented zero-allocation methods for SMA, EMA, and WMA calculations using ReadOnlySpan and Span.
- Added unit tests for Span API to validate input, match TSeries calculations, handle NaN values, and ensure zero allocation.
- Enhanced documentation to include usage examples for the new Span API.
- Introduced performance benchmarks comparing the new Span API against existing TSeries implementations and other libraries.
This commit is contained in:
Miha Kralj
2025-11-29 20:48:01 -08:00
parent 5c1fb18520
commit 2d28b8f62a
12 changed files with 936 additions and 3 deletions
+34 -1
View File
@@ -77,11 +77,44 @@ Console.WriteLine($"Current EMA: {result.Value}");
// Access current value property
Console.WriteLine($"Current Value: {ema.Value.Value}");
// Batch calculation
// Batch calculation (TSeries API)
TSeries source = ...;
TSeries results = Ema.Calculate(source, 10);
// High-performance Span API (zero allocation)
double[] prices = new double[10000];
double[] output = new double[10000];
Ema.Calculate(prices.AsSpan(), output.AsSpan(), period: 10);
// Or with direct alpha:
Ema.Calculate(prices.AsSpan(), output.AsSpan(), alpha: 0.1818);
```
### Zero-Allocation Span API
For performance-critical scenarios (backtesting, HFT), use the Span-based overload:
```csharp
// Allocate buffers once, reuse across calculations
double[] source = new double[200000];
double[] emaOutput = new double[200000];
// Zero heap allocation during calculation - by period
Ema.Calculate(source.AsSpan(), emaOutput.AsSpan(), period: 100);
// Or by alpha for direct control
Ema.Calculate(source.AsSpan(), emaOutput.AsSpan(), alpha: 0.02);
// Results are written directly to output buffer
Console.WriteLine($"Last EMA: {emaOutput[^1]}");
```
**Benefits:**
* **Zero allocation**: No GC pressure during calculation
* **Cache-friendly**: Sequential memory access patterns
* **Hunter's bias correction**: Same accuracy as TSeries API
* **Compatible** with `ArrayPool<T>` for buffer management
### Multi-Alpha EMA (`EmaVector`)
The `EmaVector` class is a SIMD-optimized implementation for calculating multiple EMAs with different periods on the same input series simultaneously. It leverages hardware intrinsics (AVX/SSE) for high performance.