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;
}
}
}