using System.Linq;
using PolyTrader.Modules.CopyTrading.Logic;
using Xunit;
using static PolyTrader.Modules.CopyTrading.Logic.TraderScore;
namespace PolyTrader.Tests
{
///
/// Sicherheitsnetz für die Copy-Score-Kennzahlen und den Auto-Pause-Kill-Switch (Phase 3).
///
public class TraderScoreTests
{
[Fact]
public void Compute_metrics_from_mixed_pnls()
{
var m = Compute(new[] { 10m, -3m, 5m, -2m });
Assert.Equal(4, m.TradeCount);
Assert.Equal(10m, m.CopyPnl);
Assert.Equal(3.0m, m.ProfitFactor); // grossProfit 15 / grossLoss 5
Assert.Equal(2.5m, m.AvgPnlPerTrade); // 10 / 4
}
[Fact]
public void Compute_empty_is_all_zero()
{
var m = Compute(Enumerable.Empty());
Assert.Equal(0, m.TradeCount);
Assert.Equal(0m, m.CopyPnl);
Assert.Equal(0m, m.ProfitFactor);
Assert.Equal(0m, m.AvgPnlPerTrade);
}
[Fact]
public void Compute_all_wins_uses_no_loss_sentinel()
{
var m = Compute(new[] { 5m, 5m });
Assert.Equal(NoLossProfitFactor, m.ProfitFactor);
Assert.Equal(10m, m.CopyPnl);
}
[Fact]
public void Compute_all_losses_profit_factor_zero()
{
var m = Compute(new[] { -5m, -5m });
Assert.Equal(0m, m.ProfitFactor);
Assert.Equal(-10m, m.CopyPnl);
Assert.Equal(-5m, m.AvgPnlPerTrade);
}
[Theory]
[InlineData(false, 20, -50, 10, 10, false)] // deaktiviert
[InlineData(true, 5, -50, 10, 10, false)] // zu wenige Trades
[InlineData(true, 12, -15, 10, 10, true)] // Verlust über Schwelle
[InlineData(true, 12, -5, 10, 10, false)] // Verlust unter Schwelle
[InlineData(true, 12, 20, 10, 10, false)] // im Plus
[InlineData(true, 12, -10, 10, 10, true)] // genau auf der Schwelle
public void ShouldAutoPause_rules(bool enabled, int count, double pnl, int minTrades, double threshold, bool expected)
{
Assert.Equal(expected, ShouldAutoPause(enabled, count, (decimal)pnl, minTrades, (decimal)threshold));
}
}
}