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 OptimizationTests { [TestMethod] public void ParameterOptimizer_OptimizeParameter_ReturnsResult() { var target = new ParameterOptimizer(new BasicLogger("OptimizationTests")); var result = target.OptimizeParameter("test", new List { 1, 2, 3 }, Trades()); Assert.IsNotNull(result); Assert.AreEqual("test", result.ParameterName); } [TestMethod] public void ParameterOptimizer_GridSearch_ReturnsResult() { var target = new ParameterOptimizer(new BasicLogger("OptimizationTests")); var p = new Dictionary>(); p.Add("a", new List { 1, 2 }); p.Add("b", new List { 3, 4 }); var result = target.GridSearch(p, Trades()); Assert.IsTrue(result.MetricsByCombination.Count > 0); } [TestMethod] public void ParameterOptimizer_WalkForward_ReturnsResult() { var target = new ParameterOptimizer(new BasicLogger("OptimizationTests")); var cfg = new StrategyConfig("S", "ES", new Dictionary(), new RiskConfig(1000, 500, 5, true), new SizingConfig(SizingMethod.FixedContracts, 1, 5, 200, new Dictionary())); var bars = Bars(); var result = target.WalkForwardTest(cfg, bars); Assert.IsNotNull(result); } [TestMethod] public void MonteCarlo_Simulate_ReturnsDistribution() { var target = new MonteCarloSimulator(new BasicLogger("OptimizationTests")); var result = target.Simulate(Trades(), 100, 20); Assert.AreEqual(100, result.FinalPnLDistribution.Count); } [TestMethod] public void MonteCarlo_RiskOfRuin_InRange() { var target = new MonteCarloSimulator(new BasicLogger("OptimizationTests")); var r = target.CalculateRiskOfRuin(Trades(), 50.0); Assert.IsTrue(r >= 0.0 && r <= 1.0); } [TestMethod] public void MonteCarlo_ConfidenceInterval_ReturnsBounds() { var target = new MonteCarloSimulator(new BasicLogger("OptimizationTests")); var result = target.Simulate(Trades(), 100, 20); var ci = target.CalculateConfidenceInterval(result, 0.95); Assert.IsTrue(ci.UpperBound >= ci.LowerBound); } [TestMethod] public void PortfolioOptimizer_OptimizeAllocation_ReturnsWeights() { var target = new PortfolioOptimizer(new BasicLogger("OptimizationTests")); var result = target.OptimizeAllocation(Strategies()); Assert.IsTrue(result.Allocation.Count > 0); } [TestMethod] public void PortfolioOptimizer_RiskParity_ReturnsWeights() { var target = new PortfolioOptimizer(new BasicLogger("OptimizationTests")); var weights = target.RiskParityAllocation(Strategies()); Assert.IsTrue(weights.Count > 0); } [TestMethod] public void PortfolioOptimizer_Sharpe_Computes() { var target = new PortfolioOptimizer(new BasicLogger("OptimizationTests")); var s = Strategies(); var a = new Dictionary(); a.Add("A", 0.5); a.Add("B", 0.5); var sharpe = target.CalculatePortfolioSharpe(a, s); Assert.IsTrue(sharpe >= 0.0 || sharpe < 0.0); } [TestMethod] public void MonteCarlo_InvalidConfidence_Throws() { var t = new MonteCarloSimulator(new BasicLogger("OptimizationTests")); var r = t.Simulate(Trades(), 20, 10); Assert.ThrowsException(() => t.CalculateConfidenceInterval(r, 1.0)); } [TestMethod] public void ParameterOptimizer_NullTrades_Throws() { var t = new ParameterOptimizer(new BasicLogger("OptimizationTests")); Assert.ThrowsException(() => t.OptimizeParameter("x", new List { 1 }, null)); } [TestMethod] public void PortfolioOptimizer_NullStrategies_Throws() { var t = new PortfolioOptimizer(new BasicLogger("OptimizationTests")); Assert.ThrowsException(() => t.OptimizeAllocation(null)); } private static List Trades() { var list = new List(); for (var i = 0; i < 30; i++) { var t = new TradeRecord(); t.TradeId = i.ToString(); t.Symbol = "ES"; t.StrategyName = i % 2 == 0 ? "A" : "B"; t.EntryTime = DateTime.UtcNow.AddMinutes(i); t.ExitTime = DateTime.UtcNow.AddMinutes(i + 1); t.Side = OrderSide.Buy; t.Quantity = 1; t.EntryPrice = 100; t.ExitPrice = 101; t.RealizedPnL = i % 3 == 0 ? -10 : 15; t.Grade = TradeGrade.B; t.RiskMode = RiskMode.PCP; t.VolatilityRegime = VolatilityRegime.Normal; t.TrendRegime = TrendRegime.Range; t.StopTicks = 8; t.TargetTicks = 16; t.Duration = TimeSpan.FromMinutes(1); list.Add(t); } return list; } private static List Bars() { var list = new List(); for (var i = 0; i < 20; i++) { list.Add(new BarData("ES", DateTime.UtcNow.AddMinutes(i), 100 + i, 101 + i, 99 + i, 100.5 + i, 1000, TimeSpan.FromMinutes(1))); } return list; } private static List Strategies() { var a = new StrategyPerformance(); a.StrategyName = "A"; a.MeanReturn = 1.2; a.StdDevReturn = 0.8; a.Sharpe = 1.5; a.Correlations.Add("B", 0.2); var b = new StrategyPerformance(); b.StrategyName = "B"; b.MeanReturn = 0.9; b.StdDevReturn = 0.7; b.Sharpe = 1.28; b.Correlations.Add("A", 0.2); return new List { a, b }; } } }