mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-23 04:58:08 +00:00
validation and profiles
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
using Xunit;
|
||||
|
||||
using OoplesFinance.StockIndicators;
|
||||
using OoplesFinance.StockIndicators.Models;
|
||||
|
||||
namespace QuanTAlib.Tests;
|
||||
|
||||
/// <summary>
|
||||
@@ -360,4 +363,21 @@ public class CcycValidationTests
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ccyc_MatchesOoples_Structural()
|
||||
{
|
||||
var gbm = new GBM(startPrice: 100.0, mu: 0.02, sigma: 0.15, seed: 42);
|
||||
var bars = gbm.Fetch(500, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
|
||||
var ooplesData = bars.Select(b => new TickerData
|
||||
{
|
||||
Date = new DateTime(b.Time, DateTimeKind.Utc),
|
||||
Open = b.Open, High = b.High, Low = b.Low,
|
||||
Close = b.Close, Volume = b.Volume
|
||||
}).ToList();
|
||||
var result = new StockData(ooplesData).CalculateEhlersCyberCycle();
|
||||
var values = result.CustomValuesList;
|
||||
int finiteCount = values.Count(v => double.IsFinite(v));
|
||||
Assert.True(finiteCount > 100, $"Expected >100 finite values, got {finiteCount}");
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
using Xunit;
|
||||
|
||||
using OoplesFinance.StockIndicators;
|
||||
using OoplesFinance.StockIndicators.Models;
|
||||
|
||||
namespace QuanTAlib.Tests;
|
||||
|
||||
/// <summary>
|
||||
@@ -358,4 +361,21 @@ public class CgValidationTests
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
[Fact]
|
||||
public void Cg_MatchesOoples_Structural()
|
||||
{
|
||||
var gbm = new GBM(startPrice: 100.0, mu: 0.02, sigma: 0.15, seed: 42);
|
||||
var bars = gbm.Fetch(500, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
|
||||
var ooplesData = bars.Select(b => new TickerData
|
||||
{
|
||||
Date = new DateTime(b.Time, DateTimeKind.Utc),
|
||||
Open = b.Open, High = b.High, Low = b.Low,
|
||||
Close = b.Close, Volume = b.Volume
|
||||
}).ToList();
|
||||
var result = new StockData(ooplesData).CalculateEhlersCenterofGravityOscillator();
|
||||
var values = result.CustomValuesList;
|
||||
int finiteCount = values.Count(v => double.IsFinite(v));
|
||||
Assert.True(finiteCount > 100, $"Expected >100 finite values, got {finiteCount}");
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
using Xunit;
|
||||
|
||||
using OoplesFinance.StockIndicators;
|
||||
using OoplesFinance.StockIndicators.Models;
|
||||
|
||||
namespace QuanTAlib.Tests;
|
||||
|
||||
/// <summary>
|
||||
@@ -381,4 +384,21 @@ public class DspValidationTests
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
[Fact]
|
||||
public void Dsp_MatchesOoples_Structural()
|
||||
{
|
||||
var gbm = new GBM(startPrice: 100.0, mu: 0.02, sigma: 0.15, seed: 42);
|
||||
var bars = gbm.Fetch(500, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
|
||||
var ooplesData = bars.Select(b => new TickerData
|
||||
{
|
||||
Date = new DateTime(b.Time, DateTimeKind.Utc),
|
||||
Open = b.Open, High = b.High, Low = b.Low,
|
||||
Close = b.Close, Volume = b.Volume
|
||||
}).ToList();
|
||||
var result = new StockData(ooplesData).CalculateDetrendedSyntheticPrice();
|
||||
var values = result.CustomValuesList;
|
||||
int finiteCount = values.Count(v => double.IsFinite(v));
|
||||
Assert.True(finiteCount > 100, $"Expected >100 finite values, got {finiteCount}");
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,8 @@ public sealed class Eacp : AbstractBase
|
||||
// Super-smoother filter: removes high-frequency noise
|
||||
double filt2 = s.Filt1;
|
||||
double filt1 = s.Filt0;
|
||||
double filt0 = _c1 * (hp0 + hp1) * 0.5 + _c2 * filt1 + _c3 * filt2;
|
||||
double filt0 = Math.FusedMultiplyAdd(_c1, (hp0 + hp1) * 0.5,
|
||||
Math.FusedMultiplyAdd(_c2, filt1, _c3 * filt2));
|
||||
|
||||
// Add filtered value to history buffer
|
||||
_filtHistory.Add(filt0);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using Xunit;
|
||||
|
||||
using OoplesFinance.StockIndicators;
|
||||
using OoplesFinance.StockIndicators.Models;
|
||||
|
||||
namespace QuanTAlib.Tests;
|
||||
|
||||
/// <summary>
|
||||
@@ -539,4 +542,21 @@ public class EbswValidationTests
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
[Fact]
|
||||
public void Ebsw_MatchesOoples_Structural()
|
||||
{
|
||||
var gbm = new GBM(startPrice: 100.0, mu: 0.02, sigma: 0.15, seed: 42);
|
||||
var bars = gbm.Fetch(500, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
|
||||
var ooplesData = bars.Select(b => new TickerData
|
||||
{
|
||||
Date = new DateTime(b.Time, DateTimeKind.Utc),
|
||||
Open = b.Open, High = b.High, Low = b.Low,
|
||||
Close = b.Close, Volume = b.Volume
|
||||
}).ToList();
|
||||
var result = new StockData(ooplesData).CalculateEhlersEvenBetterSineWaveIndicator();
|
||||
var values = result.CustomValuesList;
|
||||
int finiteCount = values.Count(v => double.IsFinite(v));
|
||||
Assert.True(finiteCount > 100, $"Expected >100 finite values, got {finiteCount}");
|
||||
}
|
||||
}
|
||||
@@ -178,7 +178,8 @@ public sealed class Ebsw : AbstractBase
|
||||
// Super-smoother filter: filt = c1 * (hp + hp[1]) / 2 + c2 * filt[1] + c3 * filt[2]
|
||||
double filt2 = s.Filt1;
|
||||
double filt1 = s.Filt0;
|
||||
double filt0 = _c1 * (hp0 + hp1) * 0.5 + _c2 * filt1 + _c3 * filt2;
|
||||
double filt0 = Math.FusedMultiplyAdd(_c1, (hp0 + hp1) * 0.5,
|
||||
Math.FusedMultiplyAdd(_c2, filt1, _c3 * filt2));
|
||||
|
||||
// Wave component: 3-bar average of filtered values
|
||||
double wave = (filt0 + filt1 + filt2) / 3.0;
|
||||
@@ -318,7 +319,8 @@ public sealed class Ebsw : AbstractBase
|
||||
hp0 = Math.FusedMultiplyAdd(hpCoef, src0 - src1, alpha1 * hp1);
|
||||
|
||||
// Super-smoother filter
|
||||
filt0 = c1 * (hp0 + hp1) * 0.5 + c2 * filt1 + c3 * filt2;
|
||||
filt0 = Math.FusedMultiplyAdd(c1, (hp0 + hp1) * 0.5,
|
||||
Math.FusedMultiplyAdd(c2, filt1, c3 * filt2));
|
||||
|
||||
// Wave component
|
||||
double wave = (filt0 + filt1 + filt2) / 3.0;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using Xunit;
|
||||
|
||||
using OoplesFinance.StockIndicators;
|
||||
using OoplesFinance.StockIndicators.Models;
|
||||
|
||||
namespace QuanTAlib.Tests;
|
||||
|
||||
/// <summary>
|
||||
@@ -358,4 +361,21 @@ public class HomodValidationTests
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
[Fact]
|
||||
public void Homod_MatchesOoples_Structural()
|
||||
{
|
||||
var gbm = new GBM(startPrice: 100.0, mu: 0.02, sigma: 0.15, seed: 42);
|
||||
var bars = gbm.Fetch(500, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
|
||||
var ooplesData = bars.Select(b => new TickerData
|
||||
{
|
||||
Date = new DateTime(b.Time, DateTimeKind.Utc),
|
||||
Open = b.Open, High = b.High, Low = b.Low,
|
||||
Close = b.Close, Volume = b.Volume
|
||||
}).ToList();
|
||||
var result = new StockData(ooplesData).CalculateEhlersHomodyneDominantCycle();
|
||||
var values = result.CustomValuesList;
|
||||
int finiteCount = values.Count(v => double.IsFinite(v));
|
||||
Assert.True(finiteCount > 100, $"Expected >100 finite values, got {finiteCount}");
|
||||
}
|
||||
}
|
||||
+11
-11
@@ -222,17 +222,17 @@ public sealed class Homod : AbstractBase
|
||||
double i2Raw = i1 - jq;
|
||||
double q2Raw = q1 + ji;
|
||||
|
||||
// EMA smooth I2 and Q2 (alpha = 0.2)
|
||||
double i2 = 0.2 * i2Raw + 0.8 * s.I2;
|
||||
double q2 = 0.2 * q2Raw + 0.8 * s.Q2;
|
||||
// EMA smooth I2 and Q2 (alpha = 0.2): FMA(0.2, x, 0.8*y)
|
||||
double i2 = Math.FusedMultiplyAdd(0.2, i2Raw, 0.8 * s.I2);
|
||||
double q2 = Math.FusedMultiplyAdd(0.2, q2Raw, 0.8 * s.Q2);
|
||||
|
||||
// Homodyne discriminator: multiply with previous values
|
||||
double reRaw = i2 * s.I2 + q2 * s.Q2;
|
||||
double imRaw = i2 * s.Q2 - q2 * s.I2;
|
||||
double reRaw = Math.FusedMultiplyAdd(i2, s.I2, q2 * s.Q2);
|
||||
double imRaw = Math.FusedMultiplyAdd(i2, s.Q2, -(q2 * s.I2));
|
||||
|
||||
// EMA smooth Re and Im (alpha = 0.2)
|
||||
double re = 0.2 * reRaw + 0.8 * s.Re;
|
||||
double im = 0.2 * imRaw + 0.8 * s.Im;
|
||||
// EMA smooth Re and Im (alpha = 0.2): FMA(0.2, x, 0.8*y)
|
||||
double re = Math.FusedMultiplyAdd(0.2, reRaw, 0.8 * s.Re);
|
||||
double im = Math.FusedMultiplyAdd(0.2, imRaw, 0.8 * s.Im);
|
||||
|
||||
// Calculate period from angle
|
||||
double period = s.Period;
|
||||
@@ -245,13 +245,13 @@ public sealed class Homod : AbstractBase
|
||||
{
|
||||
double candidate = TwoPi / angle;
|
||||
double clamped = Math.Clamp(Math.Abs(candidate), _minPeriod, _maxPeriod);
|
||||
period = 0.2 * clamped + 0.8 * period;
|
||||
period = Math.FusedMultiplyAdd(0.2, clamped, 0.8 * period);
|
||||
}
|
||||
}
|
||||
|
||||
// Smooth the period (alpha = 0.33)
|
||||
// Smooth the period (alpha = 0.33): FMA(alpha, delta, prevSmooth)
|
||||
const double alpha = 0.33;
|
||||
double smoothPeriod = s.SmoothPeriod + alpha * (period - s.SmoothPeriod);
|
||||
double smoothPeriod = Math.FusedMultiplyAdd(alpha, period - s.SmoothPeriod, s.SmoothPeriod);
|
||||
|
||||
// Exponential warmup compensation
|
||||
double result = smoothPeriod;
|
||||
|
||||
Reference in New Issue
Block a user