using System; using System.Collections.Generic; using NT8.Core.Common.Models; using NT8.Core.Risk; using NT8.Core.Sizing; namespace NT8.Adapters.NinjaTrader { /// /// Order adapter for executing trades through NT8 /// public class NT8OrderAdapter { private readonly object _lock = new object(); private readonly INT8ExecutionBridge _bridge; private IRiskManager _riskManager; private IPositionSizer _positionSizer; private readonly List _executionHistory; /// /// Constructor for NT8OrderAdapter. /// public NT8OrderAdapter(INT8ExecutionBridge bridge) { if (bridge == null) throw new ArgumentNullException("bridge"); _bridge = bridge; _executionHistory = new List(); } /// /// Initialize the order adapter with required components /// public void Initialize(IRiskManager riskManager, IPositionSizer positionSizer) { if (riskManager == null) { throw new ArgumentNullException("riskManager"); } if (positionSizer == null) { throw new ArgumentNullException("positionSizer"); } try { _riskManager = riskManager; _positionSizer = positionSizer; } catch (Exception) { throw; } } /// /// Execute strategy intent through NT8 order management /// public void ExecuteIntent(StrategyIntent intent, StrategyContext context, StrategyConfig config) { if (intent == null) { throw new ArgumentNullException("intent"); } if (context == null) { throw new ArgumentNullException("context"); } if (config == null) { throw new ArgumentNullException("config"); } if (_riskManager == null || _positionSizer == null) { throw new InvalidOperationException("Adapter not initialized. Call Initialize() first."); } try { // Validate the intent through risk management var riskDecision = _riskManager.ValidateOrder(intent, context, config.RiskSettings); if (!riskDecision.Allow) { // Risk rejected the order flow. return; } // Calculate position size var sizingResult = _positionSizer.CalculateSize(intent, context, config.SizingSettings); if (sizingResult.Contracts <= 0) { // No tradable size produced. return; } // In a real implementation, this would call NT8's order execution methods. ExecuteInNT8(intent, sizingResult); } catch (Exception) { throw; } } /// /// Gets a snapshot of executions submitted through this adapter. /// /// Execution history snapshot. public IList GetExecutionHistory() { try { lock (_lock) { return new List(_executionHistory); } } catch (Exception) { throw; } } /// /// Execute the order in NT8 (placeholder implementation) /// private void ExecuteInNT8(StrategyIntent intent, SizingResult sizing) { if (intent == null) throw new ArgumentNullException("intent"); if (sizing == null) throw new ArgumentNullException("sizing"); var signalName = string.Format("SDK_{0}_{1}", intent.Symbol, intent.Side); if (intent.Side == OrderSide.Buy) { _bridge.EnterLongManaged( sizing.Contracts, signalName, intent.StopTicks, intent.TargetTicks.HasValue ? intent.TargetTicks.Value : 0, 0.25); } else if (intent.Side == OrderSide.Sell) { _bridge.EnterShortManaged( sizing.Contracts, signalName, intent.StopTicks, intent.TargetTicks.HasValue ? intent.TargetTicks.Value : 0, 0.25); } lock (_lock) { _executionHistory.Add(new NT8OrderExecutionRecord( intent.Symbol, intent.Side, intent.EntryType, sizing.Contracts, intent.StopTicks, intent.TargetTicks, DateTime.UtcNow)); } } /// /// Handle order updates from NT8 /// public void OnOrderUpdate(string orderId, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, string orderState, DateTime time, string errorCode, string nativeError) { if (string.IsNullOrWhiteSpace(orderId)) { throw new ArgumentException("orderId"); } try { // Pass order updates to risk manager for tracking. if (_riskManager != null) { // In a real implementation, convert NT8 order data to SDK models. } } catch (Exception) { throw; } } /// /// Handle execution updates from NT8 /// public void OnExecutionUpdate(string executionId, string orderId, double price, int quantity, string marketPosition, DateTime time) { if (string.IsNullOrWhiteSpace(executionId)) { throw new ArgumentException("executionId"); } if (string.IsNullOrWhiteSpace(orderId)) { throw new ArgumentException("orderId"); } try { // Pass execution updates to risk manager for P&L tracking. if (_riskManager != null) { // In a real implementation, convert NT8 execution data to SDK models. } } catch (Exception) { throw; } } } /// /// Execution record captured by NT8OrderAdapter for diagnostics and tests. /// public class NT8OrderExecutionRecord { /// /// Trading symbol. /// public string Symbol { get; set; } /// /// Order side. /// public OrderSide Side { get; set; } /// /// Entry order type. /// public OrderType EntryType { get; set; } /// /// Executed contract quantity. /// public int Contracts { get; set; } /// /// Stop-loss distance in ticks. /// public int StopTicks { get; set; } /// /// Profit target distance in ticks. /// public int? TargetTicks { get; set; } /// /// Timestamp when the execution was recorded. /// public DateTime Timestamp { get; set; } /// /// Constructor for NT8OrderExecutionRecord. /// public NT8OrderExecutionRecord(string symbol, OrderSide side, OrderType entryType, int contracts, int stopTicks, int? targetTicks, DateTime timestamp) { Symbol = symbol; Side = side; EntryType = entryType; Contracts = contracts; StopTicks = stopTicks; TargetTicks = targetTicks; Timestamp = timestamp; } } }