mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-18 10:38:05 +00:00
Enhance validation tests for various indicators with external library comparisons
- Added detailed comments explaining the validation limitations for MMA and ZLEMA due to differences in algorithm implementations. - Implemented validation tests for True Range against TALib and Tulip, ensuring directional agreement. - Updated Ulcer Index validation to clarify differences in algorithmic approaches between QuanTAlib and Skender. - Enhanced Ease of Movement tests to verify directional agreement with Tulip's EMV, noting differences in volume scaling. - Expanded Klinger Volume Oscillator tests to validate against Skender and Tulip, focusing on directional agreement across multiple period configurations. - Improved Negative Volume Index tests to compare percentage changes with Tulip, addressing differences in starting values. - Updated Positive Volume Index tests to validate against Tulip, emphasizing percentage change comparisons. - Enhanced Williams Accumulation/Distribution tests to verify directional agreement with Tulip, highlighting formula differences.
This commit is contained in:
@@ -1,18 +1,21 @@
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace QuanTAlib.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Validation tests for Qstick indicator.
|
||||
/// Validates against manual formula calculations since Qstick is not
|
||||
/// available in TA-Lib, Skender, Tulip, or Ooples.
|
||||
/// Validates against manual formula calculations and Tulip Indicators qstick.
|
||||
/// Qstick is not available in TA-Lib, Skender, or Ooples.
|
||||
/// </summary>
|
||||
public sealed class QstickValidationTests : IDisposable
|
||||
{
|
||||
private readonly ValidationTestData _data;
|
||||
private readonly ITestOutputHelper _output;
|
||||
|
||||
public QstickValidationTests()
|
||||
public QstickValidationTests(ITestOutputHelper output)
|
||||
{
|
||||
_output = output;
|
||||
_data = new ValidationTestData();
|
||||
}
|
||||
|
||||
@@ -350,4 +353,72 @@ public sealed class QstickValidationTests : IDisposable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// Tulip Indicators Cross-Validation
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
[Fact]
|
||||
public void Validate_Tulip_Qstick()
|
||||
{
|
||||
// Tulip qstick: inputs = {open[], close[]}, options = {period}, outputs = {qstick[]}
|
||||
// Formula: SMA(close - open, period) — same as QuanTAlib Qstick with useEma=false
|
||||
int period = 14;
|
||||
|
||||
double[] openData = _data.OpenPrices.ToArray();
|
||||
double[] closeData = _data.ClosePrices.ToArray();
|
||||
|
||||
// QuanTAlib batch
|
||||
var qSeries = Qstick.Batch(_data.Bars, period);
|
||||
double[] qResult = new double[qSeries.Count];
|
||||
for (int i = 0; i < qSeries.Count; i++)
|
||||
{
|
||||
qResult[i] = qSeries[i].Value;
|
||||
}
|
||||
|
||||
// Tulip qstick
|
||||
var indicator = Tulip.Indicators.qstick;
|
||||
double[][] inputs = { openData, closeData };
|
||||
double[] options = { period };
|
||||
double[][] outputs = { new double[openData.Length] };
|
||||
indicator.Run(inputs, options, outputs);
|
||||
double[] tResult = outputs[0];
|
||||
|
||||
// Tulip output is shorter by (period-1) — lookback = period - 1
|
||||
int lookback = period - 1;
|
||||
ValidationHelper.VerifyData(qResult, tResult, lookback);
|
||||
|
||||
_output.WriteLine($"Qstick validated against Tulip Indicators (period={period})");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_Tulip_Qstick_MultiplePeriods()
|
||||
{
|
||||
int[] periods = { 5, 10, 20, 50 };
|
||||
|
||||
foreach (int period in periods)
|
||||
{
|
||||
double[] openData = _data.OpenPrices.ToArray();
|
||||
double[] closeData = _data.ClosePrices.ToArray();
|
||||
|
||||
var qSeries = Qstick.Batch(_data.Bars, period);
|
||||
double[] qResult = new double[qSeries.Count];
|
||||
for (int i = 0; i < qSeries.Count; i++)
|
||||
{
|
||||
qResult[i] = qSeries[i].Value;
|
||||
}
|
||||
|
||||
var indicator = Tulip.Indicators.qstick;
|
||||
double[][] inputs = { openData, closeData };
|
||||
double[] options = { period };
|
||||
double[][] outputs = { new double[openData.Length] };
|
||||
indicator.Run(inputs, options, outputs);
|
||||
double[] tResult = outputs[0];
|
||||
|
||||
int lookback = period - 1;
|
||||
ValidationHelper.VerifyData(qResult, tResult, lookback);
|
||||
}
|
||||
|
||||
_output.WriteLine("Qstick validated against Tulip for multiple periods (5, 10, 20, 50)");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user