Files
QuanTAlib/quantower/IndicatorExtensions.Tests.cs
T

153 lines
5.7 KiB
C#

using Xunit;
using TradingPlatform.BusinessLayer;
using System.Drawing;
using System.Reflection;
namespace QuanTAlib.Tests;
public class IndicatorExtensionsTests
{
private class TestIndicator : Indicator
{
public TestIndicator()
{
Name = "Test Indicator";
}
}
private class TestCoordinatesConverter : ICoordinatesConverter
{
private readonly DateTime _time;
public TestCoordinatesConverter(DateTime time) => _time = time;
public DateTime GetTime(int x) => _time;
public double GetChartX(DateTime time) => 0;
public double GetChartY(double value) => 0;
}
[Fact]
public void DataSourceInputAttribute_HasCorrectDefaults()
{
var attr = new IndicatorExtensions.DataSourceInputAttribute();
Assert.Equal("Data source", attr.Name);
Assert.Equal(20, attr.SortIndex);
Assert.NotNull(attr.Variants);
Assert.NotEmpty(attr.Variants);
}
[Fact]
public void GetInputValue_ReturnsCorrectValues_ForSourceTypes()
{
var indicator = new TestIndicator();
var now = DateTime.UtcNow;
// Open=100, High=110, Low=90, Close=105, Volume=1000
indicator.HistoricalData.AddBar(now, 100, 110, 90, 105, 1000);
// Ensure Count is updated (mock implementation detail)
// The mock HistoricalData.Count reflects added items.
// Indicator.Count => HistoricalData.Count.
var args = new UpdateArgs(UpdateReason.NewBar);
// Test each SourceType
Assert.Equal(100, IndicatorExtensions.GetInputValue(indicator, args, SourceType.Open).Value);
Assert.Equal(110, IndicatorExtensions.GetInputValue(indicator, args, SourceType.High).Value);
Assert.Equal(90, IndicatorExtensions.GetInputValue(indicator, args, SourceType.Low).Value);
Assert.Equal(105, IndicatorExtensions.GetInputValue(indicator, args, SourceType.Close).Value);
// HL2 = (110 + 90) / 2 = 100
Assert.Equal(100, IndicatorExtensions.GetInputValue(indicator, args, SourceType.HL2).Value);
// OC2 = (100 + 105) / 2 = 102.5
Assert.Equal(102.5, IndicatorExtensions.GetInputValue(indicator, args, SourceType.OC2).Value);
// OHL3 = (100 + 110 + 90) / 3 = 100
Assert.Equal(100, IndicatorExtensions.GetInputValue(indicator, args, SourceType.OHL3).Value);
// HLC3 = (110 + 90 + 105) / 3 = 101.666...
Assert.Equal(101.66666666666667, IndicatorExtensions.GetInputValue(indicator, args, SourceType.HLC3).Value, 5);
// OHLC4 = (100 + 110 + 90 + 105) / 4 = 101.25
Assert.Equal(101.25, IndicatorExtensions.GetInputValue(indicator, args, SourceType.OHLC4).Value);
// HLCC4 = (110 + 90 + 105 + 105) / 4 = 102.5
Assert.Equal(102.5, IndicatorExtensions.GetInputValue(indicator, args, SourceType.HLCC4).Value);
}
[Fact]
public void GetInputBar_ReturnsCorrectBar()
{
var indicator = new TestIndicator();
var now = DateTime.UtcNow;
indicator.HistoricalData.AddBar(now, 100, 110, 90, 105, 1000);
var args = new UpdateArgs(UpdateReason.NewBar);
var bar = IndicatorExtensions.GetInputBar(indicator, args);
Assert.Equal(now, bar.AsDateTime);
Assert.Equal(100, bar.Open);
Assert.Equal(110, bar.High);
Assert.Equal(90, bar.Low);
Assert.Equal(105, bar.Close);
Assert.Equal(1000, bar.Volume);
}
[Fact]
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
public void PaintMethods_DoNotThrow_WithValidGraphics()
{
// This test attempts to verify that paint methods don't crash.
// It requires System.Drawing.Common to be functional.
if (!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows))
{
// Skip on non-Windows if System.Drawing is not fully supported (GDI+)
return;
}
using var bitmap = new Bitmap(100, 100);
using var graphics = Graphics.FromImage(bitmap);
var indicator = new TestIndicator();
indicator.CurrentChart = new MockChart();
// Add some data
var now = new DateTime(2024, 1, 1, 12, 0, 0, DateTimeKind.Utc);
for (int i = 0; i < 20; i++)
{
indicator.HistoricalData.AddBar(now.AddMinutes(i), 100, 110, 90, 105);
}
// Setup converter to return a time that exists in our data (e.g. the middle bar)
// We added bars at now, now+1min, ..., now+19min.
// Let's return now+10min.
var validTime = now.AddMinutes(10);
indicator.CurrentChart.MainWindow.CoordinatesConverter = new TestCoordinatesConverter(validTime);
var args = new PaintChartEventArgs(graphics, new Rectangle(0, 0, 100, 100));
using var pen = new Pen(Color.Red);
// Test PaintHLine
IndicatorExtensions.PaintHLine(indicator, args, 100, pen);
// Test PaintSmoothCurve
var series = new LineSeries("Test", Color.Blue, 1, LineStyle.Solid);
for (int i = 0; i < 20; i++) series.AddValue(); // Fill with NaNs or values
for (int i = 0; i < 20; i++) series.SetValue(100 + i, i); // Set some values
IndicatorExtensions.PaintSmoothCurve(indicator, args, series, 0);
// Test PaintHistogram
IndicatorExtensions.PaintHistogram(indicator, args, series, 0);
// Test DrawText
IndicatorExtensions.DrawText(indicator, args, "Test Text");
// Assert that we reached the end without throwing
Assert.True(true);
}
}