using System; using System.Collections.Generic; using System.Diagnostics; using Microsoft.VisualStudio.TestTools.UnitTesting; using NT8.Core.Common.Models; using NT8.Core.Intelligence; using NT8.Core.Logging; namespace NT8.Performance.Tests { [TestClass] public class Phase4PerformanceTests { [TestMethod] public void ConfluenceScoreCalculation_ShouldBeUnder5ms_Average() { var scorer = new ConfluenceScorer(new BasicLogger("Phase4PerformanceTests"), 200); var intent = CreateIntent(OrderSide.Buy); var context = CreateContext(); var bar = CreateBar(); var factors = CreateFactors(0.82, 0.76, 0.88, 0.79, 0.81); var sw = Stopwatch.StartNew(); for (var i = 0; i < 1000; i++) { var score = scorer.CalculateScore(intent, context, bar, factors); Assert.IsTrue(score.WeightedScore >= 0.0); } sw.Stop(); var avgMs = sw.Elapsed.TotalMilliseconds / 1000.0; Assert.IsTrue(avgMs < 5.0, string.Format("Average confluence scoring time {0:F4}ms exceeded 5ms", avgMs)); } [TestMethod] public void RegimeDetection_ShouldBeUnder3ms_Average() { var volDetector = new VolatilityRegimeDetector(new BasicLogger("Phase4PerformanceTests"), 100); var trendDetector = new TrendRegimeDetector(new BasicLogger("Phase4PerformanceTests")); var bars = BuildBars(12, 5000.0, 0.75); var sw = Stopwatch.StartNew(); for (var i = 0; i < 1000; i++) { var vol = volDetector.DetectRegime("ES", 1.0 + ((i % 6) * 0.2), 1.0); var trend = trendDetector.DetectTrend("ES", bars, 5000.0); Assert.IsTrue(Enum.IsDefined(typeof(VolatilityRegime), vol)); Assert.IsTrue(Enum.IsDefined(typeof(TrendRegime), trend)); } sw.Stop(); var avgMs = sw.Elapsed.TotalMilliseconds / 1000.0; Assert.IsTrue(avgMs < 3.0, string.Format("Average regime detection time {0:F4}ms exceeded 3ms", avgMs)); } [TestMethod] public void GradeFiltering_ShouldBeUnder1ms_Average() { var filter = new GradeFilter(); var grades = new TradeGrade[] { TradeGrade.APlus, TradeGrade.A, TradeGrade.B, TradeGrade.C, TradeGrade.D, TradeGrade.F }; var modes = new RiskMode[] { RiskMode.ECP, RiskMode.PCP, RiskMode.DCP, RiskMode.HR }; var sw = Stopwatch.StartNew(); for (var i = 0; i < 5000; i++) { var grade = grades[i % grades.Length]; var mode = modes[i % modes.Length]; var accepted = filter.ShouldAcceptTrade(grade, mode); var multiplier = filter.GetSizeMultiplier(grade, mode); if (!accepted) { Assert.IsTrue(multiplier >= 0.0); } } sw.Stop(); var avgMs = sw.Elapsed.TotalMilliseconds / 5000.0; Assert.IsTrue(avgMs < 1.0, string.Format("Average grade filter time {0:F4}ms exceeded 1ms", avgMs)); } [TestMethod] public void RiskModeUpdate_ShouldBeUnder2ms_Average() { var manager = new RiskModeManager(new BasicLogger("Phase4PerformanceTests")); var sw = Stopwatch.StartNew(); for (var i = 0; i < 2000; i++) { var pnl = (i % 2 == 0) ? 300.0 : -250.0; var winStreak = i % 5; var lossStreak = i % 4; manager.UpdateRiskMode(pnl, winStreak, lossStreak); var mode = manager.GetCurrentMode(); Assert.IsTrue(mode >= RiskMode.HR); } sw.Stop(); var avgMs = sw.Elapsed.TotalMilliseconds / 2000.0; Assert.IsTrue(avgMs < 2.0, string.Format("Average risk mode update time {0:F4}ms exceeded 2ms", avgMs)); } [TestMethod] public void OverallIntelligenceFlow_ShouldBeUnder15ms_Average() { var scorer = new ConfluenceScorer(new BasicLogger("Phase4PerformanceTests"), 200); var volDetector = new VolatilityRegimeDetector(new BasicLogger("Phase4PerformanceTests"), 100); var trendDetector = new TrendRegimeDetector(new BasicLogger("Phase4PerformanceTests")); var modeManager = new RiskModeManager(new BasicLogger("Phase4PerformanceTests")); var filter = new GradeFilter(); var intent = CreateIntent(OrderSide.Buy); var context = CreateContext(); var bar = CreateBar(); var factors = CreateFactors(0.84, 0.78, 0.86, 0.75, 0.80); var bars = BuildBars(12, 5000.0, 0.5); var sw = Stopwatch.StartNew(); for (var i = 0; i < 500; i++) { var score = scorer.CalculateScore(intent, context, bar, factors); var vol = volDetector.DetectRegime("ES", 1.2 + ((i % 5) * 0.15), 1.0); var trend = trendDetector.DetectTrend("ES", bars, 5000.0); var lossStreak = (vol == VolatilityRegime.Extreme) ? 3 : (i % 3); modeManager.UpdateRiskMode(i % 2 == 0 ? 350.0 : -150.0, i % 4, lossStreak); var mode = modeManager.GetCurrentMode(); var allowed = filter.ShouldAcceptTrade(score.Grade, mode); var mult = filter.GetSizeMultiplier(score.Grade, mode); Assert.IsTrue(mult >= 0.0); Assert.IsTrue(Enum.IsDefined(typeof(TrendRegime), trend)); Assert.IsTrue(allowed || !allowed); } sw.Stop(); var avgMs = sw.Elapsed.TotalMilliseconds / 500.0; Assert.IsTrue(avgMs < 15.0, string.Format("Average intelligence flow time {0:F4}ms exceeded 15ms", avgMs)); } private static StrategyIntent CreateIntent(OrderSide side) { return new StrategyIntent( "ES", side, OrderType.Market, null, 8, 16, 0.8, "Phase4 performance", new Dictionary()); } private static StrategyContext CreateContext() { return new StrategyContext( "ES", DateTime.UtcNow, new Position("ES", 0, 0, 0, 0, DateTime.UtcNow), new AccountInfo(100000, 100000, 0, 0, DateTime.UtcNow), new MarketSession(DateTime.Today.AddHours(9.5), DateTime.Today.AddHours(16), true, "RTH"), new Dictionary()); } private static BarData CreateBar() { return new BarData("ES", DateTime.UtcNow, 5000, 5004, 4998, 5003, 1200, TimeSpan.FromMinutes(1)); } private static List CreateFactors(double setup, double trend, double vol, double timing, double quality) { var factors = new List(); factors.Add(new FixedFactor(FactorType.Setup, setup)); factors.Add(new FixedFactor(FactorType.Trend, trend)); factors.Add(new FixedFactor(FactorType.Volatility, vol)); factors.Add(new FixedFactor(FactorType.Timing, timing)); factors.Add(new FixedFactor(FactorType.ExecutionQuality, quality)); return factors; } private static List BuildBars(int count, double start, double step) { var list = new List(); var t = DateTime.UtcNow.AddMinutes(-count); for (var i = 0; i < count; i++) { var close = start + (i * step); list.Add(new BarData("ES", t.AddMinutes(i), close - 1.0, close + 1.0, close - 2.0, close, 1000 + i, TimeSpan.FromMinutes(1))); } return list; } private class FixedFactor : IFactorCalculator { private readonly FactorType _type; private readonly double _score; public FixedFactor(FactorType type, double score) { _type = type; _score = score; } public FactorType Type { get { return _type; } } public ConfluenceFactor Calculate(StrategyIntent intent, StrategyContext context, BarData bar) { return new ConfluenceFactor(_type, "Fixed", _score, 1.0, "fixed", new Dictionary()); } } } }