Dpo chart + refactored tests

This commit is contained in:
Miha Kralj
2024-11-07 09:55:19 -08:00
parent a0ffd952af
commit 69aef2b127
8 changed files with 416 additions and 864 deletions
+4
View File
@@ -46,6 +46,10 @@
<ProjectReference Include="..\quantower\Volatility\_Volatility.csproj" Aliases="volatility" />
<ProjectReference Include="..\quantower\Averages\_Averages.csproj" Aliases="averages" />
<ProjectReference Include="..\quantower\Statistics\_Statistics.csproj" Aliases="statistics" />
<ProjectReference Include="..\quantower\Momentum\_Momentum.csproj" Aliases="momentum" />
<ProjectReference Include="..\quantower\Oscillators\_Oscillators.csproj" Aliases="oscillators" />
<ProjectReference Include="..\quantower\Volume\_Volume.csproj" Aliases="volume" />
<ProjectReference Include="..\quantower\Experiments\_Experiments.csproj" Aliases="experiments" />
</ItemGroup>
</Project>
+91
View File
@@ -0,0 +1,91 @@
using Xunit;
using System.Security.Cryptography;
namespace QuanTAlib.Tests;
public abstract class UpdateTestBase
{
protected readonly RandomNumberGenerator rng = RandomNumberGenerator.Create();
protected const int RandomUpdates = 100;
protected const double ReferenceValue = 100.0;
protected const int precision = 8;
protected double GetRandomDouble()
{
byte[] bytes = new byte[8];
rng.GetBytes(bytes);
return ((double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200) - 100; // Range: -100 to 100
}
protected TBar GetRandomBar(bool IsNew)
{
double open = GetRandomDouble();
double high = open + Math.Abs(GetRandomDouble());
double low = open - Math.Abs(GetRandomDouble());
double close = low + ((high - low) * GetRandomDouble());
return new TBar(DateTime.Now, open, high, low, close, 1000, IsNew);
}
protected void TestTValueUpdate<T>(T indicator, Func<TValue, TValue> calc) where T : class
{
var initialValue = calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
var finalValue = calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue.Value, finalValue.Value, precision);
}
protected void TestTBarUpdate<T>(T indicator, Func<TBar, TValue> calc) where T : class
{
TBar r = GetRandomBar(true);
var initialValue = calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
calc(GetRandomBar(IsNew: false));
}
var finalValue = calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue.Value, finalValue.Value, precision);
}
protected void TestDualTValueUpdate<T>(T indicator, Func<TValue, TValue, TValue> calc) where T : class
{
var initialValue = calc(
new TValue(DateTime.Now, ReferenceValue, IsNew: true),
new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
calc(
new TValue(DateTime.Now, GetRandomDouble(), IsNew: false),
new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
var finalValue = calc(
new TValue(DateTime.Now, ReferenceValue, IsNew: false),
new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue.Value, finalValue.Value, precision);
}
protected void TestDualTBarUpdate<T>(T indicator, Func<TBar, TBar, TValue> calc) where T : class
{
TBar bar1 = GetRandomBar(true);
TBar bar2 = GetRandomBar(true);
var initialValue = calc(bar1, bar2);
for (int i = 0; i < RandomUpdates; i++)
{
calc(GetRandomBar(false), GetRandomBar(false));
}
var finalValue = calc(
new TBar(bar1.Time, bar1.Open, bar1.High, bar1.Low, bar1.Close, bar1.Volume, false),
new TBar(bar2.Time, bar2.Open, bar2.High, bar2.Low, bar2.Close, bar2.Volume, false));
Assert.Equal(initialValue.Value, finalValue.Value, precision);
}
}
+164 -159
View File
@@ -1,172 +1,112 @@
using Xunit;
using System.Security.Cryptography;
using System.Reflection;
#pragma warning disable S1944, S2053, S2222, S2259, S2583, S2589, S3329, S3655, S3900, S3949, S3966, S4158, S4347, S5773, S6781
namespace QuanTAlib;
namespace QuanTAlib.Tests;
public class EventingTests
{
[Fact]
public void EventBasedCalculations()
private const int TestDataPoints = 200;
private const int DefaultPeriod = 10;
private const double Tolerance = 1e-9;
private static readonly (string Name, object[] DirectParams, object[] EventParams)[] ValueIndicators = new[]
{
// Create a cryptographically secure random number generator
using var rng = RandomNumberGenerator.Create();
("Afirma", new object[] { DefaultPeriod, DefaultPeriod, Afirma.WindowType.BlackmanHarris }, new object[] { new TSeries(), DefaultPeriod, DefaultPeriod, Afirma.WindowType.BlackmanHarris }),
("Alma", new object[] { DefaultPeriod, 0.85, 6.0 }, new object[] { new TSeries(), DefaultPeriod, 0.85, 6.0 }),
("Convolution", new object[] { new double[] {1,2,3,2,1} }, new object[] { new TSeries(), new double[] {1,2,3,2,1} }),
("Dema", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Dsma", new object[] { DefaultPeriod, 0.9 }, new object[] { new TSeries(), DefaultPeriod, 0.9 }),
("Dwma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Ema", new object[] { DefaultPeriod, true }, new object[] { new TSeries(), DefaultPeriod, true }),
("Epma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Pwma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Frama", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Fwma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Gma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Hma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Htit", new object[] { }, new object[] { new TSeries() }),
("Hwma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Jma", new object[] { DefaultPeriod, 0, 0.45, 10 }, new object[] { new TSeries(), DefaultPeriod, 0, 0.45, 10 }),
("Kama", new object[] { DefaultPeriod, 2, 30 }, new object[] { new TSeries(), DefaultPeriod, 2, 30 }),
("Ltma", new object[] { 0.2 }, new object[] { new TSeries(), 0.2 }),
("Maaf", new object[] { 39, 0.002 }, new object[] { new TSeries(), 39, 0.002 }),
("Mama", new object[] { 0.5, 0.05 }, new object[] { new TSeries(), 0.5, 0.05 }),
("Mgdi", new object[] { DefaultPeriod, 0.6 }, new object[] { new TSeries(), DefaultPeriod, 0.6 }),
("Mma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Qema", new object[] { 0.2, 0.2, 0.2, 0.2 }, new object[] { new TSeries(), 0.2, 0.2, 0.2, 0.2 }),
("Rema", new object[] { DefaultPeriod, 0.5 }, new object[] { new TSeries(), DefaultPeriod, 0.5 }),
("Rma", new object[] { DefaultPeriod, true }, new object[] { new TSeries(), DefaultPeriod, true }),
("Sma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Wma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Tema", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Zlema", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Sinema", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Smma", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("T3", new object[] { DefaultPeriod, 0.7, true }, new object[] { new TSeries(), DefaultPeriod, 0.7, true }),
("Trima", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Vidya", new object[] { DefaultPeriod, 0, 0.2 }, new object[] { new TSeries(), DefaultPeriod, 0, 0.2 }),
("Apo", new object[] { 12, 26 }, new object[] { new TSeries(), 12, 26 }),
("Macd", new object[] { 12, 26, 9 }, new object[] { new TSeries(), 12, 26, 9 }),
("Rsi", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Rsx", new object[] { DefaultPeriod, 0, 0.55 }, new object[] { new TSeries(), DefaultPeriod, 0, 0.55 }),
("Cmo", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Cog", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Curvature", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Entropy", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Kurtosis", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Max", new object[] { DefaultPeriod, 0.0 }, new object[] { new TSeries(), DefaultPeriod, 0.0 }),
("Median", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Min", new object[] { DefaultPeriod, 0.0 }, new object[] { new TSeries(), DefaultPeriod, 0.0 }),
("Mode", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Percentile", new object[] { DefaultPeriod, 0.5 }, new object[] { new TSeries(), DefaultPeriod, 0.5 }),
("Skew", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Slope", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Stddev", new object[] { DefaultPeriod, false }, new object[] { new TSeries(), DefaultPeriod, false }),
("Variance", new object[] { DefaultPeriod, false }, new object[] { new TSeries(), DefaultPeriod, false }),
("Zscore", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Beta", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Corr", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Hv", new object[] { DefaultPeriod, false }, new object[] { new TSeries(), DefaultPeriod, false }),
("Jvolty", new object[] { DefaultPeriod, 0 }, new object[] { new TSeries(), DefaultPeriod, 0 }),
("Rv", new object[] { DefaultPeriod, false }, new object[] { new TSeries(), DefaultPeriod, false }),
("Rvi", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Mae", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Mapd", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Mape", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Mase", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Mda", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Me", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Mpe", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Mse", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Msle", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Rae", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Rmse", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Rmsle", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Rse", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Smape", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Rsquared", new object[] { DefaultPeriod }, new object[] { new TSeries(), DefaultPeriod }),
("Huber", new object[] { DefaultPeriod, 1.0 }, new object[] { new TSeries(), DefaultPeriod, 1.0 })
};
// Create input series to hold our random values
var input = new TSeries();
var barInput = new TBarSeries();
int p = 10;
private static readonly (string Name, object[] DirectParams, object[] EventParams)[] BarIndicators = new[]
{
("Adl", new object[] { }, new object[] { new TBarSeries() }),
("Adosc", new object[] { 3, 10 }, new object[] { new TBarSeries(), 3, 10 }),
("Aobv", new object[] { }, new object[] { new TBarSeries() }),
("Cmf", new object[] { 20 }, new object[] { new TBarSeries(), 20 }),
("Eom", new object[] { 14 }, new object[] { new TBarSeries(), 14 }),
("Kvo", new object[] { 34, 55 }, new object[] { new TBarSeries(), 34, 55 }),
("Atr", new object[] { 14 }, new object[] { new TBarSeries(), 14 }),
("Chop", new object[] { 14 }, new object[] { new TBarSeries(), 14 }),
("Dosc", new object[] { }, new object[] { new TBarSeries() })
};
// Create a list of value-based indicator pairs
var valueIndicators = new List<(string Name, AbstractBase Direct, AbstractBase EventBased)>
{
("Afirma", new Afirma(p,p,Afirma.WindowType.BlackmanHarris), new Afirma(input, p,p,Afirma.WindowType.BlackmanHarris)),
("Alma", new Alma(p), new Alma(input, p)),
("Convolution", new Convolution(new double[] {1,2,3,2,1}), new Convolution(input, new double[] {1,2,3,2,1})),
("Dema", new Dema(p), new Dema(input, p)),
("Dsma", new Dsma(p), new Dsma(input, p)),
("Dwma", new Dwma(p), new Dwma(input, p)),
("Ema", new Ema(p), new Ema(input, p)),
("Epma", new Epma(p), new Epma(input, p)),
("Pwma", new Pwma(p), new Pwma(input, p)),
("Frama", new Frama(p), new Frama(input, p)),
("Fwma", new Fwma(p), new Fwma(input, p)),
("Gma", new Gma(p), new Gma(input, p)),
("Hma", new Hma(p), new Hma(input, p)),
("Htit", new Htit(), new Htit(input)),
("Hwma", new Hwma(p), new Hwma(input, p)),
("Jma", new Jma(p), new Jma(input, p)),
("Kama", new Kama(p), new Kama(input, p)),
("Ltma", new Ltma(gamma: 0.2), new Ltma(input, gamma: 0.2)),
("Maaf", new Maaf(p), new Maaf(input, p)),
("Mama", new Mama(p), new Mama(input, p)),
("Mgdi", new Mgdi(p, kFactor: 0.6), new Mgdi(input, p, kFactor: 0.6)),
("Mma", new Mma(p), new Mma(input, p)),
("Qema", new Qema(k1: 0.2, k2: 0.2, k3: 0.2, k4: 0.2), new Qema(input, k1: 0.2, k2: 0.2, k3: 0.2, k4: 0.2)),
("Rema", new Rema(p), new Rema(input, p)),
("Rma", new Rma(p), new Rma(input, p)),
("Sma", new Sma(p), new Sma(input, p)),
("Wma", new Wma(p), new Wma(input, p)),
("Rma", new Rma(p), new Rma(input, p)),
("Tema", new Tema(p), new Tema(input, p)),
("Kama", new Kama(2, 30, 6), new Kama(input, 2, 30, 6)),
("Zlema", new Zlema(p), new Zlema(input, p)),
("Sinema", new Sinema(p), new Sinema(input, p)),
("Smma", new Smma(p), new Smma(input, p)),
("T3", new T3(p), new T3(input, p)),
("Trima", new Trima(p), new Trima(input, p)),
("Vidya", new Vidya(p), new Vidya(input, p)),
("Apo", new Apo(12, 26), new Apo(input, 12, 26)),
("Macd", new Macd(12, 26, 9), new Macd(input, 12, 26, 9)),
("Rsi", new Rsi(p), new Rsi(input, p)),
("Rsx", new Rsx(p), new Rsx(input, p)),
("Cmo", new Cmo(p), new Cmo(input, p)),
("Cog", new Cog(p), new Cog(input, p)),
("Curvature", new Curvature(p), new Curvature(input, p)),
("Entropy", new Entropy(p), new Entropy(input, p)),
("Kurtosis", new Kurtosis(p), new Kurtosis(input, p)),
("Max", new Max(p), new Max(input, p)),
("Median", new Median(p), new Median(input, p)),
("Min", new Min(p), new Min(input, p)),
("Mode", new Mode(p), new Mode(input, p)),
("Percentile", new Percentile(p, 0.5), new Percentile(input, p, 0.5)),
("Skew", new Skew(p), new Skew(input, p)),
("Slope", new Slope(p), new Slope(input, p)),
("Stddev", new Stddev(p), new Stddev(input, p)),
("Variance", new Variance(p), new Variance(input, p)),
("Zscore", new Zscore(p), new Zscore(input, p)),
("Beta", new Beta(p), new Beta(input, p)),
("Corr", new Corr(p), new Corr(input, p)),
// Volatility indicators (value-based)
("Hv", new Hv(p), new Hv(input, p)),
("Jvolty", new Jvolty(p), new Jvolty(input, p)),
("Rv", new Rv(p), new Rv(input, p)),
("Rvi", new Rvi(p), new Rvi(input, p)),
// Error classes
("Mae", new Mae(p), new Mae(input, p)),
("Mapd", new Mapd(p), new Mapd(input, p)),
("Mape", new Mape(p), new Mape(input, p)),
("Mase", new Mase(p), new Mase(input, p)),
("Mda", new Mda(p), new Mda(input, p)),
("Me", new Me(p), new Me(input, p)),
("Mpe", new Mpe(p), new Mpe(input, p)),
("Mse", new Mse(p), new Mse(input, p)),
("Msle", new Msle(p), new Msle(input, p)),
("Rae", new Rae(p), new Rae(input, p)),
("Rmse", new Rmse(p), new Rmse(input, p)),
("Rmsle", new Rmsle(p), new Rmsle(input, p)),
("Rse", new Rse(p), new Rse(input, p)),
("Smape", new Smape(p), new Smape(input, p)),
("Rsquared", new Rsquared(p), new Rsquared(input, p)),
("Huber", new Huber(p), new Huber(input, p))
};
public static IEnumerable<object[]> GetValueIndicatorData()
=> ValueIndicators.Select(x => new object[] { x.Name, x.DirectParams, x.EventParams });
// Create a list of bar-based indicator pairs
var barIndicators = new List<(string Name, AbstractBase Direct, AbstractBase EventBased)>
{
// Volume indicators
("Adl", new Adl(), new Adl(barInput)),
("Adosc", new Adosc(3, 10), new Adosc(barInput, 3, 10)),
("Aobv", new Aobv(), new Aobv(barInput)),
("Cmf", new Cmf(20), new Cmf(barInput, 20)),
("Eom", new Eom(14), new Eom(barInput, 14)),
("Kvo", new Kvo(34, 55), new Kvo(barInput, 34, 55)),
// Volatility indicators (bar-based)
("Atr", new Atr(14), new Atr(barInput, 14)),
// Oscillators (bar-based)
("Chop", new Chop(14), new Chop(barInput, 14)),
("Dosc", new Dosc(), new Dosc(barInput))
};
// Generate 200 random values and feed them to indicators
for (int i = 0; i < 200; i++)
{
// Generate random value for value-based indicators
double randomValue = GetRandomDouble(rng) * 100;
input.Add(randomValue);
// Calculate value-based indicators
foreach (var (_, direct, _) in valueIndicators)
{
direct.Calc(randomValue);
}
// Generate random bar for bar-based indicators
var bar = new TBar(
DateTime.Now,
randomValue,
randomValue + Math.Abs(GetRandomDouble(rng) * 10),
randomValue - Math.Abs(GetRandomDouble(rng) * 10),
randomValue + (GetRandomDouble(rng) * 5),
Math.Abs(GetRandomDouble(rng) * 1000),
true
);
barInput.Add(bar);
// Calculate bar-based indicators
foreach (var (_, direct, _) in barIndicators)
{
direct.Calc(bar);
}
}
// Compare the results for value-based indicators
foreach (var (name, direct, eventBased) in valueIndicators)
{
bool areEqual = (double.IsNaN(direct.Value) && double.IsNaN(eventBased.Value)) ||
Math.Abs(direct.Value - eventBased.Value) < 1e-9;
Assert.True(areEqual, $"Value indicator {name} failed: Expected {direct.Value}, Actual {eventBased.Value}");
}
// Compare the results for bar-based indicators
foreach (var (name, direct, eventBased) in barIndicators)
{
bool areEqual = (double.IsNaN(direct.Value) && double.IsNaN(eventBased.Value)) ||
Math.Abs(direct.Value - eventBased.Value) < 1e-9;
Assert.True(areEqual, $"Bar indicator {name} failed: Expected {direct.Value}, Actual {eventBased.Value}");
}
}
public static IEnumerable<object[]> GetBarIndicatorData()
=> BarIndicators.Select(x => new object[] { x.Name, x.DirectParams, x.EventParams });
private static double GetRandomDouble(RandomNumberGenerator rng)
{
@@ -174,4 +114,69 @@ public class EventingTests
rng.GetBytes(bytes);
return (double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue;
}
private static TBar GenerateRandomBar(RandomNumberGenerator rng, double baseValue)
{
return new TBar(
DateTime.Now,
baseValue,
baseValue + Math.Abs(GetRandomDouble(rng) * 10),
baseValue - Math.Abs(GetRandomDouble(rng) * 10),
baseValue + (GetRandomDouble(rng) * 5),
Math.Abs(GetRandomDouble(rng) * 1000),
true
);
}
[Theory]
[MemberData(nameof(GetValueIndicatorData))]
public void ValueIndicatorEventTest(string indicatorName, object[] directParams, object[] eventParams)
{
using var rng = RandomNumberGenerator.Create();
var input = (TSeries)eventParams[0];
// Create indicator instances using reflection
var indicatorType = Type.GetType($"QuanTAlib.{indicatorName}, QuanTAlib")!;
var directIndicator = (AbstractBase)Activator.CreateInstance(indicatorType, directParams)!;
var eventIndicator = (AbstractBase)Activator.CreateInstance(indicatorType, eventParams)!;
// Generate test data and calculate
for (int i = 0; i < TestDataPoints; i++)
{
double randomValue = GetRandomDouble(rng) * 100;
input.Add(randomValue);
directIndicator.Calc(randomValue);
}
bool areEqual = (double.IsNaN(directIndicator.Value) && double.IsNaN(eventIndicator.Value)) ||
Math.Abs(directIndicator.Value - eventIndicator.Value) < Tolerance;
Assert.True(areEqual, $"Value indicator {indicatorName} failed: Expected {directIndicator.Value}, Actual {eventIndicator.Value}");
}
[Theory]
[MemberData(nameof(GetBarIndicatorData))]
public void BarIndicatorEventTest(string indicatorName, object[] directParams, object[] eventParams)
{
using var rng = RandomNumberGenerator.Create();
var barInput = (TBarSeries)eventParams[0];
// Create indicator instances using reflection
var indicatorType = Type.GetType($"QuanTAlib.{indicatorName}, QuanTAlib")!;
var directIndicator = (AbstractBase)Activator.CreateInstance(indicatorType, directParams)!;
var eventIndicator = (AbstractBase)Activator.CreateInstance(indicatorType, eventParams)!;
// Generate test data and calculate
for (int i = 0; i < TestDataPoints; i++)
{
var bar = GenerateRandomBar(rng, GetRandomDouble(rng) * 100);
barInput.Add(bar);
directIndicator.Calc(bar);
}
bool areEqual = (double.IsNaN(directIndicator.Value) && double.IsNaN(eventIndicator.Value)) ||
Math.Abs(directIndicator.Value - eventIndicator.Value) < Tolerance;
Assert.True(areEqual, $"Bar indicator {indicatorName} failed: Expected {directIndicator.Value}, Actual {eventIndicator.Value}");
}
}
+54 -1
View File
@@ -1,6 +1,10 @@
extern alias volatility;
extern alias averages;
extern alias statistics;
extern alias momentum;
extern alias oscillators;
extern alias volume;
extern alias experiments;
using Xunit;
using System.Reflection;
@@ -8,6 +12,10 @@ using TradingPlatform.BusinessLayer;
using statistics::QuanTAlib;
using averages::QuanTAlib;
using volatility::QuanTAlib;
using momentum::QuanTAlib;
using oscillators::QuanTAlib;
using volume::QuanTAlib;
using experiments::QuanTAlib;
namespace QuanTAlib
{
@@ -43,6 +51,39 @@ namespace QuanTAlib
}
}
private static void TestIndicatorMultipleFields<T>(string[] fieldNames) where T : Indicator, new()
{
var indicator = new T();
try
{
var onInitMethod = typeof(T).GetMethod("OnInit", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(onInitMethod);
onInitMethod.Invoke(indicator, null);
var onUpdateMethod = typeof(T).GetMethod("OnUpdate", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(onUpdateMethod);
foreach (var fieldName in fieldNames)
{
var field = typeof(T).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(field);
var fieldValue = field.GetValue(indicator);
Assert.NotNull(fieldValue);
}
Assert.NotNull(indicator.ShortName);
Assert.NotEmpty(indicator.ShortName);
Assert.NotNull(indicator.Name);
Assert.NotEmpty(indicator.Name);
Assert.NotNull(indicator.Description);
Assert.NotEmpty(indicator.Description);
Assert.IsAssignableFrom<Indicator>(indicator);
}
catch (Exception ex)
{
throw new Xunit.Sdk.XunitException($"Test failed for {typeof(T).Name}: {ex.Message}");
}
}
// Averages Indicators
[Fact] public void Afirma() => TestIndicator<AfirmaIndicator>();
[Fact] public void Alma() => TestIndicator<AlmaIndicator>();
@@ -95,9 +136,21 @@ namespace QuanTAlib
// Volatility Indicators
[Fact] public void Atr() => TestIndicator<AtrIndicator>("atr");
[Fact] public void Cmo() => TestIndicator<CmoIndicator>("cmo");
[Fact] public void Cvi() => TestIndicator<CviIndicator>("cvi");
[Fact] public void Historical() => TestIndicator<HistoricalIndicator>("historical");
[Fact] public void Jbands() => TestIndicatorMultipleFields<JbandsIndicator>(new[] { "jmaUp", "jmaLo" });
[Fact] public void Jvolty() => TestIndicator<JvoltyIndicator>("jma");
[Fact] public void Realized() => TestIndicator<RealizedIndicator>("realized");
[Fact] public void Rvi() => TestIndicator<RviIndicator>("rvi");
// Momentum Indicators
[Fact] public void Adx() => TestIndicator<momentum::QuanTAlib.AdxIndicator>("adx");
[Fact] public void Adxr() => TestIndicator<momentum::QuanTAlib.AdxrIndicator>("adxr");
[Fact] public void Apo() => TestIndicator<momentum::QuanTAlib.ApoIndicator>("apo");
[Fact] public void Dmi() => TestIndicator<momentum::QuanTAlib.DmiIndicator>("dmi");
[Fact] public void Dmx() => TestIndicator<momentum::QuanTAlib.DmxIndicator>("dmx");
[Fact] public void Dpo() => TestIndicator<momentum::QuanTAlib.DpoIndicator>("dpo");
[Fact] public void Macd() => TestIndicator<momentum::QuanTAlib.MacdIndicator>("macd");
}
}
+33 -213
View File
@@ -1,340 +1,160 @@
using Xunit;
using System.Security.Cryptography;
namespace QuanTAlib.Tests;
public class OscillatorsUpdateTests
public class OscillatorsUpdateTests : UpdateTestBase
{
private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create();
private const int RandomUpdates = 100;
private const double ReferenceValue = 100.0;
private const int precision = 8;
private double GetRandomDouble()
{
byte[] bytes = new byte[8];
rng.GetBytes(bytes);
return ((double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200) - 100; // Range: -100 to 100
}
private TBar GetRandomBar(bool IsNew)
{
double open = GetRandomDouble();
double high = open + Math.Abs(GetRandomDouble());
double low = open - Math.Abs(GetRandomDouble());
double close = low + ((high - low) * GetRandomDouble());
return new TBar(DateTime.Now, open, high, low, close, 1000, IsNew);
}
[Fact]
public void Rsi_Update()
{
var indicator = new Rsi(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Rsx_Update()
{
var indicator = new Rsx(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Cmo_Update()
{
var indicator = new Cmo(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Ao_Update()
{
var indicator = new Ao();
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Ac_Update()
{
var indicator = new Ac();
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Aroon_Update()
{
var indicator = new Aroon(period: 25);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Bop_Update()
{
var indicator = new Bop();
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Cci_Update()
{
var indicator = new Cci(period: 20);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Cfo_Update()
{
var indicator = new Cfo(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Chop_Update()
{
var indicator = new Chop(period: 14);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Cog_Update()
{
var indicator = new Cog(period: 10);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
TestTValueUpdate(indicator, indicator.Calc);
}
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
[Fact]
public void Coppock_Update()
{
var indicator = new Coppock(roc1Period: 14, roc2Period: 11, wmaPeriod: 10);
TestTValueUpdate(indicator, indicator.Calc);
}
Assert.Equal(initialValue, finalValue, precision);
[Fact]
public void Crsi_Update()
{
var indicator = new Crsi(period1: 10, period2: 14, period3: 30);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Smi_Update()
{
var indicator = new Smi(period: 10, smooth1: 3, smooth2: 3);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Srsi_Update()
{
var indicator = new Srsi(rsiPeriod: 14, stochPeriod: 14, smoothK: 3, smoothD: 3);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Stc_Update()
{
var indicator = new Stc(cyclePeriod: 10, fastPeriod: 23, slowPeriod: 50);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Stoch_Update()
{
var indicator = new Stoch(period: 14, smoothK: 3, smoothD: 3);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Tsi_Update()
{
var indicator = new Tsi(firstPeriod: 25, secondPeriod: 13);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Uo_Update()
{
var indicator = new Uo(period1: 7, period2: 14, period3: 28);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Willr_Update()
{
var indicator = new Willr(period: 14);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Dosc_Update()
{
var indicator = new Dosc();
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Efi_Update()
{
var indicator = new Efi(period: 13);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
}
+29 -169
View File
@@ -1,272 +1,132 @@
using Xunit;
using System.Security.Cryptography;
namespace QuanTAlib.Tests;
public class StatisticsUpdateTests
public class StatisticsUpdateTests : UpdateTestBase
{
private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create();
private const int RandomUpdates = 100;
private const double ReferenceValue = 100.0;
private const int precision = 8;
private double GetRandomDouble()
{
byte[] bytes = new byte[8];
rng.GetBytes(bytes);
return ((double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200) - 100; // Range: -100 to 100
}
private TBar GetRandomBar(bool IsNew)
{
double open = GetRandomDouble();
double high = open + Math.Abs(GetRandomDouble());
double low = open - Math.Abs(GetRandomDouble());
double close = low + ((high - low) * GetRandomDouble());
return new TBar(DateTime.Now, open, high, low, close, 1000, IsNew);
}
[Fact]
public void Beta_Update()
{
var indicator = new Beta(period: 14);
TBar marketBar = GetRandomBar(true);
TBar assetBar = GetRandomBar(true);
double initialValue = indicator.Calc(marketBar, assetBar);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(false), GetRandomBar(false));
}
double finalValue = indicator.Calc(new TBar(marketBar.Time, marketBar.Open, marketBar.High, marketBar.Low, marketBar.Close, marketBar.Volume, false),
new TBar(assetBar.Time, assetBar.Open, assetBar.High, assetBar.Low, assetBar.Close, assetBar.Volume, false));
Assert.Equal(initialValue, finalValue, precision);
TestDualTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Corr_Update()
{
var indicator = new Corr(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true), new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false), new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false), new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestDualTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Curvature_Update()
{
var indicator = new Curvature(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Entropy_Update()
{
var indicator = new Entropy(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Hurst_Update()
{
var indicator = new Hurst(period: 100, minLength: 10);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Kurtosis_Update()
{
var indicator = new Kurtosis(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Max_Update()
{
var indicator = new Max(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Median_Update()
{
var indicator = new Median(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Min_Update()
{
var indicator = new Min(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Mode_Update()
{
var indicator = new Mode(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Percentile_Update()
{
var indicator = new Percentile(period: 14, percent: 50);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Skew_Update()
{
var indicator = new Skew(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Slope_Update()
{
var indicator = new Slope(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Stddev_Update()
{
var indicator = new Stddev(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
TestTValueUpdate(indicator, indicator.Calc);
}
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
[Fact]
public void Theil_Update()
{
var indicator = new Theil(period: 14);
TestTValueUpdate(indicator, indicator.Calc);
}
Assert.Equal(initialValue, finalValue, precision);
[Fact]
public void Tsf_Update()
{
var indicator = new Tsf(period: 14);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Variance_Update()
{
var indicator = new Variance(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Zscore_Update()
{
var indicator = new Zscore(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
}
+37 -318
View File
@@ -1,504 +1,223 @@
using Xunit;
using System.Security.Cryptography;
namespace QuanTAlib.Tests;
public class VolatilityUpdateTests
public class VolatilityUpdateTests : UpdateTestBase
{
private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create();
private const int RandomUpdates = 100;
private const double ReferenceValue = 100.0;
private const int precision = 8;
private double GetRandomDouble()
{
byte[] bytes = new byte[8];
rng.GetBytes(bytes);
return ((double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200) - 100; // Range: -100 to 100
}
private TBar GetRandomBar(bool IsNew)
{
double open = GetRandomDouble();
double high = open + Math.Abs(GetRandomDouble());
double low = open - Math.Abs(GetRandomDouble());
double close = low + ((high - low) * GetRandomDouble());
return new TBar(DateTime.Now, open, high, low, close, 1000, IsNew);
}
[Fact]
public void Adr_Update()
{
var indicator = new Adr(period: 14);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Atr_Update()
{
var indicator = new Atr(period: 14);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
TestTBarUpdate(indicator, indicator.Calc);
}
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
[Fact]
public void Atrs_Update()
{
var indicator = new Atrs(period: 14, factor: 2.0);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Ap_Update()
{
var indicator = new Ap(period: 20);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Atrp_Update()
{
var indicator = new Atrp(period: 14);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Bband_Update()
{
var indicator = new Bband(period: 20, multiplier: 2.0);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Ccv_Update()
{
var indicator = new Ccv(period: 20);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Ce_Update()
{
var indicator = new Ce(period: 22, multiplier: 3.0);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Cv_Update()
{
var indicator = new Cv(period: 20);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Cvi_Update()
{
var indicator = new Cvi(period: 10, smoothPeriod: 10);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Dchn_Update()
{
var indicator = new Dchn(period: 20);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Ewma_Update()
{
var indicator = new Ewma(period: 20, lambda: 0.94);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Fcb_Update()
{
var indicator = new Fcb(period: 20, smoothing: 0.5);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Gkv_Update()
{
var indicator = new Gkv(period: 20);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Historical_Update()
{
var indicator = new Hv(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Hlv_Update()
{
var indicator = new Hlv(period: 20);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Jvolty_Update()
{
var indicator = new Jvolty(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Natr_Update()
{
var indicator = new Natr(period: 14);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Pch_Update()
{
var indicator = new Pch(period: 20);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Pv_Update()
{
var indicator = new Pv(period: 10);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Realized_Update()
{
var indicator = new Rv(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Rsv_Update()
{
var indicator = new Rsv(period: 10);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Rvi_Update()
{
var indicator = new Rvi(period: 14);
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
}
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTValueUpdate(indicator, indicator.Calc);
}
[Fact]
public void Sv_Update()
{
var indicator = new Sv(period: 20, lambda: 0.94);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Tr_Update()
{
var indicator = new Tr();
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Ui_Update()
{
var indicator = new Ui(period: 14);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Vc_Update()
{
var indicator = new Vc(period: 20, deviations: 2.0);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Vov_Update()
{
var indicator = new Vov(period: 20);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Vr_Update()
{
var indicator = new Vr(shortPeriod: 10, longPeriod: 20);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Vs_Update()
{
var indicator = new Vs(period: 14, multiplier: 2.0);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
[Fact]
public void Yzv_Update()
{
var indicator = new Yzv(period: 20);
TBar r = GetRandomBar(true);
double initialValue = indicator.Calc(r);
for (int i = 0; i < RandomUpdates; i++)
{
indicator.Calc(GetRandomBar(IsNew: false));
}
double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false));
Assert.Equal(initialValue, finalValue, precision);
TestTBarUpdate(indicator, indicator.Calc);
}
}
+4 -4
View File
@@ -25,7 +25,7 @@ public class DpoIndicator : Indicator, IWatchlistIndicator
[InputParameter("Show cold values", sortIndex: 3)]
public bool ShowColdValues { get; set; } = true;
private Dpo? Dpo;
private Dpo? dpo;
protected LineSeries? DpoSeries;
public int MinHistoryDepths => Period * 2;
int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths;
@@ -42,14 +42,14 @@ public class DpoIndicator : Indicator, IWatchlistIndicator
protected override void OnInit()
{
Dpo = new Dpo(Period);
dpo = new Dpo(Period);
base.OnInit();
}
protected override void OnUpdate(UpdateArgs args)
{
TBar input = this.GetInputBar(args);
TValue result = Dpo!.Calc(input);
TValue result = dpo!.Calc(input);
DpoSeries!.SetValue(result.Value);
DpoSeries!.SetMarker(0, Color.Transparent);
@@ -62,6 +62,6 @@ public class DpoIndicator : Indicator, IWatchlistIndicator
public override void OnPaintChart(PaintChartEventArgs args)
{
base.OnPaintChart(args);
this.PaintSmoothCurve(args, DpoSeries!, Dpo!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2);
this.PaintSmoothCurve(args, DpoSeries!, dpo!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2);
}
}