mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-17 18:18:04 +00:00
v0.8.7: Replace periodic ResyncInterval with Kahan compensated summation
Comprehensive refactor across all indicators replacing the periodic ResyncInterval-based drift correction (every 1000 ticks recalculate from scratch) with Kahan compensated summation for running sums. Key changes: - Remove ResyncInterval constants and TickCount fields from all State records - Add Kahan compensation fields (SumComp, SumSqComp, etc.) to State records - Replace naive sum += val - removed with Kahan delta pattern - Remove Resync()/RecalculateSum() methods that did O(N) recalculation - Update batch/SIMD paths to use Kahan compensation instead of resync loops - IIR filters (EMA, REMA, RGMA) simplified: inherently self-correcting - Version bump to 0.8.7 - Build system: README version stamping via Directory.Build.props - Minor doc/test tolerance adjustments for new numerical characteristics Affected modules: channels, core, cycles, dynamics, errors, momentum, oscillators, statistics, trends_FIR, trends_IIR, volatility, volume
This commit is contained in:
@@ -32,10 +32,11 @@ public delegate void BiInputBatchDelegate(
|
||||
///
|
||||
/// Infrastructure provided:
|
||||
/// - _p_state / _buffer.Snapshot() / _buffer.Restore() for bar correction (isNew semantics)
|
||||
/// - RingBuffer-based sliding window with a single running sum
|
||||
/// - Periodic resync every 1000 updates for floating-point drift correction
|
||||
/// - RingBuffer-based sliding window with a single Kahan compensated running sum
|
||||
/// - NaN/Infinity handling with last-valid-value substitution
|
||||
/// - Template Method pattern: subclasses only implement ComputeError and optionally PostProcess
|
||||
///
|
||||
/// Kahan compensated summation prevents floating-point drift without periodic resync.
|
||||
/// </remarks>
|
||||
[SkipLocalsInit]
|
||||
public abstract class BiInputIndicatorBase : AbstractBase
|
||||
@@ -43,13 +44,11 @@ public abstract class BiInputIndicatorBase : AbstractBase
|
||||
protected readonly RingBuffer _buffer;
|
||||
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
protected record struct BiInputState(double Sum, double LastValidActual, double LastValidPredicted, int TickCount);
|
||||
protected record struct BiInputState(double Sum, double Compensation, double LastValidActual, double LastValidPredicted);
|
||||
|
||||
protected BiInputState _state;
|
||||
protected BiInputState _p_state;
|
||||
|
||||
protected const int ResyncInterval = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a bi-input indicator with specified period.
|
||||
/// </summary>
|
||||
@@ -141,15 +140,17 @@ public abstract class BiInputIndicatorBase : AbstractBase
|
||||
_p_state = _state;
|
||||
// Snapshot buffer state BEFORE Add so Restore can undo it
|
||||
_buffer.Snapshot();
|
||||
_state.Sum = _state.Sum - GetRemovedValue() + error;
|
||||
_buffer.Add(error);
|
||||
_state.TickCount++;
|
||||
|
||||
if (_buffer.IsFull && _state.TickCount >= ResyncInterval)
|
||||
// Kahan compensated sliding window update
|
||||
double delta = error - GetRemovedValue();
|
||||
{
|
||||
_state.TickCount = 0;
|
||||
_state.Sum = _buffer.RecalculateSum();
|
||||
double y = delta - _state.Compensation;
|
||||
double t = _state.Sum + y;
|
||||
_state.Compensation = (t - _state.Sum) - y;
|
||||
_state.Sum = t;
|
||||
}
|
||||
|
||||
_buffer.Add(error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user