using System; using System.Collections.Generic; using Microsoft.VisualStudio.TestTools.UnitTesting; using NT8.Core.Analytics; using NT8.Core.Common.Models; using NT8.Core.Intelligence; using NT8.Core.Logging; namespace NT8.Core.Tests.Analytics { [TestClass] public class GradePerformanceAnalyzerTests { private GradePerformanceAnalyzer _target; [TestInitialize] public void TestInitialize() { _target = new GradePerformanceAnalyzer(new BasicLogger("GradePerformanceAnalyzerTests")); } [TestMethod] public void AnalyzeByGrade_ReturnsReport() { var r = _target.AnalyzeByGrade(Sample()); Assert.IsNotNull(r); } [TestMethod] public void AnalyzeByGrade_HasMetrics() { var r = _target.AnalyzeByGrade(Sample()); Assert.IsTrue(r.MetricsByGrade.Count > 0); } [TestMethod] public void CalculateGradeAccuracy_Bounded() { var a = _target.CalculateGradeAccuracy(TradeGrade.A, Sample()); Assert.IsTrue(a >= 0 && a <= 1); } [TestMethod] public void FindOptimalThreshold_ReturnsEnum() { var t = _target.FindOptimalThreshold(Sample()); Assert.IsTrue(Enum.IsDefined(typeof(TradeGrade), t)); } [TestMethod] public void GetMetricsByGrade_ReturnsAll() { var m = _target.GetMetricsByGrade(Sample()); Assert.IsTrue(m.Count >= 6); } [TestMethod] public void AnalyzeByGrade_Null_Throws() { Assert.ThrowsException(() => _target.AnalyzeByGrade(null)); } [TestMethod] public void Accuracy_Null_Throws() { Assert.ThrowsException(() => _target.CalculateGradeAccuracy(TradeGrade.B, null)); } [TestMethod] public void Threshold_Null_Throws() { Assert.ThrowsException(() => _target.FindOptimalThreshold(null)); } [TestMethod] public void Metrics_Null_Throws() { Assert.ThrowsException(() => _target.GetMetricsByGrade(null)); } [TestMethod] public void Accuracy_Empty_IsZero() { Assert.AreEqual(0.0, _target.CalculateGradeAccuracy(TradeGrade.A, new List()), 0.0001); } [TestMethod] public void SuggestedThreshold_NotDefaultOnData() { var r = _target.AnalyzeByGrade(Sample()); Assert.IsTrue((int)r.SuggestedThreshold >= 1); } [TestMethod] public void Metrics_ContainsA() { var m = _target.GetMetricsByGrade(Sample()); Assert.IsTrue(m.ContainsKey(TradeGrade.A)); } [TestMethod] public void Metrics_ContainsF() { var m = _target.GetMetricsByGrade(Sample()); Assert.IsTrue(m.ContainsKey(TradeGrade.F)); } [TestMethod] public void Analyze_GradeAccuracyPresent() { var r = _target.AnalyzeByGrade(Sample()); Assert.IsTrue(r.GradeAccuracy.ContainsKey(TradeGrade.B)); } [TestMethod] public void Analyze_ExpectancyComputed() { var r = _target.AnalyzeByGrade(Sample()); Assert.IsTrue(r.MetricsByGrade[TradeGrade.A].Expectancy >= -1000); } private static List Sample() { return new List { Trade(TradeGrade.A, 50), Trade(TradeGrade.A, -10), Trade(TradeGrade.B, 20), Trade(TradeGrade.C, -15), Trade(TradeGrade.D, -5), Trade(TradeGrade.F, -25) }; } private static TradeRecord Trade(TradeGrade grade, double pnl) { var t = new TradeRecord(); t.TradeId = Guid.NewGuid().ToString(); t.Symbol = "ES"; t.StrategyName = "S"; t.EntryTime = DateTime.UtcNow; t.ExitTime = DateTime.UtcNow.AddMinutes(1); t.Side = OrderSide.Buy; t.Quantity = 1; t.EntryPrice = 100; t.ExitPrice = 101; t.RealizedPnL = pnl; t.Grade = grade; t.RiskMode = RiskMode.PCP; t.VolatilityRegime = VolatilityRegime.Normal; t.TrendRegime = TrendRegime.Range; t.StopTicks = 8; t.TargetTicks = 16; t.Duration = TimeSpan.FromMinutes(1); return t; } } }