Files
QuanTAlib/Tests/test_skender.stock.cs
T

355 lines
12 KiB
C#
Raw Normal View History

2024-09-22 17:31:24 -07:00
using Xunit;
using Skender.Stock.Indicators;
2024-10-05 19:36:01 -07:00
using System.Diagnostics.CodeAnalysis;
2024-10-08 17:34:58 -07:00
using System.Security.Cryptography;
2024-10-05 19:36:01 -07:00
2024-10-08 18:49:50 -07:00
#pragma warning disable S1944, S2053, S2222, S2259, S2583, S2589, S3329, S3655, S3900, S3949, S3966, S4158, S4347, S5773, S6781
2024-10-11 18:02:09 -07:00
namespace QuanTAlib.Tests;
2024-10-05 19:36:01 -07:00
2024-09-22 17:31:24 -07:00
public class SkenderTests
{
private readonly TBarSeries bars;
private readonly GbmFeed feed;
2024-10-08 17:34:58 -07:00
private readonly RandomNumberGenerator rng;
2024-09-22 17:31:24 -07:00
private readonly double range;
2024-10-06 14:44:43 -07:00
private int period;
2024-10-08 13:59:33 -07:00
private readonly int iterations = 3; // Initialized directly at declaration
2024-09-22 17:31:24 -07:00
private readonly IEnumerable<Quote> quotes;
public SkenderTests()
{
2024-10-08 17:34:58 -07:00
rng = RandomNumberGenerator.Create();
2024-09-22 17:31:24 -07:00
feed = new(sigma: 0.5, mu: 0.0);
bars = new(feed);
range = 1e-9;
feed.Add(10000);
quotes = bars.Select(q => new Quote
{
Date = q.Time,
Open = (decimal)q.Open,
High = (decimal)q.High,
Low = (decimal)q.Low,
Close = (decimal)q.Close,
Volume = (decimal)q.Volume
});
}
2024-10-08 17:34:58 -07:00
private int GetRandomNumber(int minValue, int maxValue)
{
byte[] randomBytes = new byte[4];
rng.GetBytes(randomBytes);
int randomInt = BitConverter.ToInt32(randomBytes, 0);
return Math.Abs(randomInt % (maxValue - minValue)) + minValue;
}
2024-09-22 17:31:24 -07:00
[Fact]
public void SMA()
{
for (int run = 0; run < iterations; run++)
{
2024-10-08 17:34:58 -07:00
period = GetRandomNumber(5, 55);
2024-09-22 17:31:24 -07:00
Sma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
var SK = quotes.GetSma(lookbackPeriods: period).Select(i => i.Sma.Null2NaN()!);
Assert.Equal(QL.Length, SK.Count());
for (int i = QL.Length - 1; i > period; i--)
{
Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range);
}
}
}
[Fact]
public void SMAEMA()
{
for (int run = 0; run < iterations; run++)
{
2024-10-08 17:34:58 -07:00
period = GetRandomNumber(5, 55);
2024-09-22 17:31:24 -07:00
Ema ma = new(period, useSma: true);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
var SK = quotes.GetEma(lookbackPeriods: period).Select(i => i.Ema.Null2NaN()!);
Assert.Equal(QL.Length, SK.Count());
for (int i = QL.Length - 1; i > period; i--)
{
Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range);
}
}
}
[Fact]
public void EMA()
{
for (int run = 0; run < iterations; run++)
{
2024-10-08 17:34:58 -07:00
period = GetRandomNumber(5, 55);
2024-09-22 17:31:24 -07:00
Ema ma = new(period, useSma: false);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
var SK = quotes.GetEma(lookbackPeriods: period).Select(i => i.Ema.Null2NaN()!);
Assert.Equal(QL.Length, SK.Count());
for (int i = QL.Length - 1; i > QL.Length - 500; i--)
{
Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range);
}
}
}
[Fact]
public void DEMA()
{
for (int run = 0; run < iterations; run++)
{
2024-10-08 17:34:58 -07:00
period = GetRandomNumber(5, 55);
2024-09-22 17:31:24 -07:00
Dema ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
var SK = quotes.GetDema(lookbackPeriods: period).Select(i => i.Dema.Null2NaN()!);
Assert.Equal(QL.Length, SK.Count());
for (int i = QL.Length - 1; i > QL.Length - 500; i--)
{
Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range);
}
}
}
[Fact]
public void TEMA()
{
for (int run = 0; run < iterations; run++)
{
2024-10-08 17:34:58 -07:00
period = GetRandomNumber(5, 55);
2024-09-22 17:31:24 -07:00
Tema ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
var SK = quotes.GetTema(lookbackPeriods: period).Select(i => i.Tema.Null2NaN()!);
Assert.Equal(QL.Length, SK.Count());
for (int i = QL.Length - 1; i > QL.Length - 500; i--)
{
Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range);
}
}
}
[Fact]
public void SMAConvolution()
{
for (int run = 0; run < iterations; run++)
{
2024-10-08 17:34:58 -07:00
period = GetRandomNumber(5, 55);
2024-09-22 17:31:24 -07:00
double[] kernel = Enumerable.Repeat(1.0, period).ToArray();
Convolution ma = new(kernel);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
var SK = quotes.GetSma(lookbackPeriods: period).Select(i => i.Sma.Null2NaN()!);
Assert.Equal(QL.Length, SK.Count());
for (int i = QL.Length - 1; i > period; i--)
{
Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range);
}
}
}
[Fact]
public void WMA()
{
for (int run = 0; run < iterations; run++)
{
2024-10-08 17:34:58 -07:00
period = GetRandomNumber(5, 55);
2024-09-22 17:31:24 -07:00
Wma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
var SK = quotes.GetWma(lookbackPeriods: period).Select(i => i.Wma.Null2NaN()!);
Assert.Equal(QL.Length, SK.Count());
for (int i = QL.Length - 1; i > period + 2; i--)
{
Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range);
}
}
}
[Fact]
public void HMA()
{
for (int run = 0; run < iterations; run++)
{
2024-10-08 17:34:58 -07:00
period = GetRandomNumber(5, 55);
2024-09-22 17:31:24 -07:00
Hma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
var SK = quotes.GetHma(lookbackPeriods: period).Select(i => i.Hma.Null2NaN()!);
Assert.Equal(QL.Length, SK.Count());
for (int i = QL.Length - 1; i > period + 5; i--)
{
Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range);
}
}
}
[Fact]
public void EPMA()
{
for (int run = 0; run < iterations; run++)
{
2024-10-08 17:34:58 -07:00
period = GetRandomNumber(5, 55);
2024-09-22 17:31:24 -07:00
Epma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
var SK = quotes.GetEpma(lookbackPeriods: period).Select(i => i.Epma.Null2NaN()!);
Assert.Equal(QL.Length, SK.Count());
for (int i = QL.Length - 1; i > period + 5; i--)
{
Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range);
}
}
}
[Fact]
public void ALMA()
{
for (int run = 0; run < iterations; run++)
{
2024-10-08 17:34:58 -07:00
period = GetRandomNumber(5, 55);
2024-09-22 17:31:24 -07:00
Alma ma = new(period, offset: 0.85, sigma: 6);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
var SK = quotes.GetAlma(lookbackPeriods: period).Select(i => i.Alma.Null2NaN()!);
Assert.Equal(QL.Length, SK.Count());
for (int i = QL.Length - 1; i > period; i--)
{
Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range);
}
}
}
[Fact]
public void T3()
{
for (int run = 0; run < iterations; run++)
{
2024-10-08 17:34:58 -07:00
period = GetRandomNumber(5, 55);
2024-09-22 17:31:24 -07:00
T3 ma = new(period, vfactor: 0.7, useSma: false);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
var SK = quotes.GetT3(lookbackPeriods: period, volumeFactor: 0.7).Select(i => i.T3.Null2NaN()!);
Assert.Equal(QL.Length, SK.Count());
for (int i = QL.Length - 1; i > period; i--)
{
Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range);
}
}
}
[Fact]
public void SMMA()
{
for (int run = 0; run < iterations; run++)
{
2024-10-08 17:34:58 -07:00
period = GetRandomNumber(5, 55);
2024-09-22 17:31:24 -07:00
Smma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
var SK = quotes.GetSmma(lookbackPeriods: period).Select(i => i.Smma.Null2NaN()!);
Assert.Equal(QL.Length, SK.Count());
for (int i = QL.Length - 1; i > period; i--)
{
Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range);
}
}
}
[Fact]
public void KAMA()
{
for (int run = 0; run < iterations; run++)
{
2024-10-08 17:34:58 -07:00
period = GetRandomNumber(5, 55);
2024-09-22 17:31:24 -07:00
Kama ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
var SK = quotes.GetKama(erPeriods: period).Select(i => i.Kama.Null2NaN()!);
Assert.Equal(QL.Length, SK.Count());
for (int i = QL.Length - 1; i > period; i--)
{
Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range);
}
}
}
[Fact]
public void MAMA()
{
for (int run = 0; run < iterations; run++)
{
Mama ma = new(fastLimit: 0.5, slowLimit: 0.05);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
var SK = quotes.Select(q => (q.Date, (double)q.Close))
.GetMama(fastLimit: 0.5, slowLimit: 0.05)
.Select(i => i.Mama.Null2NaN()!);
Assert.Equal(QL.Length, SK.Count());
2024-11-04 18:08:33 -08:00
for (int i = QL.Length - 1; i > 500; i--)
2024-09-22 17:31:24 -07:00
{
Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range);
}
}
}
[Fact]
public void MGDI()
{
for (int run = 0; run < iterations; run++)
{
2024-10-08 17:34:58 -07:00
period = GetRandomNumber(5, 55);
2024-09-22 17:31:24 -07:00
Mgdi ma = new(period: period);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
var SK = quotes.Select(q => (q.Date, (double)q.Close))
.GetDynamic(lookbackPeriods: period)
.Select(i => i.Dynamic.Null2NaN()!);
Assert.Equal(QL.Length, SK.Count());
for (int i = QL.Length - 1; i > period + 5; i--)
{
Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range);
}
}
}
2024-09-30 06:46:07 -07:00
[Fact]
public void ATR()
{
for (int run = 0; run < iterations; run++)
{
2024-10-08 17:34:58 -07:00
period = GetRandomNumber(5, 55);
2024-09-30 06:46:07 -07:00
Atr ma = new(period: period);
TSeries QL = new();
foreach (TBar item in bars) { QL.Add(ma.Calc(item)); }
2024-10-08 09:49:28 -07:00
var atrValues = quotes.GetAtr(lookbackPeriods: period).Select(i => i.Atr.Null2NaN()!);
const int AdditionalPeriods = 500;
2024-09-30 06:46:07 -07:00
2024-10-22 05:46:48 -07:00
for (int i = QL.Length - 1; i > 1000 + AdditionalPeriods; i--)
2024-09-30 06:46:07 -07:00
{
2024-10-08 09:49:28 -07:00
Assert.InRange(atrValues.ElementAt(i) - QL[i].Value, -range, range);
2024-09-30 06:46:07 -07:00
}
}
}
2024-10-08 13:59:33 -07:00
}