using Microsoft.VisualStudio.TestTools.UnitTesting; using NT8.Adapters.NinjaTrader; using NT8.Core.Common.Models; using System; using System.Collections.Generic; using System.Diagnostics; namespace NT8.Integration.Tests { /// /// Integration tests for NT8 data conversion layer. /// [TestClass] public class NT8DataConverterIntegrationTests { [TestMethod] public void ConvertBar_ValidInput_ReturnsExpectedBarData() { // Arrange var time = new DateTime(2026, 2, 15, 14, 30, 0, DateTimeKind.Utc); // Act var result = NT8DataConverter.ConvertBar("ES 03-26", time, 6000.25, 6010.50, 5998.75, 6005.00, 12000, 5); // Assert Assert.AreEqual("ES 03-26", result.Symbol); Assert.AreEqual(time, result.Time); Assert.AreEqual(6000.25, result.Open); Assert.AreEqual(6010.50, result.High); Assert.AreEqual(5998.75, result.Low); Assert.AreEqual(6005.00, result.Close); Assert.AreEqual(12000, result.Volume); Assert.AreEqual(TimeSpan.FromMinutes(5), result.BarSize); } [TestMethod] public void ConvertBar_InvalidBarSize_ThrowsArgumentException() { // Act & Assert Assert.ThrowsException(() => NT8DataConverter.ConvertBar("NQ 03-26", DateTime.UtcNow, 1, 2, 0.5, 1.5, 10, 0)); } [TestMethod] public void ConvertBar_EmptySymbol_ThrowsArgumentException() { // Act & Assert Assert.ThrowsException(() => NT8DataConverter.ConvertBar("", DateTime.UtcNow, 1, 2, 0.5, 1.5, 10, 5)); } [TestMethod] public void ConvertAccount_ValidInput_ReturnsExpectedAccountInfo() { // Arrange var lastUpdate = new DateTime(2026, 2, 15, 14, 45, 0, DateTimeKind.Utc); // Act var account = NT8DataConverter.ConvertAccount(100000.0, 95000.0, 1250.5, 5000.0, lastUpdate); // Assert Assert.AreEqual(100000.0, account.Equity); Assert.AreEqual(95000.0, account.BuyingPower); Assert.AreEqual(1250.5, account.DailyPnL); Assert.AreEqual(5000.0, account.MaxDrawdown); Assert.AreEqual(lastUpdate, account.LastUpdate); } [TestMethod] public void ConvertPosition_ValidInput_ReturnsExpectedPosition() { // Arrange var lastUpdate = new DateTime(2026, 2, 15, 15, 0, 0, DateTimeKind.Utc); // Act var position = NT8DataConverter.ConvertPosition("GC 04-26", 3, 2105.2, 180.0, -20.0, lastUpdate); // Assert Assert.AreEqual("GC 04-26", position.Symbol); Assert.AreEqual(3, position.Quantity); Assert.AreEqual(2105.2, position.AveragePrice); Assert.AreEqual(180.0, position.UnrealizedPnL); Assert.AreEqual(-20.0, position.RealizedPnL); Assert.AreEqual(lastUpdate, position.LastUpdate); } [TestMethod] public void ConvertPosition_EmptySymbol_ThrowsArgumentException() { // Act & Assert Assert.ThrowsException(() => NT8DataConverter.ConvertPosition("", 1, 100.0, 0.0, 0.0, DateTime.UtcNow)); } [TestMethod] public void ConvertSession_EndBeforeStart_ThrowsArgumentException() { // Arrange var start = new DateTime(2026, 2, 15, 16, 0, 0, DateTimeKind.Utc); var end = new DateTime(2026, 2, 15, 9, 30, 0, DateTimeKind.Utc); // Act & Assert Assert.ThrowsException(() => NT8DataConverter.ConvertSession(start, end, true, "RTH")); } [TestMethod] public void ConvertContext_NullCustomData_CreatesEmptyDictionary() { // Arrange var position = new Position("MES 03-26", 1, 5000.0, 15.0, 10.0, DateTime.UtcNow); var account = new AccountInfo(50000.0, 50000.0, 200.0, 1000.0, DateTime.UtcNow); var session = new MarketSession(DateTime.Today.AddHours(9.5), DateTime.Today.AddHours(16), true, "RTH"); // Act var context = NT8DataConverter.ConvertContext("MES 03-26", DateTime.UtcNow, position, account, session, null); // Assert Assert.IsNotNull(context.CustomData); Assert.AreEqual(0, context.CustomData.Count); } [TestMethod] public void ConvertContext_WithCustomData_CopiesDictionaryValues() { // Arrange var position = new Position("CL 04-26", 2, 75.25, 50.0, -20.0, DateTime.UtcNow); var account = new AccountInfo(75000.0, 74000.0, -150.0, 1200.0, DateTime.UtcNow); var session = new MarketSession(DateTime.Today.AddHours(18), DateTime.Today.AddDays(1).AddHours(17), false, "ETH"); var input = new Dictionary(); input.Add("spread", 1.25); input.Add("source", "sim"); // Act var context = NT8DataConverter.ConvertContext("CL 04-26", DateTime.UtcNow, position, account, session, input); // Assert Assert.AreEqual("CL 04-26", context.Symbol); Assert.AreEqual(2, context.CustomData.Count); Assert.AreEqual(1.25, (double)context.CustomData["spread"]); Assert.AreEqual("sim", (string)context.CustomData["source"]); // Validate copied dictionary (not same reference) input.Add("newKey", 99); Assert.AreEqual(2, context.CustomData.Count); } [TestMethod] public void ConvertContext_NullPosition_ThrowsArgumentNullException() { // Arrange var account = new AccountInfo(50000.0, 50000.0, 200.0, 1000.0, DateTime.UtcNow); var session = new MarketSession(DateTime.Today.AddHours(9.5), DateTime.Today.AddHours(16), true, "RTH"); // Act & Assert Assert.ThrowsException(() => NT8DataConverter.ConvertContext("MES 03-26", DateTime.UtcNow, null, account, session, null)); } [TestMethod] public void ConvertContext_NullAccount_ThrowsArgumentNullException() { // Arrange var position = new Position("MES 03-26", 1, 5000.0, 15.0, 10.0, DateTime.UtcNow); var session = new MarketSession(DateTime.Today.AddHours(9.5), DateTime.Today.AddHours(16), true, "RTH"); // Act & Assert Assert.ThrowsException(() => NT8DataConverter.ConvertContext("MES 03-26", DateTime.UtcNow, position, null, session, null)); } [TestMethod] public void ConvertContext_NullSession_ThrowsArgumentNullException() { // Arrange var position = new Position("MES 03-26", 1, 5000.0, 15.0, 10.0, DateTime.UtcNow); var account = new AccountInfo(50000.0, 50000.0, 200.0, 1000.0, DateTime.UtcNow); // Act & Assert Assert.ThrowsException(() => NT8DataConverter.ConvertContext("MES 03-26", DateTime.UtcNow, position, account, null, null)); } [TestMethod] public void ConvertSession_EmptyName_ThrowsArgumentException() { // Arrange var start = new DateTime(2026, 2, 15, 9, 30, 0, DateTimeKind.Utc); var end = new DateTime(2026, 2, 15, 16, 0, 0, DateTimeKind.Utc); // Act & Assert Assert.ThrowsException(() => NT8DataConverter.ConvertSession(start, end, true, "")); } [TestMethod] public void ConvertBar_Performance_AverageUnderOneMillisecond() { // Arrange var iterations = 5000; var startedAt = DateTime.UtcNow; // Act var stopwatch = Stopwatch.StartNew(); for (var i = 0; i < iterations; i++) { NT8DataConverter.ConvertBar( "ES 03-26", startedAt.AddMinutes(i), 6000.25, 6010.50, 5998.75, 6005.00, 12000, 5); } stopwatch.Stop(); // Assert var averageMs = stopwatch.Elapsed.TotalMilliseconds / iterations; Assert.IsTrue(averageMs < 1.0, string.Format("Expected average conversion under 1.0 ms but was {0:F6} ms", averageMs)); } } }