# OrderManager Class Implementation Design

## Overview

The OrderManager class is the primary implementation of the IOrderManager interface, providing core order management functionality, integration with risk management, and support for algorithmic execution strategies.

## Class Structure

```csharp
using NT8.Core.Common.Models;
using NT8.Core.Risk;
using NT8.Core.Sizing;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace NT8.Core.Orders
{
    /// <summary>
    /// Order manager implementation with smart routing and algorithmic execution
    /// </summary>
    public class OrderManager : IOrderManager
    {
        private readonly IRiskManager _riskManager;
        private readonly IPositionSizer _positionSizer;
        private readonly ILogger<OrderManager> _logger;
        private readonly object _lock = new object();
        
        // Configuration
        private RoutingConfig _routingConfig;
        private AlgorithmParameters _algorithmParameters;
        
        // State
        private readonly Dictionary<string, OrderStatus> _orders;
        private readonly Dictionary<string, ExecutionVenue> _venues;
        private readonly RoutingMetrics _routingMetrics;
        private readonly OmsMetrics _omsMetrics;
        
        public OrderManager(
            IRiskManager riskManager,
            IPositionSizer positionSizer,
            ILogger<OrderManager> logger)
        {
            _riskManager = riskManager ?? throw new ArgumentNullException(nameof(riskManager));
            _positionSizer = positionSizer ?? throw new ArgumentNullException(nameof(positionSizer));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            
            _orders = new Dictionary<string, OrderStatus>();
            _venues = new Dictionary<string, ExecutionVenue>();
            _routingMetrics = new RoutingMetrics(new Dictionary<string, VenueMetrics>(), 0, 0.0, DateTime.UtcNow);
            _omsMetrics = new OmsMetrics(0, 0, 0.0, 0.0, 0.0, 0, DateTime.UtcNow);
            
            InitializeDefaultConfig();
            InitializeVenues();
        }
        
        private void InitializeDefaultConfig()
        {
            _routingConfig = new RoutingConfig(
                SmartRoutingEnabled: true,
                DefaultVenue: "Primary",
                VenuePreferences: new Dictionary<string, double> { ["Primary"] = 1.0, ["Secondary"] = 0.8 },
                MaxSlippagePercent: 0.5,
                MaxRoutingTime: TimeSpan.FromSeconds(30),
                RouteByCost: true,
                RouteBySpeed: true,
                RouteByReliability: true
            );
            
            _algorithmParameters = new AlgorithmParameters(
                new TwapConfig(TimeSpan.FromMinutes(15), 30, true),
                new VwapConfig(0.1, true),
                new IcebergConfig(0.1, true)
            );
        }
        
        private void InitializeVenues()
        {
            _venues.Add("Primary", new ExecutionVenue(
                "Primary", "Primary execution venue", true, 1.0, 1.0, 0.99));
                
            _venues.Add("Secondary", new ExecutionVenue(
                "Secondary", "Backup execution venue", true, 1.2, 0.9, 0.95));
        }
    }
}
```

## Core Order Management Implementation

### Order Submission

```csharp
public async Task<OrderResult> SubmitOrderAsync(OrderRequest request, StrategyContext context)
{
    if (request == null) throw new ArgumentNullException(nameof(request));
    if (context == null) throw new ArgumentNullException(nameof(context));
    
    try
    {
        _logger.LogInformation("Submitting order for {Symbol} {Side} {Quantity}", 
            request.Symbol, request.Side, request.Quantity);
        
        // 1. Validate order through risk management
        var riskDecision = await ValidateOrderAsync(request, context);
        if (!riskDecision.Allow)
        {
            _logger.LogWarning("Order rejected by risk management: {Reason}", riskDecision.RejectReason);
            return new OrderResult(false, null, riskDecision.RejectReason, null);
        }
        
        // 2. Route order based on smart routing logic
        var routingResult = await RouteOrderAsync(request, context);
        if (!routingResult.Success)
        {
            _logger.LogError("Order routing failed: {Message}", routingResult.Message);
            return new OrderResult(false, null, routingResult.Message, null);
        }
        
        // 3. Submit to selected venue (simulated)
        var orderId = Guid.NewGuid().ToString();
        var orderStatus = new OrderStatus(
            orderId, request.Symbol, request.Side, request.Type, request.Quantity, 0,
            request.LimitPrice, request.StopPrice, OrderState.Submitted, DateTime.UtcNow, null, 
            new List<OrderFill>());
            
        lock (_lock)
        {
            _orders[orderId] = orderStatus;
            UpdateOmsMetrics();
        }
        
        _logger.LogInformation("Order {OrderId} submitted to {Venue}", orderId, routingResult.SelectedVenue.Name);
        
        return new OrderResult(true, orderId, "Order submitted successfully", orderStatus);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error submitting order for {Symbol}", request.Symbol);
        return new OrderResult(false, null, $"Error submitting order: {ex.Message}", null);
    }
}
```

