mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-25 22:08:05 +00:00
python wrapper
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using Skender.Stock.Indicators;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace QuanTAlib.Tests;
|
||||
@@ -262,4 +263,46 @@ public sealed class KdjValidationTests(ITestOutputHelper output) : IDisposable
|
||||
}
|
||||
return kdj.Last.Value;
|
||||
}
|
||||
|
||||
// ── Skender Cross-Validation ──
|
||||
|
||||
/// <summary>
|
||||
/// Structural validation against Skender <c>GetKdj</c>.
|
||||
/// Skender KDJ uses SMA-based smoothing while QuanTAlib uses Wilder's RMA,
|
||||
/// so numeric equality is not expected. Both must produce finite, bounded output
|
||||
/// and track the same directional movements on the same data.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Validate_Skender_Kdj_Structural()
|
||||
{
|
||||
var data = new ValidationTestData();
|
||||
const int length = 9;
|
||||
const int signal = 3;
|
||||
|
||||
// QuanTAlib KDJ (streaming)
|
||||
var kdj = new Kdj(length, signal);
|
||||
foreach (var bar in data.Bars)
|
||||
{
|
||||
kdj.Update(bar);
|
||||
}
|
||||
|
||||
// Skender Stochastic (KDJ is based on Stochastic %K/%D)
|
||||
var sResult = data.SkenderQuotes.GetStoch(length, signal, signal).ToList();
|
||||
|
||||
// Structural: both produce finite output
|
||||
Assert.True(kdj.IsHot, "QuanTAlib KDJ should be hot");
|
||||
Assert.True(double.IsFinite(kdj.K.Value), "QuanTAlib K must be finite");
|
||||
Assert.True(double.IsFinite(kdj.D.Value), "QuanTAlib D must be finite");
|
||||
|
||||
int finiteCount = sResult.Count(r => r.K is not null && double.IsFinite(r.K.Value));
|
||||
Assert.True(finiteCount > 100, $"Skender should produce >100 finite K values, got {finiteCount}");
|
||||
|
||||
// Directional agreement on final segment (both should agree on overbought/oversold)
|
||||
bool qOverbought = kdj.K.Value > 50;
|
||||
bool sOverbought = sResult[^1].K!.Value > 50;
|
||||
output.WriteLine($"KDJ structural: QuanTAlib K={kdj.K.Value:F2} ({(qOverbought ? "overbought" : "oversold")}), " +
|
||||
$"Skender K={sResult[^1].K:F2} ({(sOverbought ? "overbought" : "oversold")})");
|
||||
|
||||
data.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user