Merging dev into main (#34)

This commit is contained in:
Miha Kralj
2024-10-08 17:45:50 -07:00
committed by GitHub
11 changed files with 196 additions and 148 deletions
+1 -1
View File
@@ -215,7 +215,7 @@ jobs:
sarif_file: results.sarif
build_publish:
needs: [SonarCloud, Code_Coverage, CodeQL, Codacy_Scan]
needs: [SonarCloud, Code_Coverage, CodeQL, Codacy_Scan, SecurityCodeScan]
if: success()
runs-on: ubuntu-latest
steps:
+3 -1
View File
@@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>preview</LangVersion>
<NoWarn>$(NoWarn);NU1903;NU5104</NoWarn>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Deterministic>true</Deterministic>
@@ -49,6 +49,8 @@
</ItemGroup>
<PropertyGroup Condition="'$(IsLocalBuild)' == 'true'">
<!-- Set the correct path to Quantower here -->
<QuantowerRoot>D:\Quantower</QuantowerRoot>
<QuantowerPath>$([System.IO.Directory]::GetDirectories("$(QuantowerRoot)\TradingPlatform", "v1*")[0])</QuantowerPath>
</PropertyGroup>
+13 -7
View File
@@ -3,16 +3,16 @@ using Trady.Analysis.Indicator;
using Trady.Core;
using Trady.Core.Infrastructure;
using System.Diagnostics.CodeAnalysis;
using System.Security.Cryptography;
namespace QuanTAlib;
[SuppressMessage("Security", "SCS0005:Weak random number generator.", Justification = "Acceptable for tests")]
public class TradyTests
{
private readonly TBarSeries bars;
private readonly GbmFeed feed;
private readonly Random rnd;
private readonly RandomNumberGenerator rng;
private readonly double range;
private readonly int iterations;
private readonly int skip;
@@ -20,7 +20,7 @@ public class TradyTests
public TradyTests()
{
rnd = new((int)DateTime.Now.Ticks);
rng = RandomNumberGenerator.Create();
feed = new(sigma: 0.5, mu: 0.0);
bars = new(feed);
range = 1e-9;
@@ -37,12 +37,20 @@ public class TradyTests
)).ToList();
}
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;
}
[Fact]
public void SMA()
{
for (int run = 0; run < iterations; run++)
{
int period = rnd.Next(50) + 5;
int period = GetRandomNumber(5, 55);
Sma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
@@ -72,7 +80,7 @@ public class TradyTests
{
for (int run = 0; run < iterations; run++)
{
int period = rnd.Next(50) + 5;
int period = GetRandomNumber(5, 55);
Ema ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
@@ -96,6 +104,4 @@ public class TradyTests
}
}
}
}
+13 -6
View File
@@ -1,15 +1,15 @@
using Xunit;
using Tulip;
using System.Diagnostics.CodeAnalysis;
using System.Security.Cryptography;
namespace QuanTAlib;
[SuppressMessage("Security", "SCS0005:Weak random number generator.", Justification = "Acceptable for tests")]
public class TulipTests
{
private readonly TBarSeries bars;
private readonly GbmFeed feed;
private readonly Random rnd;
private readonly RandomNumberGenerator rng;
private readonly double range;
private readonly int iterations;
private readonly double[] data;
@@ -18,9 +18,8 @@ public class TulipTests
public TulipTests()
{
rnd = new((int)DateTime.Now.Ticks);
rng = RandomNumberGenerator.Create();
feed = new(sigma: 0.5, mu: 0.0);
bars = new(feed);
range = 1e-9;
feed.Add(10000);
iterations = 3;
@@ -29,12 +28,20 @@ public class TulipTests
outdata = new double[data.Count()];
}
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;
}
[Fact]
public void SMA()
{
for (int run = 0; run < iterations; run++)
{
int period = rnd.Next(50) + 5;
int period = GetRandomNumber(5, 55);
Sma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
@@ -58,7 +65,7 @@ public class TulipTests
{
for (int run = 0; run < iterations; run++)
{
int period = rnd.Next(30) + 5;
int period = GetRandomNumber(5, 35);
Ema ma = new(period, useSma: false);
TSeries QL = new();
foreach (TBar item in feed)
+43 -38
View File
@@ -1,4 +1,5 @@
using Xunit;
using System.Security.Cryptography;
namespace QuanTAlib;
@@ -7,8 +8,8 @@ public class EventingTests
[Fact]
public void VerifyEventBasedCalculations()
{
// Create a random number generator with a fixed seed for reproducibility
var random = new Random(42);
// Create a cryptographically secure random number generator
using var rng = RandomNumberGenerator.Create();
// Create an input series to hold our random values
var input = new TSeries();
@@ -16,46 +17,43 @@ public class EventingTests
// Create a list of indicator pairs (direct calculation and event-based)
var indicators = new List<(AbstractBase Direct, AbstractBase EventBased)>
{
(new Afirma(p,p,Afirma.WindowType.BlackmanHarris), new Afirma(input, p,p,Afirma.WindowType.BlackmanHarris)),
(new Alma(p), new Alma(input, p)),
(new Convolution([1,2,3,2,1]), new Convolution(input, [1,2,3,2,1])),
(new Dema(p), new Dema(input, p)),
(new Dsma(p), new Dsma(input, p)),
(new Dwma(p), new Dwma(input, p)),
(new Ema(p), new Ema(input, p)),
(new Epma(p), new Epma(input, p)),
(new Frama(p), new Frama(input, p)),
(new Fwma(p), new Fwma(input, p)),
(new Gma(p), new Gma(input, p)),
(new Hma(p), new Hma(input, p)),
(new Htit(), new Htit(input)),
(new Hwma(p), new Hwma(input, p)),
(new Jma(p), new Jma(input, p)),
(new Kama(p), new Kama(input, p)),
(new Ltma(gamma: 0.2), new Ltma(input, gamma: 0.2)),
(new Maaf(p), new Maaf(input, p)),
(new Mama(p), new Mama(input, p)),
(new Mgdi(p), new Mgdi(input, p)),
(new Mma(p), new Mma(input, p)),
(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)),
(new Rema(p), new Rema(input, p)),
(new Rma(p), new Rma(input, p)),
(new Sma(p), new Sma(input, p)),
(new Wma(p), new Wma(input, p)),
(new Rma(p), new Rma(input, p)),
(new Tema(p), new Tema(input, p)),
(new Kama(2, 30, 6), new Kama(input, 2, 30, 6)),
(new Zlema(p), new Zlema(input, p))
};
{
(new Afirma(p,p,Afirma.WindowType.BlackmanHarris), new Afirma(input, p,p,Afirma.WindowType.BlackmanHarris)),
(new Alma(p), new Alma(input, p)),
(new Convolution([1,2,3,2,1]), new Convolution(input, [1,2,3,2,1])),
(new Dema(p), new Dema(input, p)),
(new Dsma(p), new Dsma(input, p)),
(new Dwma(p), new Dwma(input, p)),
(new Ema(p), new Ema(input, p)),
(new Epma(p), new Epma(input, p)),
(new Frama(p), new Frama(input, p)),
(new Fwma(p), new Fwma(input, p)),
(new Gma(p), new Gma(input, p)),
(new Hma(p), new Hma(input, p)),
(new Htit(), new Htit(input)),
(new Hwma(p), new Hwma(input, p)),
(new Jma(p), new Jma(input, p)),
(new Kama(p), new Kama(input, p)),
(new Ltma(gamma: 0.2), new Ltma(input, gamma: 0.2)),
(new Maaf(p), new Maaf(input, p)),
(new Mama(p), new Mama(input, p)),
(new Mgdi(p), new Mgdi(input, p)),
(new Mma(p), new Mma(input, p)),
(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)),
(new Rema(p), new Rema(input, p)),
(new Rma(p), new Rma(input, p)),
(new Sma(p), new Sma(input, p)),
(new Wma(p), new Wma(input, p)),
(new Rma(p), new Rma(input, p)),
(new Tema(p), new Tema(input, p)),
(new Kama(2, 30, 6), new Kama(input, 2, 30, 6)),
(new Zlema(p), new Zlema(input, p))
};
// Generate 200 random values and feed them to both direct and event-based indicators
for (int i = 0; i< 200; i++)
{
double randomValue = random.NextDouble() * 100;
double randomValue = GetRandomDouble(rng) * 100;
input.Add(randomValue);
// Calculate direct indicators
@@ -71,4 +69,11 @@ foreach (var (direct, eventBased) in indicators)
Assert.Equal(direct.Value, eventBased.Value, 9);
}
}
private static double GetRandomDouble(RandomNumberGenerator rng)
{
byte[] bytes = new byte[8];
rng.GetBytes(bytes);
return (double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue;
}
}
+33 -8
View File
@@ -1,16 +1,16 @@
using Xunit;
using System.Reflection;
using System.Diagnostics.CodeAnalysis;
using System.Security.Cryptography;
namespace QuanTAlib;
/// <summary>
/// Contains unit tests for bar-based indicators in QuanTAlib.
/// </summary>
[SuppressMessage("Security", "SCS0005:Weak random number generator.", Justification = "Acceptable for tests")]
public class BarIndicatorTests
{
private readonly Random rnd;
private readonly RandomNumberGenerator rng;
private const int SeriesLen = 1000;
private const int Corrections = 100;
@@ -19,7 +19,7 @@ public class BarIndicatorTests
/// </summary>
public BarIndicatorTests()
{
rnd = new Random((int)DateTime.Now.Ticks);
rng = RandomNumberGenerator.Create();
}
private static readonly ITValue[] indicators = new ITValue[]
@@ -124,15 +124,40 @@ public class BarIndicatorTests
/// <returns>A randomly generated TBar.</returns>
private TBar GenerateRandomBar(bool isNew)
{
double open = rnd.NextDouble() * 200 - 100;
double close = rnd.NextDouble() * 200 - 100;
double high = Math.Max(open, close) + rnd.NextDouble() * 10;
double low = Math.Min(open, close) - rnd.NextDouble() * 10;
long volume = rnd.Next(0, 10000);
double open = GetRandomDouble() * 200 - 100;
double close = GetRandomDouble() * 200 - 100;
double high = Math.Max(open, close) + GetRandomDouble() * 10;
double low = Math.Min(open, close) - GetRandomDouble() * 10;
long volume = GetRandomNumber(0, 10000);
return new TBar(Time: DateTime.Now, Open: open, High: high, Low: low, Close: close, Volume: volume, IsNew: isNew);
}
/// <summary>
/// Generates a random double between 0 and 1.
/// </summary>
/// <returns>A random double between 0 and 1.</returns>
private double GetRandomDouble()
{
byte[] bytes = new byte[8];
rng.GetBytes(bytes);
return (double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue;
}
/// <summary>
/// Generates a random integer between minValue (inclusive) and maxValue (exclusive).
/// </summary>
/// <param name="minValue">The minimum value (inclusive).</param>
/// <param name="maxValue">The maximum value (exclusive).</param>
/// <returns>A random integer between minValue and maxValue.</returns>
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;
}
/// <summary>
/// Provides the list of indicators for parameterized tests.
/// </summary>
+13 -5
View File
@@ -1,19 +1,27 @@
using Xunit;
using System.Reflection;
using System.Diagnostics.CodeAnalysis;
using System.Security.Cryptography;
namespace QuanTAlib;
[SuppressMessage("Security", "SCS0005:Weak random number generator.", Justification = "Acceptable for tests")]
public class IndicatorTests
{
private readonly Random rnd;
private readonly RandomNumberGenerator rng;
private const int SeriesLen = 1000;
private const int Corrections = 100;
public IndicatorTests()
{
rnd = new Random((int)DateTime.Now.Ticks);
rng = RandomNumberGenerator.Create();
}
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;
}
// skipcq: CS-R1055
@@ -83,12 +91,12 @@ public class IndicatorTests
for (int i = 0; i < SeriesLen; i++)
{
TValue item1 = new(Time: DateTime.Now, Value: rnd.Next(-100, 100), IsNew: true);
TValue item1 = new(Time: DateTime.Now, Value: GetRandomNumber(-100, 100), IsNew: true);
InvokeCalc(indicator1, calcMethod, item1);
for (int j = 0; j < Corrections; j++)
{
item1 = new(Time: DateTime.Now, Value: rnd.Next(-100, 100), IsNew: false);
item1 = new(Time: DateTime.Now, Value: GetRandomNumber(-100, 100), IsNew: false);
InvokeCalc(indicator1, calcMethod, item1);
}
+26 -20
View File
@@ -1,16 +1,15 @@
using Xunit;
using Skender.Stock.Indicators;
using System.Diagnostics.CodeAnalysis;
using System.Security.Cryptography;
namespace QuanTAlib;
[SuppressMessage("Security", "SCS0005:Weak random number generator.", Justification = "Acceptable for tests")]
public class SkenderTests
{
private readonly TBarSeries bars;
private readonly GbmFeed feed;
private readonly Random rnd;
private readonly RandomNumberGenerator rng;
private readonly double range;
private int period;
private readonly int iterations = 3; // Initialized directly at declaration
@@ -18,7 +17,7 @@ public class SkenderTests
public SkenderTests()
{
rnd = new((int)DateTime.Now.Ticks);
rng = RandomNumberGenerator.Create();
feed = new(sigma: 0.5, mu: 0.0);
bars = new(feed);
range = 1e-9;
@@ -34,12 +33,20 @@ public class SkenderTests
});
}
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;
}
[Fact]
public void SMA()
{
for (int run = 0; run < iterations; run++)
{
period = rnd.Next(50) + 5;
period = GetRandomNumber(5, 55);
Sma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
@@ -58,7 +65,7 @@ public class SkenderTests
{
for (int run = 0; run < iterations; run++)
{
period = rnd.Next(50) + 5;
period = GetRandomNumber(5, 55);
Ema ma = new(period, useSma: true);
TSeries QL = new();
foreach (TBar item in feed)
@@ -77,7 +84,7 @@ public class SkenderTests
{
for (int run = 0; run < iterations; run++)
{
period = rnd.Next(50) + 5;
period = GetRandomNumber(5, 55);
Ema ma = new(period, useSma: false);
TSeries QL = new();
foreach (TBar item in feed)
@@ -96,7 +103,7 @@ public class SkenderTests
{
for (int run = 0; run < iterations; run++)
{
period = rnd.Next(50) + 5;
period = GetRandomNumber(5, 55);
Dema ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
@@ -115,7 +122,7 @@ public class SkenderTests
{
for (int run = 0; run < iterations; run++)
{
period = rnd.Next(50) + 5;
period = GetRandomNumber(5, 55);
Tema ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
@@ -134,7 +141,7 @@ public class SkenderTests
{
for (int run = 0; run < iterations; run++)
{
period = rnd.Next(50) + 5;
period = GetRandomNumber(5, 55);
double[] kernel = Enumerable.Repeat(1.0, period).ToArray();
Convolution ma = new(kernel);
TSeries QL = new();
@@ -154,7 +161,7 @@ public class SkenderTests
{
for (int run = 0; run < iterations; run++)
{
period = rnd.Next(50) + 5;
period = GetRandomNumber(5, 55);
Wma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
@@ -173,7 +180,7 @@ public class SkenderTests
{
for (int run = 0; run < iterations; run++)
{
period = rnd.Next(50) + 5;
period = GetRandomNumber(5, 55);
Hma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
@@ -192,7 +199,7 @@ public class SkenderTests
{
for (int run = 0; run < iterations; run++)
{
period = rnd.Next(50) + 5;
period = GetRandomNumber(5, 55);
Epma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
@@ -211,7 +218,7 @@ public class SkenderTests
{
for (int run = 0; run < iterations; run++)
{
period = rnd.Next(50) + 5;
period = GetRandomNumber(5, 55);
Alma ma = new(period, offset: 0.85, sigma: 6);
TSeries QL = new();
foreach (TBar item in feed)
@@ -230,7 +237,7 @@ public class SkenderTests
{
for (int run = 0; run < iterations; run++)
{
period = rnd.Next(50) + 5;
period = GetRandomNumber(5, 55);
T3 ma = new(period, vfactor: 0.7, useSma: false);
TSeries QL = new();
foreach (TBar item in feed)
@@ -249,7 +256,7 @@ public class SkenderTests
{
for (int run = 0; run < iterations; run++)
{
period = rnd.Next(50) + 5;
period = GetRandomNumber(5, 55);
Smma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
@@ -268,7 +275,7 @@ public class SkenderTests
{
for (int run = 0; run < iterations; run++)
{
period = rnd.Next(50) + 5;
period = GetRandomNumber(5, 55);
Kama ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
@@ -307,7 +314,7 @@ public class SkenderTests
{
for (int run = 0; run < iterations; run++)
{
period = rnd.Next(50) + 5;
period = GetRandomNumber(5, 55);
Mgdi ma = new(period: period);
TSeries QL = new();
foreach (TBar item in feed)
@@ -328,7 +335,7 @@ public class SkenderTests
{
for (int run = 0; run < iterations; run++)
{
period = rnd.Next(50) + 5;
period = GetRandomNumber(5, 55);
Atr ma = new(period: period);
TSeries QL = new();
foreach (TBar item in bars) { QL.Add(ma.Calc(item)); }
@@ -342,5 +349,4 @@ public class SkenderTests
}
}
}
}
+30 -36
View File
@@ -1,33 +1,36 @@
using Xunit;
using TALib;
using System.Diagnostics.CodeAnalysis;
using System.Security.Cryptography;
namespace QuanTAlib;
[SuppressMessage("Security", "SCS0005:Weak random number generator.", Justification = "Acceptable for tests")]
public class TAlibTests
{
private readonly TBarSeries bars;
private readonly GbmFeed feed;
private readonly Random rnd;
private readonly RandomNumberGenerator rng;
private readonly double range;
private readonly int iterations;
private readonly double[] data;
private readonly double[] TALIB;
public TAlibTests()
{
rnd = new((int)DateTime.Now.Ticks);
rng = RandomNumberGenerator.Create();
feed = new(sigma: 0.5, mu: 0.0);
bars = new(feed);
range = 1e-9;
feed.Add(10000);
iterations = 3;
data = feed.Close.v.ToArray();
TALIB = new double[data.Count()];
}
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;
}
[Fact]
@@ -35,7 +38,7 @@ public class TAlibTests
{
for (int run = 0; run < iterations; run++)
{
int period = rnd.Next(50) + 5;
int period = GetRandomNumber(5, 55);
Sma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
@@ -44,7 +47,6 @@ public class TAlibTests
Assert.Equal(QL.Length, TALIB.Count());
for (int i = QL.Length - 1; i > period; i--)
{
double TL = i < outBegIdx ? double.NaN : TALIB[i - outBegIdx];
Assert.InRange(TALIB[i - outBegIdx] - QL[i].Value, -range, range);
}
}
@@ -55,7 +57,7 @@ public class TAlibTests
{
for (int run = 0; run < iterations; run++)
{
int period = rnd.Next(50) + 5;
int period = GetRandomNumber(5, 55);
Ema ma = new(period, useSma: true);
TSeries QL = new();
foreach (TBar item in feed)
@@ -64,7 +66,6 @@ public class TAlibTests
Assert.Equal(QL.Length, TALIB.Count());
for (int i = QL.Length - 1; i > period; i--)
{
double TL = i < outBegIdx ? double.NaN : TALIB[i - outBegIdx];
Assert.InRange(TALIB[i - outBegIdx] - QL[i].Value, -range, range);
}
}
@@ -75,7 +76,7 @@ public class TAlibTests
{
for (int run = 0; run < iterations; run++)
{
int period = rnd.Next(50) + 5;
int period = GetRandomNumber(5, 55);
Dema ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
@@ -84,7 +85,6 @@ public class TAlibTests
Assert.Equal(QL.Length, TALIB.Length);
for (int i = QL.Length - 1; i > period * 20; i--)
{
double TL = i < outBegIdx ? double.NaN : TALIB[i - outBegIdx];
Assert.InRange(TALIB[i - outBegIdx] - QL[i].Value, -range, range);
}
}
@@ -95,7 +95,7 @@ public class TAlibTests
{
for (int run = 0; run < iterations; run++)
{
int period = rnd.Next(50) + 5;
int period = GetRandomNumber(5, 55);
Tema ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
@@ -104,41 +104,37 @@ public class TAlibTests
Assert.Equal(QL.Length, TALIB.Length);
for (int i = QL.Length - 1; i > period * 20; i--)
{
double TL = i < outBegIdx ? double.NaN : TALIB[i - outBegIdx];
Assert.InRange(TALIB[i - outBegIdx] - QL[i].Value, -range, range);
}
}
}
//TODO fix WMA
/*
[Fact]
public void WMA()
[Fact]
public void WMA()
{
for (int run = 0; run < iterations; run++)
{
for (int run = 0; run < iterations; run++)
int period = GetRandomNumber(5, 55);
Wma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
Core.Wma(data, 0, QL.Length - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(QL.Length, TALIB.Count());
for (int i = QL.Length - 1; i > period * 3; i--)
{
period = rnd.Next(50) + 5;
Wma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
Core.Wma(data, 0, QL.Length - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(QL.Length, TALIB.Count());
for (int i = QL.Length - 1; i > period*3; i--)
{
double TL = i < outBegIdx ? double.NaN : TALIB[i - outBegIdx];
Assert.InRange(TALIB[i - outBegIdx] - QL[i].Value, -range, range);
}
Assert.InRange(TALIB[i - outBegIdx] - QL[i].Value, -range, range);
}
}
*/
}
[Fact]
public void T3()
{
for (int run = 0; run < iterations; run++)
{
int period = rnd.Next(50) + 5;
int period = GetRandomNumber(5, 55);
T3 ma = new(period, vfactor: 0.7, useSma: false);
TSeries QL = new();
foreach (TBar item in feed)
@@ -147,10 +143,8 @@ public class TAlibTests
Assert.Equal(QL.Length, TALIB.Length);
for (int i = QL.Length - 1; i > period * 20; i--)
{
double TL = i < outBegIdx ? double.NaN : TALIB[i - outBegIdx];
Assert.InRange(TALIB[i - outBegIdx] - QL[i].Value, -range, range);
}
}
}
}
+15 -8
View File
@@ -1,11 +1,11 @@
using System.CommandLine.Rendering.Views;
using System.Security.Cryptography;
namespace QuanTAlib;
public class GbmFeed : TBarSeries
{
private readonly double _mu, _sigma;
private readonly Random _random;
private readonly RandomNumberGenerator _rng;
private double _lastClose, _lastHigh, _lastLow;
public GbmFeed(double initialPrice = 100.0, double mu = 0.05, double sigma = 0.2)
@@ -13,7 +13,7 @@ public class GbmFeed : TBarSeries
_lastClose = _lastHigh = _lastLow = initialPrice;
_mu = mu;
_sigma = sigma;
_random = new Random((int)DateTime.Now.Ticks);
_rng = RandomNumberGenerator.Create();
this.Name = $"GBM({_sigma:F2})";
}
@@ -39,9 +39,9 @@ public class GbmFeed : TBarSeries
double newClose = _lastClose * Math.Exp(drift + diffusion);
double open = _lastClose;
double high = Math.Max(_lastHigh, Math.Max(open, newClose) * (1 + _random.NextDouble() * 0.01));
double low = Math.Min(_lastLow, Math.Min(open, newClose) * (1 - _random.NextDouble() * 0.01));
double volume = 1000 + _random.NextDouble() * 1000;
double high = Math.Max(_lastHigh, Math.Max(open, newClose) * (1 + GenerateRandomDouble() * 0.01));
double low = Math.Min(_lastLow, Math.Min(open, newClose) * (1 - GenerateRandomDouble() * 0.01));
double volume = 1000 + GenerateRandomDouble() * 1000;
if (isNew)
{
@@ -62,8 +62,15 @@ public class GbmFeed : TBarSeries
private double GenerateNormalRandom()
{
// Box-Muller transform to generate standard normal random variable
double u1 = 1.0 - _random.NextDouble(); // Uniform(0,1] random doubles
double u2 = 1.0 - _random.NextDouble();
double u1 = 1.0 - GenerateRandomDouble(); // Uniform(0,1] random doubles
double u2 = 1.0 - GenerateRandomDouble();
return Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2);
}
private double GenerateRandomDouble()
{
byte[] bytes = new byte[8];
_rng.GetBytes(bytes);
return (double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue;
}
}
+6 -18
View File
@@ -18,36 +18,24 @@
<DebugType>full</DebugType>
<ProduceReferenceAssembly>True</ProduceReferenceAssembly>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageTags>
<PackageIcon>QuanTAlib2.png</PackageIcon>
<PackageReadmeFile>readme.md</PackageReadmeFile>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<PackageTags>
Indicators;Stock;Market;Technical;Analysis;Algorithmic;Trading;Trade;Trend;Momentum;Finance;Algorithm;Algo;
AlgoTrading;Financial;Strategy;Chart;Charting;Oscillator;Overlay;Equity;Bitcoin;Crypto;Cryptocurrency;Forex;
Quantitative;Historical;Quotes;
</PackageTags>
<NoWarn>$(NoWarn);NU5104</NoWarn>
<PackageIcon>QuanTAlib2.png</PackageIcon>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<ProduceReferenceAssembly>True</ProduceReferenceAssembly>
<PackageIconUrl>https://raw.githubusercontent.com/mihakralj/QuanTAlib/main/.github/QuanTAlib2.png</PackageIconUrl>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
<PackageTags>
Indicators;Stock;Market;Technical;Analysis;Algorithmic;Trading;Trade;Trend;Momentum;Finance;Algorithm;Algo;
AlgoTrading;Financial;Strategy;Chart;Charting;Oscillator;Overlay;Equity;Bitcoin;Crypto;Cryptocurrency;Forex;
Quantitative;Historical;Quotes;
</PackageTags>
<PackageIcon>QuanTAlib2.png</PackageIcon>
<PackageIconUrl>https://raw.githubusercontent.com/mihakralj/QuanTAlib/main/.github/QuanTAlib2.png</PackageIconUrl>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
</PropertyGroup>
<PropertyGroup>
<PackageIcon>QuanTAlib2.png</PackageIcon>
<PackageIconUrl>https://raw.githubusercontent.com/mihakralj/QuanTAlib/main/.github/QuanTAlib2.png</PackageIconUrl>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
</PropertyGroup>
<ItemGroup>
<None Include="..\docs\readme.md" Pack="true" PackagePath=""/>
<None Include="..\.github\QuanTAlib2.png" Pack="true" Visible="false" PackagePath=""/>
<PackageReference Include="System.Text.Json" Version="9.0.0-rc.1.24431.7" />
</ItemGroup>
<ItemGroup>
<Reference Include="TradingPlatform.BusinessLayer">
<HintPath>..\.github\TradingPlatform.BusinessLayer.dll</HintPath>