using FluentAssertions; using Managing.Domain.Accounts; using Managing.Domain.Shared.Helpers; using Managing.Domain.Statistics; using Xunit; namespace Managing.Domain.Tests; /// /// Tests for trader analysis methods in TradingBox. /// Covers trader evaluation, filtering, and analysis methods. /// public class TraderAnalysisTests : TradingBoxTests { [Fact] public void IsAGoodTrader_WithAllCriteriaMet_ReturnsTrue() { // Arrange var trader = new Trader { Winrate = 35, // > 30 TradeCount = 10, // > 8 AverageWin = 100m, AverageLoss = -50m, // |AverageLoss| < AverageWin Pnl = 250m // > 0 }; // Act var result = TradingBox.IsAGoodTrader(trader); // Assert result.Should().BeTrue(); } [Fact] public void IsAGoodTrader_WithLowWinrate_ReturnsFalse() { // Arrange var trader = new Trader { Winrate = 25, // < 30 TradeCount = 10, AverageWin = 100m, AverageLoss = -50m, Pnl = 250m }; // Act var result = TradingBox.IsAGoodTrader(trader); // Assert result.Should().BeFalse(); } [Fact] public void IsAGoodTrader_WithInsufficientTrades_ReturnsFalse() { // Arrange var trader = new Trader { Winrate = 35, TradeCount = 5, // < 8 AverageWin = 100m, AverageLoss = -50m, Pnl = 250m }; // Act var result = TradingBox.IsAGoodTrader(trader); // Assert result.Should().BeFalse(); } [Fact] public void IsAGoodTrader_WithPoorRiskReward_ReturnsFalse() { // Arrange var trader = new Trader { Winrate = 35, TradeCount = 10, AverageWin = 50m, AverageLoss = -100m, // |AverageLoss| > AverageWin Pnl = 250m }; // Act var result = TradingBox.IsAGoodTrader(trader); // Assert result.Should().BeFalse(); } [Fact] public void IsAGoodTrader_WithNegativePnL_ReturnsFalse() { // Arrange var trader = new Trader { Winrate = 35, TradeCount = 10, AverageWin = 100m, AverageLoss = -50m, Pnl = -50m // < 0 }; // Act var result = TradingBox.IsAGoodTrader(trader); // Assert result.Should().BeFalse(); } [Fact] public void IsABadTrader_WithAllCriteriaMet_ReturnsTrue() { // Arrange var trader = new Trader { Winrate = 25, // < 30 TradeCount = 10, // > 8 AverageWin = 50m, AverageLoss = -200m, // |AverageLoss| * 3 > AverageWin Pnl = -500m // < 0 }; // Act var result = TradingBox.IsABadTrader(trader); // Assert result.Should().BeTrue(); } [Fact] public void IsABadTrader_WithGoodWinrate_ReturnsFalse() { // Arrange var trader = new Trader { Winrate = 35, // > 30 TradeCount = 10, AverageWin = 50m, AverageLoss = -200m, Pnl = -500m }; // Act var result = TradingBox.IsABadTrader(trader); // Assert result.Should().BeFalse(); } [Fact] public void IsABadTrader_WithInsufficientTrades_ReturnsFalse() { // Arrange var trader = new Trader { Winrate = 25, TradeCount = 5, // < 8 AverageWin = 50m, AverageLoss = -200m, Pnl = -500m }; // Act var result = TradingBox.IsABadTrader(trader); // Assert result.Should().BeFalse(); } [Fact] public void IsABadTrader_WithGoodRiskReward_ReturnsFalse() { // Arrange var trader = new Trader { Winrate = 25, TradeCount = 10, AverageWin = 200m, // AverageWin > |AverageLoss| * 3 AverageLoss = -50m, Pnl = -500m }; // Act var result = TradingBox.IsABadTrader(trader); // Assert result.Should().BeFalse(); } [Fact] public void IsABadTrader_WithPositivePnL_ReturnsFalse() { // Arrange var trader = new Trader { Winrate = 25, TradeCount = 10, AverageWin = 50m, AverageLoss = -200m, Pnl = 100m // > 0 }; // Act var result = TradingBox.IsABadTrader(trader); // Assert result.Should().BeFalse(); } [Fact] public void FindBadTrader_WithEmptyList_ReturnsEmptyList() { // Arrange var traders = new List(); // Act var result = traders.FindBadTrader(); // Assert result.Should().BeEmpty(); } [Fact] public void FindBadTrader_WithOnlyGoodTraders_ReturnsEmptyList() { // Arrange var traders = new List { new Trader { Winrate = 35, TradeCount = 10, AverageWin = 100m, AverageLoss = -50m, Pnl = 250m }, new Trader { Winrate = 40, TradeCount = 15, AverageWin = 150m, AverageLoss = -75m, Pnl = 500m } }; // Act var result = traders.FindBadTrader(); // Assert result.Should().BeEmpty(); } [Fact] public void FindBadTrader_WithMixedTraders_ReturnsOnlyBadTraders() { // Arrange var goodTrader = new Trader { Winrate = 35, TradeCount = 10, AverageWin = 100m, AverageLoss = -50m, Pnl = 250m }; var badTrader1 = new Trader { Winrate = 25, TradeCount = 10, AverageWin = 50m, AverageLoss = -200m, Pnl = -500m }; var badTrader2 = new Trader { Winrate = 20, TradeCount = 12, AverageWin = 30m, AverageLoss = -150m, Pnl = -300m }; var traders = new List { goodTrader, badTrader1, badTrader2 }; // Act var result = traders.FindBadTrader(); // Assert result.Should().HaveCount(2); result.Should().Contain(badTrader1); result.Should().Contain(badTrader2); result.Should().NotContain(goodTrader); } [Fact] public void FindGoodTrader_WithEmptyList_ReturnsEmptyList() { // Arrange var traders = new List(); // Act var result = traders.FindGoodTrader(); // Assert result.Should().BeEmpty(); } [Fact] public void FindGoodTrader_WithOnlyBadTraders_ReturnsEmptyList() { // Arrange var traders = new List { new Trader { Winrate = 25, TradeCount = 10, AverageWin = 50m, AverageLoss = -200m, Pnl = -500m }, new Trader { Winrate = 20, TradeCount = 12, AverageWin = 30m, AverageLoss = -150m, Pnl = -300m } }; // Act var result = traders.FindGoodTrader(); // Assert result.Should().BeEmpty(); } [Fact] public void FindGoodTrader_WithMixedTraders_ReturnsOnlyGoodTraders() { // Arrange var badTrader = new Trader { Winrate = 25, TradeCount = 10, AverageWin = 50m, AverageLoss = -200m, Pnl = -500m }; var goodTrader1 = new Trader { Winrate = 35, TradeCount = 10, AverageWin = 100m, AverageLoss = -50m, Pnl = 250m }; var goodTrader2 = new Trader { Winrate = 40, TradeCount = 15, AverageWin = 150m, AverageLoss = -75m, Pnl = 500m }; var traders = new List { badTrader, goodTrader1, goodTrader2 }; // Act var result = traders.FindGoodTrader(); // Assert result.Should().HaveCount(2); result.Should().Contain(goodTrader1); result.Should().Contain(goodTrader2); result.Should().NotContain(badTrader); } [Fact] public void MapToTraders_WithAccounts_CreatesTradersWithCorrectAddresses() { // Arrange var account1 = new Account { Key = "0x123", Name = "Account1" }; var account2 = new Account { Key = "0x456", Name = "Account2" }; var accounts = new List { account1, account2 }; // Act var result = accounts.MapToTraders(); // Assert result.Should().HaveCount(2); result[0].Address.Should().Be("0x123"); result[1].Address.Should().Be("0x456"); } [Fact] public void MapToTraders_WithEmptyList_ReturnsEmptyList() { // Arrange var accounts = new List(); // Act var result = accounts.MapToTraders(); // Assert result.Should().BeEmpty(); } [Theory] [InlineData(35, 10, 100, -50, 250, true)] // Good trader [InlineData(25, 10, 50, -200, -500, false)] // Bad trader [InlineData(29, 9, 50, -150, -100, false)] // Boundary bad trader [InlineData(32, 7, 100, -50, 200, false)] // Insufficient trades [InlineData(28, 10, 200, -50, -100, false)] // Good RR but low winrate public void TraderEvaluation_TheoryTests(int winrate, int tradeCount, decimal avgWin, decimal avgLoss, decimal pnl, bool expectedGood) { // Arrange var trader = new Trader { Winrate = winrate, TradeCount = tradeCount, AverageWin = avgWin, AverageLoss = avgLoss, Pnl = pnl }; // Act & Assert if (expectedGood) { TradingBox.IsAGoodTrader(trader).Should().BeTrue(); TradingBox.IsABadTrader(trader).Should().BeFalse(); } else { TradingBox.IsAGoodTrader(trader).Should().BeFalse(); // Bad trader evaluation depends on multiple criteria } } [Fact] public void TraderAnalysis_MethodsAreConsistent() { // Arrange var trader = new Trader { Winrate = 35, TradeCount = 10, AverageWin = 100m, AverageLoss = -50m, Pnl = 250m }; // Act var isGood = TradingBox.IsAGoodTrader(trader); var isBad = TradingBox.IsABadTrader(trader); // Assert // A trader cannot be both good and bad (isGood && isBad).Should().BeFalse(); } [Fact] public void FindMethods_WorkTogetherCorrectly() { // Arrange var traders = new List { new Trader { Winrate = 35, TradeCount = 10, AverageWin = 100m, AverageLoss = -50m, Pnl = 250m }, // Good new Trader { Winrate = 25, TradeCount = 10, AverageWin = 50m, AverageLoss = -200m, Pnl = -500m }, // Bad new Trader { Winrate = 32, TradeCount = 5, AverageWin = 75m, AverageLoss = -75m, Pnl = 0m } // Neither }; // Act var goodTraders = traders.FindGoodTrader(); var badTraders = traders.FindBadTrader(); // Assert goodTraders.Should().HaveCount(1); badTraders.Should().HaveCount(1); goodTraders.First().Should().NotBe(badTraders.First()); } }