### Order Cancellation

```csharp
public async Task<bool> CancelOrderAsync(string orderId)
{
    if (string.IsNullOrEmpty(orderId)) throw new ArgumentException("Order ID required", nameof(orderId));
    
    try
    {
        lock (_lock)
        {
            if (!_orders.ContainsKey(orderId))
            {
                _logger.LogWarning("Cannot cancel order {OrderId} - not found", orderId);
                return false;
            }
            
            var order = _orders[orderId];
            if (order.State == OrderState.Filled || order.State == OrderState.Cancelled)
            {
                _logger.LogWarning("Cannot cancel order {OrderId} - already {State}", orderId, order.State);
                return false;
            }
            
            // Update order state to cancelled
            var updatedOrder = order with { State = OrderState.Cancelled, FilledTime = DateTime.UtcNow };
            _orders[orderId] = updatedOrder;
            
            UpdateOmsMetrics();
        }
        
        _logger.LogInformation("Order {OrderId} cancelled successfully", orderId);
        return true;
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error cancelling order {OrderId}", orderId);
        return false;
    }
}
```

## Risk Integration Implementation

```csharp
public async Task<RiskDecision> ValidateOrderAsync(OrderRequest request, StrategyContext context)
{
    if (request == null) throw new ArgumentNullException(nameof(request));
    if (context == null) throw new ArgumentNullException(nameof(context));
    
    // Convert OrderRequest to StrategyIntent for risk validation
    var intent = new StrategyIntent(
        request.Symbol,
        request.Side,
        ConvertOrderType(request.Type),
        (double?)request.LimitPrice,
        GetStopTicks(request),
        null, // TargetTicks
        1.0, // Confidence
        "OMS Order Submission",
        new Dictionary<string, object>()
    );
    
    // Create a mock risk config for validation
    var riskConfig = new RiskConfig(1000, 200, 10, true);
    
    return _riskManager.ValidateOrder(intent, context, riskConfig);
}

private OrderType ConvertOrderType(NT8.Core.Orders.OrderType orderType)
{
    return orderType switch
    {
        NT8.Core.Orders.OrderType.Market => OrderType.Market,
        NT8.Core.Orders.OrderType.Limit => OrderType.Limit,
        NT8.Core.Orders.OrderType.StopMarket => OrderType.StopMarket,
        NT8.Core.Orders.OrderType.StopLimit => OrderType.StopLimit,
        _ => OrderType.Market
    };
}

private int GetStopTicks(OrderRequest request)
{
    // Simplified stop ticks calculation
    return 10;
}
```

## Smart Order Routing Implementation

