mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-23 04:58:08 +00:00
feat(tests): enhance tests with GBM for noise generation and improve tolerance for MAMA validation
feat(trends): implement IDisposable in Bessel and Conv classes to manage event subscriptions fix(trends): add validation for period and parameters in Kama and MGDI calculations fix(trends): clamp logarithmic calculations in JMA to avoid -Infinity
This commit is contained in:
@@ -45,10 +45,10 @@ public class MamaValidationTests
|
||||
var sResult = _testData.SkenderQuotes.GetMama(fastLimit, slowLimit).ToList();
|
||||
|
||||
// 3. Verify MAMA
|
||||
// Tolerance increased to 20.0 due to optimized Phase calculation (Atan2 vs Atan)
|
||||
// The optimized version handles quadrants correctly (-pi to pi) while original (and Skender)
|
||||
// uses Atan (-pi/2 to pi/2), causing divergence at quadrant transitions.
|
||||
ValidationHelper.VerifyData(qResult, sResult, x => x.Mama, skip: 100, tolerance: 20.0);
|
||||
// Tolerance increased to 40.0 due to optimized Phase calculation (Atan2 vs Atan) and Phase Wrapping correction.
|
||||
// The optimized version handles quadrants correctly (-pi to pi) and wraps phase differences (-pi to pi),
|
||||
// while original (and Skender) uses Atan (-pi/2 to pi/2) and ignores phase wrapping, causing divergence.
|
||||
ValidationHelper.VerifyData(qResult, sResult, x => x.Mama, skip: 100, tolerance: 40.0);
|
||||
|
||||
_output.WriteLine("MAMA Batch validated successfully against Skender");
|
||||
}
|
||||
@@ -76,11 +76,11 @@ public class MamaValidationTests
|
||||
var sResult = _testData.SkenderQuotes.GetMama(fastLimit, slowLimit).ToList();
|
||||
|
||||
// 3. Verify MAMA
|
||||
// Tolerance increased to 20.0 due to optimized Phase calculation (Atan2 vs Atan)
|
||||
ValidationHelper.VerifyData(qMamaResults, sResult, x => x.Mama, skip: 100, tolerance: 20.0);
|
||||
// Tolerance increased to 40.0 due to optimized Phase calculation and Phase Wrapping correction.
|
||||
ValidationHelper.VerifyData(qMamaResults, sResult, x => x.Mama, skip: 100, tolerance: 40.0);
|
||||
|
||||
// 4. Verify FAMA
|
||||
ValidationHelper.VerifyData(qFamaResults, sResult, x => x.Fama, skip: 100, tolerance: 20.0);
|
||||
ValidationHelper.VerifyData(qFamaResults, sResult, x => x.Fama, skip: 100, tolerance: 40.0);
|
||||
|
||||
_output.WriteLine("MAMA/FAMA Streaming validated successfully against Skender");
|
||||
}
|
||||
@@ -112,10 +112,11 @@ public class MamaValidationTests
|
||||
var qResult = mama.Update(_testData.Data); // _testData.Data is Close prices
|
||||
|
||||
// 3. Verify MAMA
|
||||
// Tolerance set to 30.0 due to significant divergence (~27.0) caused by:
|
||||
// Tolerance set to 40.0 due to significant divergence caused by:
|
||||
// 1. Initialization: Ooples starts from 0, QuanTAlib warms up with Average.
|
||||
// 2. Precision: Ooples uses 4-decimal constants, QuanTAlib uses exact fractions.
|
||||
ValidationHelper.VerifyData(qResult, oMama, x => x, skip: 100, tolerance: 30.0);
|
||||
// 3. Phase Wrapping: QuanTAlib correctly handles phase wrapping, Ooples does not.
|
||||
ValidationHelper.VerifyData(qResult, oMama, x => x, skip: 100, tolerance: 40.0);
|
||||
|
||||
// 4. Verify FAMA
|
||||
// QuanTAlib stores Fama in a separate property, not in the main TSeries result
|
||||
|
||||
+12
-2
@@ -99,6 +99,14 @@ public sealed class Mama : AbstractBase
|
||||
Fama = new TValue(DateTime.MinValue, double.NaN);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static double NormalizeAngle(double angle)
|
||||
{
|
||||
while (angle <= -Math.PI) angle += TwoPi;
|
||||
while (angle > Math.PI) angle -= TwoPi;
|
||||
return angle;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private double Step(double price, bool isNew)
|
||||
{
|
||||
@@ -188,7 +196,8 @@ public sealed class Mama : AbstractBase
|
||||
_state.Phase = Math.Atan2(q1, i1);
|
||||
|
||||
// Adaptive alpha
|
||||
double delta = Math.Max(_p_state.Phase - _state.Phase, MinDeltaRadians);
|
||||
double diff = NormalizeAngle(_p_state.Phase - _state.Phase);
|
||||
double delta = Math.Max(Math.Abs(diff), MinDeltaRadians);
|
||||
double alpha = _scaledFastLimit / delta;
|
||||
alpha = Math.Clamp(alpha, _slowLimit, _fastLimit);
|
||||
|
||||
@@ -383,7 +392,8 @@ public sealed class Mama : AbstractBase
|
||||
double phase = Math.Atan2(q1, i1);
|
||||
|
||||
// Adaptive alpha
|
||||
double delta = Math.Max(p_phase - phase, MinDeltaRadians);
|
||||
double diff = NormalizeAngle(p_phase - phase);
|
||||
double delta = Math.Max(Math.Abs(diff), MinDeltaRadians);
|
||||
double alpha = scaledFastLimit / delta;
|
||||
alpha = Math.Clamp(alpha, slowLimit, fastLimit);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user