Files
Miha Kralj 060649192f docs: remove C# Implementation Considerations sections, clean up temp scripts, reorganize test files
- Remove 'C# Implementation Considerations' sections from 34 indicator .md files
- Delete 29 temp PowerShell scripts (_fix_mojibake.ps1, _hex_scan.ps1, etc.)
- Move test files into tests/ subdirectories for consistent project structure
- Add trader-focused bullet points to indicator documentation
2026-03-12 12:34:16 -07:00

231 lines
7.2 KiB
C#

using TradingPlatform.BusinessLayer;
namespace QuanTAlib.Tests;
public class VaIndicatorTests
{
[Fact]
public void VaIndicator_Constructor_SetsDefaults()
{
var indicator = new VaIndicator();
Assert.Equal("VA - Volume Accumulation", indicator.Name);
Assert.True(indicator.SeparateWindow);
Assert.True(indicator.OnBackGround);
Assert.Equal(1, indicator.MinHistoryDepths);
}
[Fact]
public void VaIndicator_ShortName_IsConstant()
{
var indicator = new VaIndicator();
Assert.Equal("VA", indicator.ShortName);
}
[Fact]
public void VaIndicator_MinHistoryDepths_EqualsOne()
{
var indicator = new VaIndicator();
Assert.Equal(1, indicator.MinHistoryDepths);
Assert.Equal(1, ((IWatchlistIndicator)indicator).MinHistoryDepths);
}
[Fact]
public void VaIndicator_Initialize_CreatesInternalVa()
{
var indicator = new VaIndicator();
// Initialize should not throw
indicator.Initialize();
// After init, line series should exist
Assert.Single(indicator.LinesSeries);
}
[Fact]
public void VaIndicator_ProcessUpdate_HistoricalBar_ComputesValue()
{
var indicator = new VaIndicator();
indicator.Initialize();
var now = DateTime.UtcNow;
for (int i = 0; i < 30; i++)
{
double close = 100 + i * 0.5;
indicator.HistoricalData.AddBar(now.AddMinutes(i), close - 2, close + 2, close - 3, close, 100000);
var args = new UpdateArgs(UpdateReason.HistoricalBar);
indicator.ProcessUpdate(args);
}
double val = indicator.LinesSeries[0].GetValue(0);
Assert.True(double.IsFinite(val));
}
[Fact]
public void VaIndicator_ProcessUpdate_NewBar_ComputesValue()
{
var indicator = new VaIndicator();
indicator.Initialize();
var now = DateTime.UtcNow;
for (int i = 0; i < 30; i++)
{
indicator.HistoricalData.AddBar(now.AddMinutes(i), 100, 110, 90, 105, 100000);
}
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
// Add new bar
indicator.HistoricalData.AddBar(now.AddMinutes(30), 105, 115, 100, 112, 80000);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.NewBar));
Assert.Equal(2, indicator.LinesSeries[0].Count);
}
[Fact]
public void VaIndicator_CloseAboveMidpoint_PositiveAccumulation()
{
var indicator = new VaIndicator();
indicator.Initialize();
var now = DateTime.UtcNow;
// Bar: H=110, L=90, C=105, V=1000
// midpoint = (110 + 90) / 2 = 100
// va_period = 1000 * (105 - 100) = 5000
indicator.HistoricalData.AddBar(now, 100, 110, 90, 105, 1000);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
double val = indicator.LinesSeries[0].GetValue(0);
Assert.Equal(5000, val, 1);
}
[Fact]
public void VaIndicator_CloseBelowMidpoint_NegativeAccumulation()
{
var indicator = new VaIndicator();
indicator.Initialize();
var now = DateTime.UtcNow;
// Bar: H=110, L=90, C=95, V=1000
// midpoint = (110 + 90) / 2 = 100
// va_period = 1000 * (95 - 100) = -5000
indicator.HistoricalData.AddBar(now, 100, 110, 90, 95, 1000);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
double val = indicator.LinesSeries[0].GetValue(0);
Assert.Equal(-5000, val, 1);
}
[Fact]
public void VaIndicator_CloseAtMidpoint_ZeroAccumulation()
{
var indicator = new VaIndicator();
indicator.Initialize();
var now = DateTime.UtcNow;
// Bar: H=110, L=90, C=100, V=1000
// midpoint = (110 + 90) / 2 = 100
// va_period = 1000 * (100 - 100) = 0
indicator.HistoricalData.AddBar(now, 100, 110, 90, 100, 1000);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
double val = indicator.LinesSeries[0].GetValue(0);
Assert.Equal(0, val, 1);
}
[Fact]
public void VaIndicator_MultipleBarAccumulation_CorrectSum()
{
var indicator = new VaIndicator();
indicator.Initialize();
var now = DateTime.UtcNow;
// Bar 1: midpoint=100, close=105, vol=1000 -> va=5000
indicator.HistoricalData.AddBar(now, 100, 110, 90, 105, 1000);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
// Bar 2: midpoint=100, close=95, vol=500 -> va_period=-2500, total=2500
indicator.HistoricalData.AddBar(now.AddMinutes(1), 100, 110, 90, 95, 500);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.NewBar));
double val = indicator.LinesSeries[0].GetValue(0);
Assert.Equal(2500, val, 1);
}
[Fact]
public void VaIndicator_LargeVolume_LargerImpact()
{
var indicator1 = new VaIndicator();
indicator1.Initialize();
var indicator2 = new VaIndicator();
indicator2.Initialize();
var now = DateTime.UtcNow;
// Same price action, different volume
indicator1.HistoricalData.AddBar(now, 100, 110, 90, 105, 1000);
indicator1.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
indicator2.HistoricalData.AddBar(now, 100, 110, 90, 105, 10000);
indicator2.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
double val1 = indicator1.LinesSeries[0].GetValue(0);
double val2 = indicator2.LinesSeries[0].GetValue(0);
// 10x volume should produce 10x VA
Assert.Equal(val1 * 10, val2, 1);
}
[Fact]
public void VaIndicator_CumulativeNature_AlwaysAccumulates()
{
var indicator = new VaIndicator();
indicator.Initialize();
var now = DateTime.UtcNow;
double lastVa = 0;
// Add multiple positive bars - VA should keep increasing
for (int i = 0; i < 10; i++)
{
indicator.HistoricalData.AddBar(now.AddMinutes(i), 100, 110, 90, 108, 1000);
var args = i == 0
? new UpdateArgs(UpdateReason.HistoricalBar)
: new UpdateArgs(UpdateReason.NewBar);
indicator.ProcessUpdate(args);
double currentVa = indicator.LinesSeries[0].GetValue(0);
Assert.True(currentVa > lastVa, $"VA should increase: {currentVa} > {lastVa}");
lastVa = currentVa;
}
}
[Fact]
public void VaIndicator_MixedPressure_CorrectNetEffect()
{
var indicator = new VaIndicator();
indicator.Initialize();
var now = DateTime.UtcNow;
// Equal positive and negative with same volume should net to zero
// Bar 1: +5000 (close above midpoint)
indicator.HistoricalData.AddBar(now, 100, 110, 90, 105, 1000);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
// Bar 2: -5000 (close below midpoint by same amount)
indicator.HistoricalData.AddBar(now.AddMinutes(1), 100, 110, 90, 95, 1000);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.NewBar));
double val = indicator.LinesSeries[0].GetValue(0);
Assert.Equal(0, val, 1);
}
}