```csharp
public async Task<RoutingResult> RouteOrderAsync(OrderRequest request, StrategyContext context)
{
    if (request == null) throw new ArgumentNullException(nameof(request));
    if (context == null) throw new ArgumentNullException(nameof(context));
    
    if (!_routingConfig.SmartRoutingEnabled)
    {
        var defaultVenue = _venues[_routingConfig.DefaultVenue];
        return new RoutingResult(true, null, defaultVenue, "Routing disabled, using default venue", 
            new Dictionary<string, object> { ["venue"] = defaultVenue.Name });
    }
    
    // Select best venue based on configuration
    var selectedVenue = SelectBestVenue(request, context);
    
    // Update routing metrics
    UpdateRoutingMetrics(selectedVenue);
    
    return new RoutingResult(true, null, selectedVenue, "Order routed successfully",
        new Dictionary<string, object> 
        { 
            ["venue"] = selectedVenue.Name, 
            ["cost_factor"] = selectedVenue.CostFactor,
            ["speed_factor"] = selectedVenue.SpeedFactor
        });
}

private ExecutionVenue SelectBestVenue(OrderRequest request, StrategyContext context)
{
    ExecutionVenue bestVenue = null;
    double bestScore = double.MinValue;
    
    foreach (var venue in _venues.Values)
    {
        if (!venue.IsActive) continue;
        
        double score = 0;
        
        // Factor in venue preferences
        if (_routingConfig.VenuePreferences.ContainsKey(venue.Name))
        {
            score += _routingConfig.VenuePreferences[venue.Name] * 100;
        }
        
        // Factor in cost if enabled
        if (_routingConfig.RouteByCost)
        {
            score -= venue.CostFactor * 50; // Lower cost is better
        }
        
        // Factor in speed if enabled
        if (_routingConfig.RouteBySpeed)
        {
            score += venue.SpeedFactor * 30; // Higher speed is better
        }
        
        // Factor in reliability
        if (_routingConfig.RouteByReliability)
        {
            score += venue.ReliabilityFactor * 20; // Higher reliability is better
        }
        
        if (score > bestScore)
        {
            bestScore = score;
            bestVenue = venue;
        }
    
    return bestVenue ?? _venues[_routingConfig.DefaultVenue];
}

private void UpdateRoutingMetrics(ExecutionVenue venue)
{
    lock (_lock)
    {
        var venueMetrics = _routingMetrics.VenuePerformance.ContainsKey(venue.Name) ? 
            _routingMetrics.VenuePerformance[venue.Name] : 
            new VenueMetrics(venue.Name, 0, 0.0, 0.0, 0.0, 0);
            
        var updatedMetrics = venueMetrics with
        {
            OrdersRouted = venueMetrics.OrdersRouted + 1
        };
        
        _routingMetrics.VenuePerformance[venue.Name] = updatedMetrics;
        _routingMetrics.TotalRoutedOrders++;
        _routingMetrics.LastUpdated = DateTime.UtcNow;
    }
}
```

## Algorithmic Execution Support

### TWAP Algorithm Integration

```csharp
public async Task<OrderResult> ExecuteTwapAsync(TwapParameters parameters, StrategyContext context)
{
    if (parameters == null) throw new ArgumentNullException(nameof(parameters));
    if (context == null) throw new ArgumentNullException(nameof(context));
    
    _logger.LogInformation("Executing TWAP order for {Symbol} {Side} {Quantity} over {Duration}", 
        parameters.Symbol, parameters.Side, parameters.TotalQuantity, parameters.Duration);
    
    // Create a parent order for tracking
    var parentOrderId = Guid.NewGuid().ToString();
    
    // Calculate slice parameters
    var sliceCount = (int)(parameters.Duration.TotalSeconds / parameters.IntervalSeconds);
    var sliceQuantity = parameters.TotalQuantity / sliceCount;
    
    // Execute slices
    for (int i = 0; i < sliceCount; i++)
    {
        // Create slice order
        var sliceRequest = new OrderRequest(
            parameters.Symbol,
            parameters.Side,
            OrderType.Market, // Simplified to market orders
            sliceQuantity,
            parameters.LimitPrice,
            null, // StopPrice
            TimeInForce.Day,
            null, // No algorithm for slices
            new Dictionary<string, object>()
        );
        
        // Submit slice order
        var result = await SubmitOrderAsync(sliceRequest, context);
        
        if (!result.Success)
        {
            _logger.LogWarning("TWAP slice {Slice}/{Total} failed: {Message}", 
                i + 1, sliceCount, result.Message);
        }
        else
        {
            _logger.LogInformation("TWAP slice {Slice}/{Total} submitted: {OrderId}", 
                i + 1, sliceCount, result.OrderId);
        }
        
        // Wait for next interval (except for last slice)
        if (i < sliceCount - 1)
        {
            await Task.Delay(TimeSpan.FromSeconds(parameters.IntervalSeconds));
        }
    }
    
    return new OrderResult(true, parentOrderId, "TWAP execution completed", null);
}
```

### VWAP Algorithm Integration

