mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-24 13:38:05 +00:00
Test completeness
This commit is contained in:
@@ -60,6 +60,7 @@ public class KamaTests
|
||||
|
||||
// Streaming
|
||||
var streamingResults = new TSeries();
|
||||
Assert.True(series.Count > 0);
|
||||
foreach (var item in series)
|
||||
{
|
||||
streamingResults.Add(kamaStreaming.Update(item));
|
||||
@@ -69,9 +70,9 @@ public class KamaTests
|
||||
var batchResults = kamaBatch.Update(series);
|
||||
|
||||
Assert.Equal(streamingResults.Count, batchResults.Count);
|
||||
for (int i = 0; i < streamingResults.Count; i++)
|
||||
foreach (var (stream, batch) in streamingResults.Zip(batchResults))
|
||||
{
|
||||
Assert.Equal(streamingResults[i].Value, batchResults[i].Value, 1e-9);
|
||||
Assert.Equal(stream.Value, batch.Value, 1e-9);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,4 +169,112 @@ public class KamaTests
|
||||
|
||||
Assert.Equal(100, kama.Last.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Kama_Calc_IsNew_AcceptsParameter()
|
||||
{
|
||||
var kama = new Kama(10);
|
||||
kama.Update(new TValue(DateTime.UtcNow, 100), isNew: true);
|
||||
Assert.Equal(100, kama.Last.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Kama_IterativeCorrections_RestoreToOriginalState()
|
||||
{
|
||||
var kama = new Kama(10);
|
||||
var gbm = new GBM(startPrice: 100.0, mu: 0.02, sigma: 0.1);
|
||||
|
||||
// Feed 20 new values (enough to fill buffer and stabilize)
|
||||
TValue lastInput = default;
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
var bar = gbm.Next(isNew: true);
|
||||
lastInput = new TValue(bar.Time, bar.Close);
|
||||
kama.Update(lastInput, isNew: true);
|
||||
}
|
||||
|
||||
// Remember state
|
||||
double valueAfter = kama.Last.Value;
|
||||
|
||||
// Generate 5 corrections with isNew=false (different values)
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
var bar = gbm.Next(isNew: false);
|
||||
kama.Update(new TValue(bar.Time, bar.Close), isNew: false);
|
||||
}
|
||||
|
||||
// Feed the remembered last input again with isNew=false
|
||||
TValue finalValue = kama.Update(lastInput, isNew: false);
|
||||
|
||||
// Should match the original state
|
||||
Assert.Equal(valueAfter, finalValue.Value, 1e-9);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Kama_SpanCalc_ValidatesInput()
|
||||
{
|
||||
double[] source = [1, 2, 3, 4, 5];
|
||||
double[] output = new double[5];
|
||||
double[] wrongSizeOutput = new double[3];
|
||||
|
||||
Assert.Throws<ArgumentException>(() => Kama.Calculate(source.AsSpan(), output.AsSpan(), 0));
|
||||
Assert.Throws<ArgumentException>(() => Kama.Calculate(source.AsSpan(), wrongSizeOutput.AsSpan(), 3));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Kama_SpanCalc_HandlesNaN()
|
||||
{
|
||||
double[] source = [100, 110, double.NaN, 120, 130];
|
||||
double[] output = new double[5];
|
||||
|
||||
Kama.Calculate(source.AsSpan(), output.AsSpan(), 3);
|
||||
|
||||
foreach (var val in output)
|
||||
{
|
||||
Assert.True(double.IsFinite(val));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Kama_AllModes_ProduceSameResult()
|
||||
{
|
||||
// Arrange
|
||||
int period = 10;
|
||||
var gbm = new GBM(startPrice: 100, mu: 0.05, sigma: 0.2, seed: 123);
|
||||
var bars = gbm.Fetch(1000, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
|
||||
var series = bars.Close;
|
||||
|
||||
// 1. Batch Mode
|
||||
var batchSeries = Kama.Calculate(series, period);
|
||||
double expected = batchSeries.Last.Value;
|
||||
|
||||
// 2. Span Mode
|
||||
var tValues = series.Values.ToArray();
|
||||
var spanInput = new ReadOnlySpan<double>(tValues);
|
||||
var spanOutput = new double[tValues.Length];
|
||||
Kama.Calculate(spanInput, spanOutput, period);
|
||||
double spanResult = spanOutput[^1];
|
||||
|
||||
// 3. Streaming Mode
|
||||
var streamingInd = new Kama(period);
|
||||
for (int i = 0; i < series.Count; i++)
|
||||
{
|
||||
streamingInd.Update(series[i]);
|
||||
}
|
||||
double streamingResult = streamingInd.Last.Value;
|
||||
|
||||
// 4. Eventing Mode
|
||||
var pubSource = new TSeries();
|
||||
var eventingInd = new Kama(pubSource, period);
|
||||
for (int i = 0; i < series.Count; i++)
|
||||
{
|
||||
pubSource.Add(series[i]);
|
||||
}
|
||||
double eventingResult = eventingInd.Last.Value;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, spanResult, precision: 9);
|
||||
Assert.Equal(expected, streamingResult, precision: 9);
|
||||
Assert.Equal(expected, eventingResult, precision: 9);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,6 +227,12 @@ public sealed class Kama : ITValuePublisher
|
||||
return new TSeries(t, v);
|
||||
}
|
||||
|
||||
public static TSeries Calculate(TSeries source, int period, int fastPeriod = 2, int slowPeriod = 30)
|
||||
{
|
||||
var kama = new Kama(period, fastPeriod, slowPeriod);
|
||||
return kama.Update(source);
|
||||
}
|
||||
|
||||
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, int period, int fastPeriod = 2, int slowPeriod = 30)
|
||||
{
|
||||
if (period <= 0) throw new ArgumentException("Period must be greater than 0", nameof(period));
|
||||
|
||||
Reference in New Issue
Block a user