mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-15 17:18:05 +00:00
Merge dev into main: v0.8.7 Kahan compensated summation
This commit is contained in:
+21
-14
@@ -41,14 +41,13 @@ public sealed class Aberr : ITValuePublisher, IDisposable
|
||||
private ITValuePublisher? _source;
|
||||
private bool _disposed;
|
||||
|
||||
private const int ResyncInterval = 1000;
|
||||
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
private record struct State(
|
||||
double SumSource,
|
||||
double SumDeviation,
|
||||
double LastValidValue,
|
||||
int TickCount
|
||||
double SumSourceComp,
|
||||
double SumDeviationComp,
|
||||
double LastValidValue
|
||||
);
|
||||
private State _state;
|
||||
private State _pState;
|
||||
@@ -164,19 +163,20 @@ public sealed class Aberr : ITValuePublisher, IDisposable
|
||||
double removedSource = _sourceBuffer.Count == _sourceBuffer.Capacity ? _sourceBuffer.Oldest : 0.0;
|
||||
double removedDeviation = _deviationBuffer.Count == _deviationBuffer.Capacity ? _deviationBuffer.Oldest : 0.0;
|
||||
|
||||
_state.SumSource = _state.SumSource - removedSource + value;
|
||||
_state.SumDeviation = _state.SumDeviation - removedDeviation + deviation;
|
||||
// Kahan compensated summation for SumSource
|
||||
double srcDelta = value - removedSource - _state.SumSourceComp;
|
||||
double srcNewSum = _state.SumSource + srcDelta;
|
||||
_state.SumSourceComp = (srcNewSum - _state.SumSource) - srcDelta;
|
||||
_state.SumSource = srcNewSum;
|
||||
|
||||
// Kahan compensated summation for SumDeviation
|
||||
double devDelta = deviation - removedDeviation - _state.SumDeviationComp;
|
||||
double devNewSum = _state.SumDeviation + devDelta;
|
||||
_state.SumDeviationComp = (devNewSum - _state.SumDeviation) - devDelta;
|
||||
_state.SumDeviation = devNewSum;
|
||||
|
||||
_sourceBuffer.Add(value);
|
||||
_deviationBuffer.Add(deviation);
|
||||
|
||||
_state.TickCount++;
|
||||
if (_sourceBuffer.IsFull && _state.TickCount >= ResyncInterval)
|
||||
{
|
||||
_state.TickCount = 0;
|
||||
_state.SumSource = _sourceBuffer.RecalculateSum();
|
||||
_state.SumDeviation = _deviationBuffer.RecalculateSum();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -218,6 +218,8 @@ public sealed class Aberr : ITValuePublisher, IDisposable
|
||||
{
|
||||
SumSource = currentSum,
|
||||
SumDeviation = _deviationBuffer.Sum,
|
||||
SumSourceComp = 0,
|
||||
SumDeviationComp = 0,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -450,6 +452,11 @@ public sealed class Aberr : ITValuePublisher, IDisposable
|
||||
}
|
||||
#pragma warning restore MA0077
|
||||
|
||||
/// <summary>
|
||||
/// Resync interval for batch path only (streaming uses Kahan compensation).
|
||||
/// </summary>
|
||||
private const int ResyncInterval = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// Internal state for scalar calculation.
|
||||
/// </summary>
|
||||
|
||||
@@ -39,17 +39,17 @@ public sealed class AccBands : ITValuePublisher, IDisposable
|
||||
private TBarSeries? _source;
|
||||
private bool _disposed;
|
||||
|
||||
private const int ResyncInterval = 1000;
|
||||
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
private record struct State(
|
||||
double SumAdjHigh,
|
||||
double SumAdjLow,
|
||||
double SumClose,
|
||||
double SumAdjHighComp,
|
||||
double SumAdjLowComp,
|
||||
double SumCloseComp,
|
||||
double LastValidHigh,
|
||||
double LastValidLow,
|
||||
double LastValidClose,
|
||||
int TickCount
|
||||
double LastValidClose
|
||||
);
|
||||
private State _state;
|
||||
private State _p_state;
|
||||
@@ -208,22 +208,27 @@ public sealed class AccBands : ITValuePublisher, IDisposable
|
||||
double removedAdjLow = _adjLowBuffer.Count == _adjLowBuffer.Capacity ? _adjLowBuffer.Oldest : 0.0;
|
||||
double removedClose = _closeBuffer.Count == _closeBuffer.Capacity ? _closeBuffer.Oldest : 0.0;
|
||||
|
||||
_state.SumAdjHigh = _state.SumAdjHigh - removedAdjHigh + adjHigh;
|
||||
_state.SumAdjLow = _state.SumAdjLow - removedAdjLow + adjLow;
|
||||
_state.SumClose = _state.SumClose - removedClose + close;
|
||||
// Kahan compensated summation for SumAdjHigh
|
||||
double ahDelta = adjHigh - removedAdjHigh - _state.SumAdjHighComp;
|
||||
double ahNewSum = _state.SumAdjHigh + ahDelta;
|
||||
_state.SumAdjHighComp = (ahNewSum - _state.SumAdjHigh) - ahDelta;
|
||||
_state.SumAdjHigh = ahNewSum;
|
||||
|
||||
// Kahan compensated summation for SumAdjLow
|
||||
double alDelta = adjLow - removedAdjLow - _state.SumAdjLowComp;
|
||||
double alNewSum = _state.SumAdjLow + alDelta;
|
||||
_state.SumAdjLowComp = (alNewSum - _state.SumAdjLow) - alDelta;
|
||||
_state.SumAdjLow = alNewSum;
|
||||
|
||||
// Kahan compensated summation for SumClose
|
||||
double clDelta = close - removedClose - _state.SumCloseComp;
|
||||
double clNewSum = _state.SumClose + clDelta;
|
||||
_state.SumCloseComp = (clNewSum - _state.SumClose) - clDelta;
|
||||
_state.SumClose = clNewSum;
|
||||
|
||||
_adjHighBuffer.Add(adjHigh);
|
||||
_adjLowBuffer.Add(adjLow);
|
||||
_closeBuffer.Add(close);
|
||||
|
||||
_state.TickCount++;
|
||||
if (_closeBuffer.IsFull && _state.TickCount >= ResyncInterval)
|
||||
{
|
||||
_state.TickCount = 0;
|
||||
_state.SumAdjHigh = _adjHighBuffer.RecalculateSum();
|
||||
_state.SumAdjLow = _adjLowBuffer.RecalculateSum();
|
||||
_state.SumClose = _closeBuffer.RecalculateSum();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -264,6 +269,9 @@ public sealed class AccBands : ITValuePublisher, IDisposable
|
||||
SumAdjHigh = _adjHighBuffer.Sum,
|
||||
SumAdjLow = _adjLowBuffer.Sum,
|
||||
SumClose = _closeBuffer.Sum,
|
||||
SumAdjHighComp = 0,
|
||||
SumAdjLowComp = 0,
|
||||
SumCloseComp = 0,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -448,15 +456,7 @@ public sealed class AccBands : ITValuePublisher, IDisposable
|
||||
_adjHighBuffer.Clear();
|
||||
_adjLowBuffer.Clear();
|
||||
_closeBuffer.Clear();
|
||||
_state = new State(
|
||||
SumAdjHigh: 0,
|
||||
SumAdjLow: 0,
|
||||
SumClose: 0,
|
||||
LastValidHigh: double.NaN,
|
||||
LastValidLow: double.NaN,
|
||||
LastValidClose: double.NaN,
|
||||
TickCount: 0
|
||||
);
|
||||
_state = default;
|
||||
_p_state = _state;
|
||||
Last = default;
|
||||
Upper = default;
|
||||
@@ -553,6 +553,11 @@ public sealed class AccBands : ITValuePublisher, IDisposable
|
||||
}
|
||||
#pragma warning restore MA0077
|
||||
|
||||
/// <summary>
|
||||
/// Resync interval for batch path only (streaming uses Kahan compensation).
|
||||
/// </summary>
|
||||
private const int ResyncInterval = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// Internal state for scalar calculation.
|
||||
/// </summary>
|
||||
|
||||
@@ -39,24 +39,23 @@ public sealed class AtrBands : ITValuePublisher, IDisposable
|
||||
private bool _disposed;
|
||||
|
||||
private const double ConvergenceThreshold = 1e-10;
|
||||
private const int ResyncInterval = 1000;
|
||||
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
private record struct State(
|
||||
double SumSource,
|
||||
double SumSourceComp,
|
||||
double RawRma,
|
||||
double E,
|
||||
double PrevClose,
|
||||
double LastValidSource,
|
||||
double LastValidHigh,
|
||||
double LastValidLow,
|
||||
double LastValidClose,
|
||||
int TickCount
|
||||
double LastValidClose
|
||||
)
|
||||
{
|
||||
public static State New() => new()
|
||||
{
|
||||
SumSource = 0,
|
||||
SumSourceComp = 0,
|
||||
RawRma = 0,
|
||||
E = 1.0,
|
||||
PrevClose = double.NaN,
|
||||
@@ -64,7 +63,6 @@ public sealed class AtrBands : ITValuePublisher, IDisposable
|
||||
LastValidHigh = double.NaN,
|
||||
LastValidLow = double.NaN,
|
||||
LastValidClose = double.NaN,
|
||||
TickCount = 0,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -266,20 +264,19 @@ public sealed class AtrBands : ITValuePublisher, IDisposable
|
||||
if (isNew)
|
||||
{
|
||||
double removed = _sourceBuffer.Count == _sourceBuffer.Capacity ? _sourceBuffer.Oldest : 0.0;
|
||||
_state.SumSource = _state.SumSource - removed + source;
|
||||
_sourceBuffer.Add(source);
|
||||
|
||||
_state.TickCount++;
|
||||
if (_sourceBuffer.IsFull && _state.TickCount >= ResyncInterval)
|
||||
{
|
||||
_state.TickCount = 0;
|
||||
_state.SumSource = _sourceBuffer.RecalculateSum();
|
||||
}
|
||||
// Kahan compensated summation for SumSource
|
||||
double delta = source - removed - _state.SumSourceComp;
|
||||
double newSum = _state.SumSource + delta;
|
||||
_state.SumSourceComp = (newSum - _state.SumSource) - delta;
|
||||
_state.SumSource = newSum;
|
||||
_sourceBuffer.Add(source);
|
||||
}
|
||||
else
|
||||
{
|
||||
_sourceBuffer.UpdateNewest(source);
|
||||
_state.SumSource = _sourceBuffer.Sum;
|
||||
_state.SumSourceComp = 0;
|
||||
}
|
||||
|
||||
// Calculate ATR using RMA with warmup compensation
|
||||
|
||||
Reference in New Issue
Block a user