```csharp
public async Task<OrderResult> ExecuteVwapAsync(VwapParameters parameters, StrategyContext context)
{
    if (parameters == null) throw new ArgumentNullException(nameof(parameters));
    if (context == null) throw new ArgumentNullException(nameof(context));
    
    _logger.LogInformation("Executing VWAP order for {Symbol} {Side} {Quantity} from {Start} to {End}", 
        parameters.Symbol, parameters.Side, parameters.TotalQuantity, parameters.StartTime, parameters.EndTime);
    
    // Create a parent order for tracking
    var parentOrderId = Guid.NewGuid().ToString();
    
    // Simplified VWAP implementation - in a real system, this would:
    // 1. Monitor market volume throughout the execution period
    // 2. Calculate participation rate based on target participation
    // 3. Execute orders in proportion to volume
    
    // For now, we'll execute the order as a single market order
    var request = new OrderRequest(
        parameters.Symbol,
        parameters.Side,
        OrderType.Market,
        parameters.TotalQuantity,
        parameters.LimitPrice,
        null, // StopPrice
        TimeInForce.Day,
        null, // No algorithm for this simplified version
        new Dictionary<string, object>()
    );
    
    var result = await SubmitOrderAsync(request, context);
    
    return new OrderResult(result.Success, parentOrderId, 
        result.Success ? "VWAP execution completed" : $"VWAP execution failed: {result.Message}", 
        result.Status);
}
```

### Iceberg Algorithm Integration

```csharp
public async Task<OrderResult> ExecuteIcebergAsync(IcebergParameters parameters, StrategyContext context)
{
    if (parameters == null) throw new ArgumentNullException(nameof(parameters));
    if (context == null) throw new ArgumentNullException(nameof(context));
    
    _logger.LogInformation("Executing Iceberg order for {Symbol} {Side} {TotalQuantity} (visible: {VisibleQuantity})", 
        parameters.Symbol, parameters.Side, parameters.TotalQuantity, parameters.VisibleQuantity);
    
    // Create a parent order for tracking
    var parentOrderId = Guid.NewGuid().ToString();
    
    var remainingQuantity = parameters.TotalQuantity;
    
    while (remainingQuantity > 0)
    {
        // Determine visible quantity for this slice
        var visibleQuantity = Math.Min(parameters.VisibleQuantity, remainingQuantity);
        
        // Create slice order
        var sliceRequest = new OrderRequest(
            parameters.Symbol,
            parameters.Side,
            parameters.LimitPrice.HasValue ? OrderType.Limit : OrderType.Market,
            visibleQuantity,
            parameters.LimitPrice,
            null, // StopPrice
            TimeInForce.Day,
            null, // No algorithm for slices
            new Dictionary<string, object>()
        );
        
        // Submit slice order
        var result = await SubmitOrderAsync(sliceRequest, context);
        
        if (!result.Success)
        {
            _logger.LogWarning("Iceberg slice failed with {Remaining} qty remaining: {Message}", 
                remainingQuantity, result.Message);
            break;
        }
        
        // Update remaining quantity
        remainingQuantity -= visibleQuantity;
        
        _logger.LogInformation("Iceberg slice submitted, {Remaining} qty remaining", remainingQuantity);
        
        // In a real implementation, we would wait for the order to fill
        // before submitting the next slice. For this design, we'll add a delay.
        if (remainingQuantity > 0)
        {
            await Task.Delay(TimeSpan.FromSeconds(5)); // Simulate time between slices
        }
    
    return new OrderResult(true, parentOrderId, "Iceberg execution completed", null);
}
```

## Configuration Management

```csharp
public void UpdateRoutingConfig(RoutingConfig config)
{
    if (config == null) throw new ArgumentNullException(nameof(config));
    
    lock (_lock)
    {
        _routingConfig = config;
    }
    
    _logger.LogInformation("Routing configuration updated");
}

public RoutingConfig GetRoutingConfig()
{
    lock (_lock)
    {
        return _routingConfig;
    }
}

public void UpdateAlgorithmParameters(AlgorithmParameters parameters)
{
    if (parameters == null) throw new ArgumentNullException(nameof(parameters));
    
    lock (_lock)
    {
        _algorithmParameters = parameters;
    }
    
    _logger.LogInformation("Algorithm parameters updated");
}

public AlgorithmParameters GetAlgorithmParameters()
{
    lock (_lock)
    {
        return _algorithmParameters;
    }
}
```

## Metrics and Monitoring

