mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-23 21:18:04 +00:00
Refactor indicators to support optional time step in Prime method
- Updated the Prime method signature in multiple indicators (Jma, Kama, Lsma, Mama, Mgdi, Pwma, Rma, Sma, Ssf, Super, T3, Tema, Trima, Usf, Vidya, Wma, Atr) to accept an optional TimeSpan parameter for improved flexibility. - Added unit tests for Lsma to verify Dispose functionality, ensuring proper unsubscription from the source and thread safety. - Enhanced Mama and Wma classes to handle non-finite inputs gracefully and added checks for valid parameters in constructors. - Introduced additional tests for T3 to validate constructor behavior with invalid volume factors. - Ensured all indicators maintain consistent behavior when handling edge cases, such as empty buffers and non-finite values.
This commit is contained in:
@@ -171,6 +171,101 @@ public class T3Tests
|
||||
Assert.Throws<ArgumentException>(() => new T3(-1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_InvalidVFactor_NaN_ThrowsArgumentOutOfRangeException()
|
||||
{
|
||||
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => new T3(5, double.NaN));
|
||||
Assert.Equal("vfactor", ex.ParamName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_InvalidVFactor_PositiveInfinity_ThrowsArgumentOutOfRangeException()
|
||||
{
|
||||
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => new T3(5, double.PositiveInfinity));
|
||||
Assert.Equal("vfactor", ex.ParamName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_InvalidVFactor_NegativeInfinity_ThrowsArgumentOutOfRangeException()
|
||||
{
|
||||
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => new T3(5, double.NegativeInfinity));
|
||||
Assert.Equal("vfactor", ex.ParamName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_InvalidVFactor_Zero_ThrowsArgumentOutOfRangeException()
|
||||
{
|
||||
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => new T3(5, 0.0));
|
||||
Assert.Equal("vfactor", ex.ParamName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_InvalidVFactor_Negative_ThrowsArgumentOutOfRangeException()
|
||||
{
|
||||
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => new T3(5, -0.5));
|
||||
Assert.Equal("vfactor", ex.ParamName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_InvalidVFactor_GreaterThanOne_ThrowsArgumentOutOfRangeException()
|
||||
{
|
||||
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => new T3(5, 1.5));
|
||||
Assert.Equal("vfactor", ex.ParamName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_ValidVFactor_EdgeCases_DoesNotThrow()
|
||||
{
|
||||
// Smallest valid value just above 0
|
||||
var t3_1 = new T3(5, 0.001);
|
||||
Assert.NotNull(t3_1);
|
||||
|
||||
// Valid value of 1.0 (edge case)
|
||||
var t3_2 = new T3(5, 1.0);
|
||||
Assert.NotNull(t3_2);
|
||||
|
||||
// Typical valid values
|
||||
var t3_3 = new T3(5, 0.5);
|
||||
Assert.NotNull(t3_3);
|
||||
|
||||
var t3_4 = new T3(5, 0.7);
|
||||
Assert.NotNull(t3_4);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BatchSpan_InvalidVFactor_NaN_ThrowsArgumentOutOfRangeException()
|
||||
{
|
||||
var input = new double[10];
|
||||
var output = new double[10];
|
||||
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => T3.Batch(input, output, 5, double.NaN));
|
||||
Assert.Equal("vfactor", ex.ParamName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BatchSpan_InvalidVFactor_Infinity_ThrowsArgumentOutOfRangeException()
|
||||
{
|
||||
var input = new double[10];
|
||||
var output = new double[10];
|
||||
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => T3.Batch(input, output, 5, double.PositiveInfinity));
|
||||
Assert.Equal("vfactor", ex.ParamName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BatchSpan_InvalidVFactor_OutOfRange_ThrowsArgumentOutOfRangeException()
|
||||
{
|
||||
var input = new double[10];
|
||||
var output = new double[10];
|
||||
|
||||
var ex1 = Assert.Throws<ArgumentOutOfRangeException>(() => T3.Batch(input, output, 5, 0.0));
|
||||
Assert.Equal("vfactor", ex1.ParamName);
|
||||
|
||||
var ex2 = Assert.Throws<ArgumentOutOfRangeException>(() => T3.Batch(input, output, 5, -0.5));
|
||||
Assert.Equal("vfactor", ex2.ParamName);
|
||||
|
||||
var ex3 = Assert.Throws<ArgumentOutOfRangeException>(() => T3.Batch(input, output, 5, 1.5));
|
||||
Assert.Equal("vfactor", ex3.ParamName);
|
||||
}
|
||||
|
||||
private class TestPublisher : ITValuePublisher
|
||||
{
|
||||
public event TValuePublishedHandler? Pub;
|
||||
@@ -222,4 +317,3 @@ public class T3Tests
|
||||
Assert.Null(exception);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-1
@@ -53,6 +53,10 @@ public sealed class T3 : AbstractBase, IDisposable
|
||||
{
|
||||
if (period <= 0)
|
||||
throw new ArgumentException("Period must be greater than 0", nameof(period));
|
||||
if (!double.IsFinite(vfactor))
|
||||
throw new ArgumentOutOfRangeException(nameof(vfactor), "Volume factor must be a finite number (not NaN or Infinity)");
|
||||
if (vfactor <= 0 || vfactor > 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(vfactor), "Volume factor must be greater than 0 and typically <= 1");
|
||||
|
||||
double alpha = 2.0 / (period + 1);
|
||||
|
||||
@@ -115,7 +119,7 @@ public sealed class T3 : AbstractBase, IDisposable
|
||||
/// Initializes the indicator state using the provided history.
|
||||
/// </summary>
|
||||
/// <param name="source">Historical data</param>
|
||||
public override void Prime(ReadOnlySpan<double> source)
|
||||
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
|
||||
{
|
||||
if (source.Length == 0) return;
|
||||
|
||||
@@ -290,6 +294,10 @@ public sealed class T3 : AbstractBase, IDisposable
|
||||
throw new ArgumentException("Period must be greater than 0", nameof(period));
|
||||
if (source.Length != output.Length)
|
||||
throw new ArgumentException("Source and output must have the same length", nameof(output));
|
||||
if (!double.IsFinite(vfactor))
|
||||
throw new ArgumentOutOfRangeException(nameof(vfactor), "Volume factor must be a finite number (not NaN or Infinity)");
|
||||
if (vfactor <= 0 || vfactor > 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(vfactor), "Volume factor must be greater than 0 and typically <= 1");
|
||||
|
||||
double alpha = 2.0 / (period + 1);
|
||||
double v = vfactor;
|
||||
|
||||
Reference in New Issue
Block a user