using System; using System.Collections.Generic; using Microsoft.VisualStudio.TestTools.UnitTesting; using NT8.Core.Common.Models; using NT8.Core.Intelligence; using NT8.Core.Logging; using NT8.Core.Sizing; namespace NT8.Integration.Tests { /// /// Integration tests for Phase 4 intelligence flow. /// [TestClass] public class Phase4IntegrationTests { [TestMethod] public void FullFlow_ConfluenceToGradeFilter_AllowsTradeInPCP() { var logger = new BasicLogger("Phase4IntegrationTests"); var scorer = new ConfluenceScorer(logger, 100); var filter = new GradeFilter(); var modeManager = new RiskModeManager(logger); var intent = CreateIntent(OrderSide.Buy); var context = CreateContext(); var bar = CreateBar(); var factors = CreateStrongFactors(); var score = scorer.CalculateScore(intent, context, bar, factors); var mode = modeManager.GetCurrentMode(); var allowed = filter.ShouldAcceptTrade(score.Grade, mode); Assert.IsTrue(allowed); Assert.IsTrue(score.WeightedScore >= 0.70); } [TestMethod] public void FullFlow_LowConfluence_RejectedInPCP() { var logger = new BasicLogger("Phase4IntegrationTests"); var scorer = new ConfluenceScorer(logger, 100); var filter = new GradeFilter(); var intent = CreateIntent(OrderSide.Buy); var context = CreateContext(); var bar = CreateBar(); var factors = CreateWeakFactors(); var score = scorer.CalculateScore(intent, context, bar, factors); var allowed = filter.ShouldAcceptTrade(score.Grade, RiskMode.PCP); Assert.IsFalse(allowed); Assert.AreEqual(TradeGrade.F, score.Grade); } [TestMethod] public void FullFlow_ModeTransitionToHR_BlocksTrades() { var logger = new BasicLogger("Phase4IntegrationTests"); var modeManager = new RiskModeManager(logger); var filter = new GradeFilter(); modeManager.UpdateRiskMode(-500.0, 0, 3); var mode = modeManager.GetCurrentMode(); var allowed = filter.ShouldAcceptTrade(TradeGrade.APlus, mode); Assert.AreEqual(RiskMode.HR, mode); Assert.IsFalse(allowed); } [TestMethod] public void FullFlow_GradeBasedSizer_AppliesGradeAndModeMultipliers() { var logger = new BasicLogger("Phase4IntegrationTests"); var filter = new GradeFilter(); var gradeSizer = new GradeBasedSizer(logger, filter); var baseSizer = new StubSizer(4, 400.0); var intent = CreateIntent(OrderSide.Buy); var context = CreateContext(); var confluence = CreateScore(TradeGrade.A, 0.85); var config = new SizingConfig(SizingMethod.FixedDollarRisk, 1, 20, 500.0, new Dictionary()); var modeConfig = new RiskModeConfig(RiskMode.ECP, 1.5, TradeGrade.B, 1500.0, 4, true, new Dictionary()); var result = gradeSizer.CalculateGradeBasedSize( intent, context, confluence, RiskMode.ECP, config, baseSizer, modeConfig); // 4 * 1.25 * 1.5 = 7.5 => 7 Assert.AreEqual(7, result.Contracts); Assert.IsTrue(result.Calculations.ContainsKey("combined_multiplier")); } [TestMethod] public void FullFlow_RegimeManager_ShouldAdjustForExtremeVolatility() { var logger = new BasicLogger("Phase4IntegrationTests"); var vol = new VolatilityRegimeDetector(logger, 20); var trend = new TrendRegimeDetector(logger); var regimeManager = new RegimeManager(logger, vol, trend, 50, 50); var bars = BuildUptrendBars(6, 5000.0, 1.0); for (var i = 0; i < bars.Count; i++) { regimeManager.UpdateRegime("ES", bars[i], 5000.0, 2.4, 1.0); } var shouldAdjust = regimeManager.ShouldAdjustStrategy("ES", CreateIntent(OrderSide.Buy)); Assert.IsTrue(shouldAdjust); } [TestMethod] public void FullFlow_ConfluenceStatsAndModeState_AreAvailable() { var logger = new BasicLogger("Phase4IntegrationTests"); var scorer = new ConfluenceScorer(logger, 10); var modeManager = new RiskModeManager(logger); var score = scorer.CalculateScore(CreateIntent(OrderSide.Buy), CreateContext(), CreateBar(), CreateStrongFactors()); var stats = scorer.GetHistoricalStats(); var state = modeManager.GetState(); Assert.IsNotNull(score); Assert.IsNotNull(stats); Assert.IsNotNull(state); Assert.IsTrue(stats.TotalCalculations >= 1); } private static StrategyIntent CreateIntent(OrderSide side) { return new StrategyIntent( "ES", side, OrderType.Market, null, 8, 16, 0.8, "Phase4 integration", 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 ConfluenceScore CreateScore(TradeGrade grade, double weighted) { var factors = new List(); factors.Add(new ConfluenceFactor(FactorType.Setup, "Setup", weighted, 1.0, "test", new Dictionary())); return new ConfluenceScore(weighted, weighted, grade, factors, DateTime.UtcNow, new Dictionary()); } private static List CreateStrongFactors() { var factors = new List(); factors.Add(new FixedFactor(FactorType.Setup, 0.90)); factors.Add(new FixedFactor(FactorType.Trend, 0.85)); factors.Add(new FixedFactor(FactorType.Volatility, 0.80)); return factors; } private static List CreateWeakFactors() { var factors = new List(); factors.Add(new FixedFactor(FactorType.Setup, 0.20)); factors.Add(new FixedFactor(FactorType.Trend, 0.30)); factors.Add(new FixedFactor(FactorType.Volatility, 0.25)); return factors; } private static List BuildUptrendBars(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()); } } private class StubSizer : IPositionSizer { private readonly int _contracts; private readonly double _risk; public StubSizer(int contracts, double risk) { _contracts = contracts; _risk = risk; } public SizingResult CalculateSize(StrategyIntent intent, StrategyContext context, SizingConfig config) { return new SizingResult(_contracts, _risk, SizingMethod.FixedDollarRisk, new Dictionary()); } public SizingMetadata GetMetadata() { return new SizingMetadata("Stub", "Stub", new List()); } } } }