```csharp
private void UpdateOmsMetrics()
{
    lock (_lock)
    {
        var activeOrders = 0;
        var filledOrders = 0;
        var failedOrders = 0;
        var totalQuantity = 0;
        
        foreach (var order in _orders.Values)
        {
            switch (order.State)
            {
                case OrderState.Submitted:
                case OrderState.Accepted:
                case OrderState.PartiallyFilled:
                    activeOrders++;
                    break;
                case OrderState.Filled:
                    filledOrders++;
                    break;
                case OrderState.Rejected:
                case OrderState.Expired:
                case OrderState.Cancelled:
                    failedOrders++;
                    break;
            }
            
            totalQuantity += order.Quantity;
        }
        
        var totalOrders = _orders.Count;
        var fillRate = totalOrders > 0 ? (double)filledOrders / totalOrders : 0.0;
        
        _omsMetrics = _omsMetrics with
        {
            TotalOrders = totalOrders,
            ActiveOrders = activeOrders,
            FailedOrders = failedOrders,
            FillRate = fillRate,
            TotalValueTraded = totalQuantity, // Simplified
            LastUpdated = DateTime.UtcNow
        };
    }
}

public OmsMetrics GetMetrics()
{
    lock (_lock)
    {
        return _omsMetrics;
    }
}

public RoutingMetrics GetRoutingMetrics()
{
    lock (_lock)
    {
        return _routingMetrics;
    }
}

public bool IsHealthy()
{
    // Simple health check - in a real implementation, this would check:
    // - Connection to execution venues
    // - Risk management system availability
    // - Position sizing system availability
    // - Internal state consistency
    
    return true;
}
```

## Order Status Management

```csharp
public async Task<OrderStatus> GetOrderStatusAsync(string orderId)
{
    if (string.IsNullOrEmpty(orderId)) throw new ArgumentException("Order ID required", nameof(orderId));
    
    lock (_lock)
    {
        return _orders.ContainsKey(orderId) ? _orders[orderId] : null;
    }
}

public async Task<List<OrderStatus>> GetOrdersBySymbolAsync(string symbol)
{
    if (string.IsNullOrEmpty(symbol)) throw new ArgumentException("Symbol required", nameof(symbol));
    
    var result = new List<OrderStatus>();
    
    lock (_lock)
    {
        foreach (var order in _orders.Values)
        {
            if (order.Symbol.Equals(symbol, StringComparison.OrdinalIgnoreCase))
            {
                result.Add(order);
            }
        }
    }
    
    return result;
}

public async Task<List<OrderStatus>> GetActiveOrdersAsync()
{
    var result = new List<OrderStatus>();
    
    lock (_lock)
    {
        foreach (var order in _orders.Values)
        {
            if (order.State == OrderState.Submitted || 
                order.State == OrderState.Accepted || 
                order.State == OrderState.PartiallyFilled)
            {
                result.Add(order);
            }
        }
    }
    
    return result;
}
```

## Error Handling and Validation

The OrderManager implements comprehensive error handling:

1. **Input Validation**: All public methods validate their parameters
2. **Exception Handling**: Try-catch blocks around critical operations
3. **Logging**: Detailed logging of all operations and errors
4. **Graceful Degradation**: When possible, the system continues operating even when some components fail

## Thread Safety

The OrderManager uses a lock-based approach to ensure thread safety:

1. **State Protection**: All shared state is protected by a single lock
2. **Atomic Operations**: Complex state updates are performed atomically
3. **Immutable Data**: Where possible, immutable data structures are used

## Integration Points

### Risk Management
- All orders pass through the IRiskManager.ValidateOrder method
- Risk decisions are respected before order submission

### Position Sizing
- Future enhancement could integrate with IPositionSizer for dynamic quantity adjustments

### Execution Venues
- Orders are routed to configured execution venues
- Routing decisions are based on configurable criteria

## Testing Considerations

The OrderManager is designed to be testable:

1. **Dependency Injection**: All dependencies are injected through the constructor
2. **Interface-Based**: Depends on interfaces rather than concrete implementations
3. **State Access**: Provides methods to access internal state for verification
4. **Configuration**: All behavior can be controlled through configuration

## Performance Considerations

1. **Lock Contention**: The single lock could become a bottleneck under high load
2. **Memory Usage**: Order state is maintained in memory
3. **Latency**: Order routing adds minimal latency
4. **Scalability**: Design supports horizontal scaling through instance isolation
