Files
nt8-sdk/docs/architecture/iceberg_algorithm_implementation.md
Billy Valentine 92f3732b3d
Some checks failed
Build and Test / build (push) Has been cancelled
Phase 0 completion: NT8 SDK core framework with risk management and position sizing
2025-09-09 17:06:37 -04:00

50 KiB

Iceberg Order Algorithm Implementation Design

Overview

This document details the implementation of the Iceberg order algorithm in the Order Management System (OMS), which executes large orders by only displaying a small portion of the total order size at any given time to minimize market impact and reduce information leakage.

Iceberg Algorithm Fundamentals

Algorithm Description

The Iceberg algorithm hides large order sizes by only displaying a small, visible portion of the total order quantity. As each displayed portion is filled, a new portion is revealed until the entire order is executed. This approach minimizes market impact by preventing other market participants from seeing the true size of the order.

Key Characteristics

  1. Size Concealment: Hides large order sizes from the market
  2. Sequential Execution: Executes orders in small, visible portions
  3. Market Impact Reduction: Reduces information leakage and adverse price movements
  4. Continuous Replenishment: Automatically replenishes visible quantity as portions are filled

Iceberg Parameters

Core Parameters

/// <summary>
/// Parameters for Iceberg algorithm execution
/// </summary>
public record IcebergParameters
{
    /// <summary>
    /// Trading symbol
    /// </summary>
    public string Symbol { get; set; }
    
    /// <summary>
    /// Order side (Buy/Sell)
    /// </summary>
    public OrderSide Side { get; set; }
    
    /// <summary>
    /// Total quantity to execute
    /// </summary>
    public int TotalQuantity { get; set; }
    
    /// <summary>
    /// Visible quantity (displayed to market)
    /// </summary>
    public int VisibleQuantity { get; set; }
    
    /// <summary>
    /// Optional limit price for limit orders
    /// </summary>
    public decimal? LimitPrice { get; set; }
    
    /// <summary>
    /// Time in force for orders
    /// </summary>
    public TimeInForce TimeInForce { get; set; } = TimeInForce.Day;
    
    /// <summary>
    /// Whether to automatically replenish visible quantity
    /// </summary>
    public bool AutoReplenish { get; set; } = true;
    
    /// <summary>
    /// Minimum visible quantity (to avoid very small orders)
    /// </summary>
    public int MinVisibleQuantity { get; set; } = 1;
    
    /// <summary>
    /// Maximum visible quantity (to control individual order impact)
    /// </summary>
    public int? MaxVisibleQuantity { get; set; }
    
    /// <summary>
    /// Delay between order placements (in milliseconds)
    /// </summary>
    public int PlacementDelayMs { get; set; } = 1000;
    
    /// <summary>
    /// Whether to cancel remaining visible quantity at end
    /// </summary>
    public bool CancelAtEnd { get; set; } = true;
    
    /// <summary>
    /// Aggressiveness factor (0.0 to 1.0) - higher values place orders more aggressively
    /// </summary>
    public double Aggressiveness { get; set; } = 0.5;
    
    /// <summary>
    /// Whether to adjust visible quantity based on market conditions
    /// </summary>
    public bool AdaptiveVisibility { get; set; } = false;
    
    /// <summary>
    /// Custom metadata for the algorithm
    /// </summary>
    public Dictionary<string, object> Metadata { get; set; } = new Dictionary<string, object>();
}

Iceberg Configuration

/// <summary>
/// Configuration for Iceberg algorithm behavior
/// </summary>
public record IcebergConfig
{
    /// <summary>
    /// Default visible quantity as percentage of total quantity
    /// </summary>
    public double DefaultVisiblePercentage { get; set; } = 0.1; // 10%
    
    /// <summary>
    /// Default placement delay (in milliseconds)
    /// </summary>
    public int DefaultPlacementDelayMs { get; set; } = 1000;
    
    /// <summary>
    /// Whether to enable adaptive visibility based on market conditions
    /// </summary>
    public bool EnableAdaptiveVisibility { get; set; } = false;
    
    /// <summary>
    /// Maximum visible quantity as percentage of total quantity
    /// </summary>
    public double MaxVisiblePercentage { get; set; } = 0.25; // 25%
    
    /// <summary>
    /// Minimum visible quantity as percentage of total quantity
    /// </summary>
    public double MinVisiblePercentage { get; set; } = 0.01; // 1%
    
    /// <summary>
    /// Whether to prioritize execution speed over impact reduction
    /// </summary>
    public bool PrioritizeSpeed { get; set; } = false;
    
    /// <summary>
    /// Retry count for failed order placements
    /// </summary>
    public int MaxRetries { get; set; } = 3;
    
    /// <summary>
    /// Delay between retries (in milliseconds)
    /// </summary>
    public int RetryDelayMs { get; set; } = 5000;
    
    /// <summary>
    /// Whether to use market depth analysis for visibility adjustment
    /// </summary>
    public bool EnableMarketDepthAnalysis { get; set; } = false;
    
    /// <summary>
    /// Whether to log detailed execution information
    /// </summary>
    public bool EnableDetailedLogging { get; set; } = false;
    
    public static IcebergConfig Default => new IcebergConfig();
}

Iceberg Execution Models

Iceberg Execution State

/// <summary>
/// State of an Iceberg execution
/// </summary>
public record IcebergExecutionState
{
    /// <summary>
    /// Unique identifier for this Iceberg execution
    /// </summary>
    public string ExecutionId { get; set; } = Guid.NewGuid().ToString();
    
    /// <summary>
    /// Parameters used for this execution
    /// </summary>
    public IcebergParameters Parameters { get; set; }
    
    /// <summary>
    /// Current execution status
    /// </summary>
    public IcebergExecutionStatus Status { get; set; } = IcebergExecutionStatus.Pending;
    
    /// <summary>
    /// Total quantity to execute
    /// </summary>
    public int TotalQuantity { get; set; }
    
    /// <summary>
    /// Quantity already executed
    /// </summary>
    public int ExecutedQuantity { get; set; }
    
    /// <summary>
    /// Remaining quantity to execute
    /// </summary>
    public int RemainingQuantity => TotalQuantity - ExecutedQuantity;
    
    /// <summary>
    /// Currently visible quantity
    /// </summary>
    public int VisibleQuantity { get; set; }
    
    /// <summary>
    /// Currently displayed order (if any)
    /// </summary>
    public IcebergOrder DisplayedOrder { get; set; }
    
    /// <summary>
    /// All orders placed during execution
    /// </summary>
    public List<IcebergOrder> Orders { get; set; } = new List<IcebergOrder>();
    
    /// <summary>
    /// Completed orders
    /// </summary>
    public List<IcebergOrder> CompletedOrders { get; set; } = new List<IcebergOrder>();
    
    /// <summary>
    /// Failed orders
    /// </summary>
    public List<IcebergOrder> FailedOrders { get; set; } = new List<IcebergOrder>();
    
    /// <summary>
    /// Start time of execution
    /// </summary>
    public DateTime? StartTime { get; set; }
    
    /// <summary>
    /// End time of execution
    /// </summary>
    public DateTime? EndTime { get; set; }
    
    /// <summary>
    /// When this execution was created
    /// </summary>
    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
    
    /// <summary>
    /// When this execution was last updated
    /// </summary>
    public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
    
    /// <summary>
    /// Error information if execution failed
    /// </summary>
    public string ErrorMessage { get; set; }
    
    /// <summary>
    /// Performance metrics for this execution
    /// </summary>
    public IcebergPerformanceMetrics PerformanceMetrics { get; set; } = new IcebergPerformanceMetrics();
}

Iceberg Order

/// <summary>
/// Represents a single order placed as part of Iceberg execution
/// </summary>
public record IcebergOrder
{
    /// <summary>
    /// Unique identifier for this order
    /// </summary>
    public string OrderId { get; set; }
    
    /// <summary>
    /// Reference to parent Iceberg execution
    /// </summary>
    public string ExecutionId { get; set; }
    
    /// <summary>
    /// Order number within execution (1-based)
    /// </summary>
    public int OrderNumber { get; set; }
    
    /// <summary>
    /// Scheduled placement time
    /// </summary>
    public DateTime ScheduledTime { get; set; }
    
    /// <summary>
    /// Actual placement time
    /// </summary>
    public DateTime? ActualTime { get; set; }
    
    /// <summary>
    /// Quantity for this order
    /// </summary>
    public int Quantity { get; set; }
    
    /// <summary>
    /// Status of this order
    /// </summary>
    public IcebergOrderStatus Status { get; set; } = IcebergOrderStatus.Pending;
    
    /// <summary>
    /// Order details
    /// </summary>
    public OrderRequest OrderDetails { get; set; }
    
    /// <summary>
    /// Fills for this order
    /// </summary>
    public List<OrderFill> Fills { get; set; } = new List<OrderFill>();
    
    /// <summary>
    /// Total filled quantity
    /// </summary>
    public int FilledQuantity => Fills?.Sum(f => f.Quantity) ?? 0;
    
    /// <summary>
    /// Average fill price
    /// </summary>
    public decimal AverageFillPrice => Fills?.Any() == true ? 
        Fills.Sum(f => f.Quantity * f.FillPrice) / FilledQuantity : 0;
    
    /// <summary>
    /// Total commission for this order
    /// </summary>
    public decimal TotalCommission => Fills?.Sum(f => f.Commission) ?? 0;
    
    /// <summary>
    /// Error information if order failed
    /// </summary>
    public string ErrorMessage { get; set; }
    
    /// <summary>
    /// Retry count for this order
    /// </summary>
    public int RetryCount { get; set; }
    
    /// <summary>
    /// Whether this order was cancelled
    /// </summary>
    public bool WasCancelled { get; set; }
    
    /// <summary>
    /// When this order was created
    /// </summary>
    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
    
    /// <summary>
    /// When this order was last updated
    /// </summary>
    public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
}

Iceberg Performance Metrics

/// <summary>
/// Performance metrics for Iceberg execution
/// </summary>
public record IcebergPerformanceMetrics
{
    /// <summary>
    /// Total execution time
    /// </summary>
    public TimeSpan TotalExecutionTime { get; set; }
    
    /// <summary>
    /// Average fill price
    /// </summary>
    public decimal AverageFillPrice { get; set; }
    
    /// <summary>
    /// Slippage (percentage)
    /// </summary>
    public decimal Slippage { get; set; }
    
    /// <summary>
    /// Implementation shortfall (percentage)
    /// </summary>
    public decimal ImplementationShortfall { get; set; }
    
    /// <summary>
    /// Number of order placements
    /// </summary>
    public int TotalOrders { get; set; }
    
    /// <summary>
    /// Number of successful orders
    /// </summary>
    public int SuccessfulOrders { get; set; }
    
    /// <summary>
    /// Number of failed orders
    /// </summary>
    public int FailedOrders { get; set; }
    
    /// <summary>
    /// Number of cancelled orders
    /// </summary>
    public int CancelledOrders { get; set; }
    
    /// <summary>
    /// Average visible quantity as percentage of total
    /// </summary>
    public decimal AverageVisibility { get; set; }
    
    /// <summary>
    /// Total commission paid
    /// </summary>
    public decimal TotalCommission { get; set; }
    
    /// <summary>
    /// When metrics were last updated
    /// </summary>
    public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
}

Enums

/// <summary>
/// Status of Iceberg execution
/// </summary>
public enum IcebergExecutionStatus
{
    Pending,
    Running,
    Completed,
    Cancelled,
    Failed
}

/// <summary>
/// Status of Iceberg order
/// </summary>
public enum IcebergOrderStatus
{
    Pending,
    Scheduled,
    Submitted,
    PartiallyFilled,
    Filled,
    Cancelled,
    Failed
}

Iceberg Algorithm Implementation

Iceberg Executor

/// <summary>
/// Executes Iceberg algorithms
/// </summary>
public class IcebergExecutor
{
    private readonly ILogger<IcebergExecutor> _logger;
    private readonly IOrderManager _orderManager;
    private readonly IMarketDataProvider _marketDataProvider;
    private readonly IcebergConfig _config;
    private readonly Dictionary<string, IcebergExecutionState> _executions;
    private readonly Dictionary<string, CancellationTokenSource> _executionCancellations;
    private readonly object _lock = new object();
    
    public IcebergExecutor(
        ILogger<IcebergExecutor> logger,
        IOrderManager orderManager,
        IMarketDataProvider marketDataProvider,
        IcebergConfig config = null)
    {
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        _orderManager = orderManager ?? throw new ArgumentNullException(nameof(orderManager));
        _marketDataProvider = marketDataProvider ?? throw new ArgumentNullException(nameof(marketDataProvider));
        _config = config ?? IcebergConfig.Default;
        _executions = new Dictionary<string, IcebergExecutionState>();
        _executionCancellations = new Dictionary<string, CancellationTokenSource>();
    }
    
    /// <summary>
    /// Execute an Iceberg order
    /// </summary>
    public async Task<IcebergExecutionState> ExecuteIcebergAsync(IcebergParameters parameters, StrategyContext context)
    {
        if (parameters == null) throw new ArgumentNullException(nameof(parameters));
        if (context == null) throw new ArgumentNullException(nameof(context));
        
        // Validate parameters
        ValidateParameters(parameters);
        
        // Create execution state
        var executionState = CreateExecutionState(parameters);
        
        lock (_lock)
        {
            _executions[executionState.ExecutionId] = executionState;
        }
        
        _logger.LogInformation("Starting Iceberg execution {ExecutionId} for {Symbol} {Side} {Quantity} (visible: {VisibleQuantity})", 
            executionState.ExecutionId, parameters.Symbol, parameters.Side, parameters.TotalQuantity, parameters.VisibleQuantity);
        
        try
        {
            // Start execution
            await StartExecutionAsync(executionState, context);
            
            return executionState;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error starting Iceberg execution {ExecutionId}", executionState.ExecutionId);
            
            executionState.Status = IcebergExecutionStatus.Failed;
            executionState.ErrorMessage = ex.Message;
            executionState.UpdatedAt = DateTime.UtcNow;
            
            throw;
        }
    
    private void ValidateParameters(IcebergParameters parameters)
    {
        if (string.IsNullOrEmpty(parameters.Symbol))
            throw new ArgumentException("Symbol is required", nameof(parameters));
            
        if (parameters.TotalQuantity <= 0)
            throw new ArgumentException("Total quantity must be positive", nameof(parameters));
            
        if (parameters.VisibleQuantity <= 0)
            throw new ArgumentException("Visible quantity must be positive", nameof(parameters));
            
        if (parameters.VisibleQuantity > parameters.TotalQuantity)
            throw new ArgumentException("Visible quantity cannot exceed total quantity", nameof(parameters));
            
        if (parameters.PlacementDelayMs < 0)
            throw new ArgumentException("Placement delay must be non-negative", nameof(parameters));
    }
    
    private IcebergExecutionState CreateExecutionState(IcebergParameters parameters)
    {
        var executionState = new IcebergExecutionState
        {
            Parameters = parameters,
            TotalQuantity = parameters.TotalQuantity,
            VisibleQuantity = parameters.VisibleQuantity,
            StartTime = DateTime.UtcNow
        };
        
        return executionState;
    }
    
    private async Task StartExecutionAsync(IcebergExecutionState executionState, StrategyContext context)
    {
        executionState.Status = IcebergExecutionStatus.Running;
        executionState.StartTime = DateTime.UtcNow;
        executionState.UpdatedAt = DateTime.UtcNow;
        
        // Create cancellation token for this execution
        var cancellationTokenSource = new CancellationTokenSource();
        lock (_lock)
        {
            _executionCancellations[executionState.ExecutionId] = cancellationTokenSource;
        }
        
        // Start execution loop
        _ = ExecuteIcebergLoopAsync(executionState, context, cancellationTokenSource.Token);
        
        _logger.LogInformation("Iceberg execution {ExecutionId} started", executionState.ExecutionId);
    }
    
    private async Task ExecuteIcebergLoopAsync(IcebergExecutionState executionState, StrategyContext context, CancellationToken cancellationToken)
    {
        try
        {
            while (executionState.RemainingQuantity > 0 && !cancellationToken.IsCancellationRequested)
            {
                // Check if we should place a new order
                if (executionState.DisplayedOrder == null || 
                    executionState.DisplayedOrder.Status == IcebergOrderStatus.Filled ||
                    executionState.DisplayedOrder.Status == IcebergOrderStatus.Cancelled ||
                    executionState.DisplayedOrder.Status == IcebergOrderStatus.Failed)
                {
                    // Place new order
                    await PlaceNextOrderAsync(executionState, context);
                }
                else if (executionState.DisplayedOrder.Status == IcebergOrderStatus.Submitted ||
                         executionState.DisplayedOrder.Status == IcebergOrderStatus.PartiallyFilled)
                {
                    // Monitor existing order
                    await MonitorOrderAsync(executionState, context);
                }
                
                // Wait before next iteration
                await Task.Delay(executionState.Parameters.PlacementDelayMs, cancellationToken);
            }
            
            // Complete execution
            await CompleteExecutionAsync(executionState);
        }
        catch (OperationCanceledException)
        {
            // Execution was cancelled
            _logger.LogInformation("Iceberg execution {ExecutionId} was cancelled", executionState.ExecutionId);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error in Iceberg execution loop {ExecutionId}", executionState.ExecutionId);
            executionState.Status = IcebergExecutionStatus.Failed;
            executionState.ErrorMessage = ex.Message;
            executionState.UpdatedAt = DateTime.UtcNow;
        }
    }
    
    private async Task PlaceNextOrderAsync(IcebergExecutionState executionState, StrategyContext context)
    {
        // Calculate order size
        var orderSize = Math.Min(executionState.VisibleQuantity, executionState.RemainingQuantity);
        if (orderSize <= 0)
        {
            return;
        }
        
        // Adjust visible quantity if adaptive
        if (executionState.Parameters.AdaptiveVisibility)
        {
            orderSize = await AdjustVisibleQuantityAsync(executionState, orderSize);
        }
        
        var orderNumber = executionState.Orders.Count + 1;
        
        var order = new IcebergOrder
        {
            ExecutionId = executionState.ExecutionId,
            OrderNumber = orderNumber,
            ScheduledTime = DateTime.UtcNow,
            Quantity = orderSize,
            OrderDetails = new OrderRequest(
                Symbol: executionState.Parameters.Symbol,
                Side: executionState.Parameters.Side,
                Type: executionState.Parameters.LimitPrice.HasValue ? OrderType.Limit : OrderType.Market,
                Quantity: orderSize,
                LimitPrice: executionState.Parameters.LimitPrice,
                StopPrice: null,
                TimeInForce: executionState.Parameters.TimeInForce,
                Algorithm: null,
                AlgorithmParameters: new Dictionary<string, object>()
            )
        };
        
        executionState.Orders.Add(order);
        executionState.DisplayedOrder = order;
        
        try
        {
            order.Status = IcebergOrderStatus.Submitted;
            order.ActualTime = DateTime.UtcNow;
            order.UpdatedAt = DateTime.UtcNow;
            
            _logger.LogInformation("Placing Iceberg order {OrderNumber} for {Quantity} (remaining: {Remaining})", 
                orderNumber, orderSize, executionState.RemainingQuantity);
            
            // Submit order
            var orderResult = await _orderManager.SubmitOrderAsync(order.OrderDetails, context);
            
            if (orderResult.Success)
            {
                order.OrderId = orderResult.OrderId;
                order.Status = IcebergOrderStatus.Submitted;
                order.UpdatedAt = DateTime.UtcNow;
                
                _logger.LogInformation("Iceberg order {OrderNumber} submitted: {OrderId}", 
                    orderNumber, orderResult.OrderId);
            }
            else
            {
                order.Status = IcebergOrderStatus.Failed;
                order.ErrorMessage = orderResult.Message;
                order.UpdatedAt = DateTime.UtcNow;
                
                _logger.LogWarning("Iceberg order {OrderNumber} failed: {ErrorMessage}", 
                    orderNumber, orderResult.Message);
                
                // Handle retry if configured
                if (order.RetryCount < _config.MaxRetries)
                {
                    order.RetryCount++;
                    _logger.LogInformation("Retrying Iceberg order {OrderNumber} (attempt {RetryCount})", 
                        orderNumber, order.RetryCount);
                    
                    await Task.Delay(_config.RetryDelayMs);
                    await PlaceNextOrderAsync(executionState, context);
                    return;
                }
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error placing Iceberg order {OrderNumber}", orderNumber);
            
            order.Status = IcebergOrderStatus.Failed;
            order.ErrorMessage = ex.Message;
            order.UpdatedAt = DateTime.UtcNow;
        }
        
        UpdateExecutionState(executionState, order);
    }
    
    private async Task<int> AdjustVisibleQuantityAsync(IcebergExecutionState executionState, int currentVisibleQuantity)
    {
        if (!_config.EnableAdaptiveVisibility)
            return currentVisibleQuantity;
            
        // Get market depth information
        var marketDepth = await GetMarketDepthAsync(executionState.Parameters.Symbol);
        if (marketDepth == null)
            return currentVisibleQuantity;
            
        // Adjust based on market depth
        var adjustedQuantity = currentVisibleQuantity;
        
        // If there's good liquidity at our price level, we can be more aggressive
        if (executionState.Parameters.Side == OrderSide.Buy)
        {
            var askDepth = marketDepth.Asks.FirstOrDefault()?.Size ?? 0;
            if (askDepth > currentVisibleQuantity * 5) // 5x our size available
            {
                adjustedQuantity = Math.Min(currentVisibleQuantity * 2, executionState.VisibleQuantity);
            }
        }
        else
        {
            var bidDepth = marketDepth.Bids.FirstOrDefault()?.Size ?? 0;
            if (bidDepth > currentVisibleQuantity * 5) // 5x our size available
            {
                adjustedQuantity = Math.Min(currentVisibleQuantity * 2, executionState.VisibleQuantity);
            }
        }
        
        // Ensure we don't exceed configured limits
        var maxVisible = executionState.Parameters.MaxVisibleQuantity ?? 
            (int)(executionState.TotalQuantity * _config.MaxVisiblePercentage);
        var minVisible = Math.Max(executionState.Parameters.MinVisibleQuantity,
            (int)(executionState.TotalQuantity * _config.MinVisiblePercentage));
            
        if (adjustedQuantity > maxVisible)
            adjustedQuantity = maxVisible;
            
        if (adjustedQuantity < minVisible)
            adjustedQuantity = minVisible;
            
        return adjustedQuantity;
    }
    
    private async Task<MarketDepth> GetMarketDepthAsync(string symbol)
    {
        // In a real implementation, this would get real-time market depth data
        // For now, we'll return null to indicate no adjustment
        return null;
    }
    
    private async Task MonitorOrderAsync(IcebergExecutionState executionState, StrategyContext context)
    {
        if (executionState.DisplayedOrder == null)
            return;
            
        // In a real implementation, we would monitor the order status
        // For now, we'll simulate order completion
        var random = new Random();
        if (random.NextDouble() < 0.3) // 30% chance of order completion each cycle
        {
            // Simulate order fill
            executionState.DisplayedOrder.Status = IcebergOrderStatus.Filled;
            executionState.DisplayedOrder.Fills.Add(new OrderFill
            {
                OrderId = executionState.DisplayedOrder.OrderId,
                Symbol = executionState.Parameters.Symbol,
                Quantity = executionState.DisplayedOrder.Quantity,
                FillPrice = executionState.Parameters.LimitPrice ?? 100, // Simulated price
                FillTime = DateTime.UtcNow,
                Commission = executionState.DisplayedOrder.Quantity * 0.5m, // Simulated commission
                ExecutionId = Guid.NewGuid().ToString()
            });
            
            executionState.DisplayedOrder.UpdatedAt = DateTime.UtcNow;
            UpdateExecutionState(executionState, executionState.DisplayedOrder);
        }
    }
    
    private void UpdateExecutionState(IcebergExecutionState executionState, IcebergOrder order)
    {
        lock (_lock)
        {
            // Update executed quantity
            executionState.ExecutedQuantity = executionState.Orders
                .Where(o => o.Status == IcebergOrderStatus.Filled)
                .Sum(o => o.FilledQuantity);
                
            // Move order to appropriate list
            if (order.Status == IcebergOrderStatus.Filled)
            {
                executionState.CompletedOrders.Add(order);
                executionState.DisplayedOrder = null; // Clear displayed order
            }
            else if (order.Status == IcebergOrderStatus.Failed)
            {
                executionState.FailedOrders.Add(order);
            }
            
            // Update execution metrics
            UpdatePerformanceMetrics(executionState);
            
            // Check if execution is complete
            if (executionState.RemainingQuantity <= 0)
            {
                _ = CompleteExecutionAsync(executionState);
            }
            
            executionState.UpdatedAt = DateTime.UtcNow;
        }
    }
    
    private void UpdatePerformanceMetrics(IcebergExecutionState executionState)
    {
        var metrics = new IcebergPerformanceMetrics();
        
        // Calculate basic metrics
        var allOrders = executionState.Orders;
        if (allOrders.Any())
        {
            metrics.TotalOrders = allOrders.Count;
            metrics.SuccessfulOrders = executionState.CompletedOrders.Count;
            metrics.FailedOrders = executionState.FailedOrders.Count;
            metrics.TotalCommission = allOrders.Sum(o => o.TotalCommission);
            
            // Calculate average visibility
            if (executionState.TotalQuantity > 0)
            {
                metrics.AverageVisibility = (decimal)(executionState.VisibleQuantity / (double)executionState.TotalQuantity);
            }
            
            // Calculate average fill price
            var totalValue = allOrders.Where(o => o.Status == IcebergOrderStatus.Filled)
                .Sum(o => o.FilledQuantity * (double)o.AverageFillPrice);
            var totalQuantity = allOrders.Where(o => o.Status == IcebergOrderStatus.Filled)
                .Sum(o => o.FilledQuantity);
                
            if (totalQuantity > 0)
            {
                metrics.AverageFillPrice = (decimal)(totalValue / totalQuantity);
            }
        }
        
        executionState.PerformanceMetrics = metrics;
    }
    
    private async Task CompleteExecutionAsync(IcebergExecutionState executionState)
    {
        if (executionState.RemainingQuantity <= 0)
        {
            executionState.Status = IcebergExecutionStatus.Completed;
            _logger.LogInformation("Iceberg execution {ExecutionId} completed successfully", executionState.ExecutionId);
        }
        else
        {
            executionState.Status = IcebergExecutionStatus.Failed;
            _logger.LogWarning("Iceberg execution {ExecutionId} completed with remaining quantity", executionState.ExecutionId);
        }
        
        executionState.EndTime = DateTime.UtcNow;
        executionState.UpdatedAt = DateTime.UtcNow;
        
        // Cancel any remaining displayed order if configured
        if (executionState.Parameters.CancelAtEnd && executionState.DisplayedOrder != null)
        {
            await CancelDisplayedOrderAsync(executionState);
        }
        
        // Clean up cancellation token
        lock (_lock)
        {
            if (_executionCancellations.ContainsKey(executionState.ExecutionId))
            {
                _executionCancellations[executionState.ExecutionId].Dispose();
                _executionCancellations.Remove(executionState.ExecutionId);
            }
        }
    }
    
    private async Task CancelDisplayedOrderAsync(IcebergExecutionState executionState)
    {
        if (executionState.DisplayedOrder?.OrderId != null)
        {
            try
            {
                await _orderManager.CancelOrderAsync(executionState.DisplayedOrder.OrderId);
                executionState.DisplayedOrder.Status = IcebergOrderStatus.Cancelled;
                executionState.DisplayedOrder.WasCancelled = true;
                executionState.DisplayedOrder.UpdatedAt = DateTime.UtcNow;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error cancelling displayed Iceberg order {OrderId}", 
                    executionState.DisplayedOrder.OrderId);
            }
        }
    }
    
    /// <summary>
    /// Cancel an Iceberg execution
    /// </summary>
    public async Task<bool> CancelExecutionAsync(string executionId)
    {
        if (string.IsNullOrEmpty(executionId)) throw new ArgumentException("Execution ID required", nameof(executionId));
        
        IcebergExecutionState executionState;
        CancellationTokenSource cancellationTokenSource;
        
        lock (_lock)
        {
            if (!_executions.ContainsKey(executionId))
                return false;
                
            executionState = _executions[executionId];
            
            if (!_executionCancellations.ContainsKey(executionId))
                return false;
                
            cancellationTokenSource = _executionCancellations[executionId];
        }
        
        if (executionState.Status != IcebergExecutionStatus.Running)
            return false;
        
        try
        {
            // Cancel the execution loop
            cancellationTokenSource.Cancel();
            
            // Cancel any displayed order
            await CancelDisplayedOrderAsync(executionState);
            
            // Update execution state
            executionState.Status = IcebergExecutionStatus.Cancelled;
            executionState.EndTime = DateTime.UtcNow;
            executionState.UpdatedAt = DateTime.UtcNow;
            
            _logger.LogInformation("Iceberg execution {ExecutionId} cancelled", executionId);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error cancelling Iceberg execution {ExecutionId}", executionId);
            return false;
        }
    }
    
    /// <summary>
    /// Get execution state
    /// </summary>
    public IcebergExecutionState GetExecutionState(string executionId)
    {
        if (string.IsNullOrEmpty(executionId)) return null;
        
        lock (_lock)
        {
            return _executions.ContainsKey(executionId) ? 
                new IcebergExecutionState(_executions[executionId]) : null;
        }
    }
    
    /// <summary>
    /// Get all execution states
    /// </summary>
    public List<IcebergExecutionState> GetAllExecutionStates()
    {
        lock (_lock)
        {
            return _executions.Values.Select(e => new IcebergExecutionState(e)).ToList();
        }
    }
}

Integration with OrderManager

Iceberg Integration in OrderManager

public partial class OrderManager : IOrderManager
{
    private readonly IcebergExecutor _icebergExecutor;
    
    // Enhanced constructor with Iceberg executor
    public OrderManager(
        IRiskManager riskManager,
        IPositionSizer positionSizer,
        ILogger<OrderManager> logger,
        RoutingConfigurationManager configManager,
        RoutingMetricsCollector metricsCollector,
        TwapExecutor twapExecutor,
        VwapExecutor vwapExecutor,
        IcebergExecutor icebergExecutor) : base(riskManager, positionSizer, logger, configManager, metricsCollector, twapExecutor, vwapExecutor)
    {
        _icebergExecutor = icebergExecutor ?? throw new ArgumentNullException(nameof(icebergExecutor));
        _venueManager = new VenueManager(logger);
        _omsToVenueOrderIdMap = new Dictionary<string, string>();
        _venueToOmsOrderIdMap = new Dictionary<string, string>();
        
        // Initialize with configurations
        InitializeWithConfigurationsAsync().Wait();
    }
    
    /// <summary>
    /// Execute an Iceberg order
    /// </summary>
    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));
        
        try
        {
            _logger.LogInformation("Executing Iceberg order for {Symbol} {Side} {Quantity} (visible: {VisibleQuantity})", 
                parameters.Symbol, parameters.Side, parameters.TotalQuantity, parameters.VisibleQuantity);
            
            // Validate through risk management
            var riskDecision = await ValidateIcebergOrderAsync(parameters, context);
            if (!riskDecision.Allow)
            {
                _logger.LogWarning("Iceberg order rejected by risk management: {Reason}", riskDecision.RejectReason);
                return new OrderResult(false, null, $"Risk validation failed: {riskDecision.RejectReason}", null);
            }
            
            // Execute Iceberg
            var executionState = await _icebergExecutor.ExecuteIcebergAsync(parameters, context);
            
            // Create order result
            var orderResult = new OrderResult(
                Success: executionState.Status == IcebergExecutionStatus.Completed,
                OrderId: executionState.ExecutionId,
                Message: executionState.Status == IcebergExecutionStatus.Completed ? 
                    "Iceberg execution completed successfully" : 
                    $"Iceberg execution failed: {executionState.ErrorMessage}",
                Status: ConvertToOrderStatus(executionState)
            );
            
            _logger.LogInformation("Iceberg order execution {Result}: {Message}", 
                orderResult.Success ? "succeeded" : "failed", orderResult.Message);
            
            return orderResult;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error executing Iceberg order for {Symbol}", parameters.Symbol);
            return new OrderResult(false, null, $"Error executing Iceberg order: {ex.Message}", null);
        }
    }
    
    private async Task<RiskDecision> ValidateIcebergOrderAsync(IcebergParameters parameters, StrategyContext context)
    {
        // Convert Iceberg parameters to strategy intent for risk validation
        var intent = new StrategyIntent(
            Symbol: parameters.Symbol,
            Side: ConvertOrderSide(parameters.Side),
            EntryType: parameters.LimitPrice.HasValue ? OrderType.Limit : OrderType.Market,
            LimitPrice: (double?)parameters.LimitPrice,
            StopTicks: 10, // Placeholder - would calculate based on stop price
            TargetTicks: null,
            Confidence: 1.0,
            Reason: "Iceberg Algorithm Order",
            Metadata: parameters.Metadata
        );
        
        // Get risk configuration
        var config = new RiskConfig(1000, 200, 10, true); // Placeholder - would get from configuration
        
        return _riskManager.ValidateOrder(intent, context, config);
    }
    
    private OrderStatus ConvertToOrderStatus(IcebergExecutionState executionState)
    {
        if (executionState == null) return null;
        
        var state = executionState.Status switch
        {
            IcebergExecutionStatus.Pending => OrderState.New,
            IcebergExecutionStatus.Running => OrderState.Accepted,
            IcebergExecutionStatus.Completed => OrderState.Filled,
            IcebergExecutionStatus.Cancelled => OrderState.Cancelled,
            IcebergExecutionStatus.Failed => OrderState.Rejected,
            _ => OrderState.Unknown
        };
        
        // Combine all fills from completed orders
        var allFills = executionState.Orders.SelectMany(o => o.Fills).ToList();
        
        return new OrderStatus(
            OrderId: executionState.ExecutionId,
            Symbol: executionState.Parameters.Symbol,
            Side: executionState.Parameters.Side,
            Type: executionState.Parameters.LimitPrice.HasValue ? OrderType.Limit : OrderType.Market,
            Quantity: executionState.TotalQuantity,
            FilledQuantity: executionState.ExecutedQuantity,
            LimitPrice: executionState.Parameters.LimitPrice,
            StopPrice: null,
            State: state,
            CreatedTime: executionState.CreatedAt,
            FilledTime: executionState.EndTime,
            Fills: allFills
        );
    }
    
    /// <summary>
    /// Cancel an Iceberg execution
    /// </summary>
    public async Task<bool> CancelIcebergAsync(string executionId)
    {
        if (string.IsNullOrEmpty(executionId)) throw new ArgumentException("Execution ID required", nameof(executionId));
        
        return await _icebergExecutor.CancelExecutionAsync(executionId);
    }
    
    /// <summary>
    /// Get Iceberg execution state
    /// </summary>
    public IcebergExecutionState GetIcebergExecutionState(string executionId)
    {
        if (string.IsNullOrEmpty(executionId)) return null;
        
        return _icebergExecutor.GetExecutionState(executionId);
    }
}

Iceberg Configuration Management

Iceberg Configuration Integration

public partial class RoutingConfigurationManager
{
    /// <summary>
    /// Get Iceberg configuration
    /// </summary>
    public async Task<IcebergConfig> GetIcebergConfigAsync()
    {
        var config = await GetConfigurationAsync<IcebergConfig>("iceberg-config");
        return config ?? IcebergConfig.Default;
    }
    
    /// <summary>
    /// Update Iceberg configuration
    /// </summary>
    public async Task UpdateIcebergConfigAsync(IcebergConfig config)
    {
        if (config == null) throw new ArgumentNullException(nameof(config));
        
        config.Id = "iceberg-config";
        config.Name = "Iceberg Configuration";
        config.Description = "Configuration for Iceberg algorithm behavior";
        
        await UpdateConfigurationAsync(config);
        _logger.LogInformation("Iceberg configuration updated");
    }
}

Testing Considerations

Unit Tests for Iceberg Algorithm

  1. Order Size Calculation: Test calculation of order sizes based on visible quantity
  2. Parameter Validation: Test validation of Iceberg parameters
  3. Order Placement: Test placement of individual orders
  4. Order Monitoring: Test monitoring of order status and fills
  5. Error Handling: Test handling of execution errors and retries
  6. Cancellation: Test cancellation of Iceberg executions
  7. Metrics Collection: Test collection of performance metrics
  8. Visibility Adjustment: Test adjustment of visible quantity based on market conditions

Integration Tests

  1. End-to-End Execution: Test complete Iceberg execution from start to finish
  2. Order Manager Integration: Test integration with OrderManager
  3. Risk Management Integration: Test risk validation for Iceberg orders
  4. Market Data Integration: Test integration with market data providers
  5. Performance Testing: Test performance with large order sizes
  6. Concurrent Executions: Test multiple concurrent Iceberg executions

Performance Considerations

Memory Management

/// <summary>
/// Manages memory usage for Iceberg executions
/// </summary>
public class IcebergMemoryManager
{
    private readonly int _maxExecutions;
    private readonly TimeSpan _executionRetentionTime;
    private readonly Dictionary<string, DateTime> _executionAccessTimes;
    private readonly object _lock = new object();
    
    public IcebergMemoryManager(int maxExecutions = 1000, TimeSpan retentionTime = default)
    {
        _maxExecutions = maxExecutions;
        _executionRetentionTime = retentionTime == default ? 
            TimeSpan.FromHours(24) : retentionTime;
        _executionAccessTimes = new Dictionary<string, DateTime>();
    }
    
    public void RecordExecutionAccess(string executionId)
    {
        lock (_lock)
        {
            _executionAccessTimes[executionId] = DateTime.UtcNow;
        }
    }
    
    public List<string> GetExpiredExecutions()
    {
        var cutoffTime = DateTime.UtcNow.Subtract(_executionRetentionTime);
        
        lock (_lock)
        {
            return _executionAccessTimes
                .Where(kvp => kvp.Value < cutoffTime)
                .Select(kvp => kvp.Key)
                .ToList();
        }
    }
    
    public bool IsMemoryPressureHigh(int currentExecutionCount)
    {
        return currentExecutionCount > (_maxExecutions * 0.8); // 80% threshold
    }
}

Adaptive Iceberg

/// <summary>
/// Adaptive Iceberg that adjusts based on market conditions
/// </summary>
public class AdaptiveIcebergExecutor : IcebergExecutor
{
    private readonly IMarketAnalyzer _marketAnalyzer;
    
    public AdaptiveIcebergExecutor(
        ILogger<IcebergExecutor> logger,
        IOrderManager orderManager,
        IMarketDataProvider marketDataProvider,
        IMarketAnalyzer marketAnalyzer,
        IcebergConfig config = null) : base(logger, orderManager, marketDataProvider, config)
    {
        _marketAnalyzer = marketAnalyzer ?? throw new ArgumentNullException(nameof(marketAnalyzer));
    }
    
    protected override async Task<int> AdjustVisibleQuantityAsync(IcebergExecutionState executionState, int currentVisibleQuantity)
    {
        if (!_config.EnableAdaptiveVisibility || _marketAnalyzer == null)
            return await base.AdjustVisibleQuantityAsync(executionState, currentVisibleQuantity);
            
        try
        {
            var marketConditions = await _marketAnalyzer.AnalyzeMarketConditionsAsync(
                executionState.Parameters.Symbol);
                
            var adjustedQuantity = currentVisibleQuantity;
            
            // Adjust based on market volatility
            if (marketConditions.Volatility > 0.02m) // High volatility (2%+)
            {
                // Reduce visibility in volatile markets
                adjustedQuantity = (int)(currentVisibleQuantity * 0.7);
            }
            else if (marketConditions.Volatility < 0.005m) // Low volatility (<0.5%)
            {
                // Increase visibility in stable markets
                adjustedQuantity = (int)(currentVisibleQuantity * 1.3);
            }
            
            // Adjust based on liquidity
            if (marketConditions.Liquidity < 0.3) // Low liquidity
            {
                // Reduce visibility in illiquid markets
                adjustedQuantity = Math.Min(adjustedQuantity, (int)(currentVisibleQuantity * 0.5));
            }
            
            // Ensure we don't exceed configured limits
            var maxVisible = executionState.Parameters.MaxVisibleQuantity ?? 
                (int)(executionState.TotalQuantity * _config.MaxVisiblePercentage);
            var minVisible = Math.Max(executionState.Parameters.MinVisibleQuantity,
                (int)(executionState.TotalQuantity * _config.MinVisiblePercentage));
                
            if (adjustedQuantity > maxVisible)
                adjustedQuantity = maxVisible;
                
            if (adjustedQuantity < minVisible)
                adjustedQuantity = minVisible;
                
            return adjustedQuantity;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error adjusting visible quantity for {Symbol}", executionState.Parameters.Symbol);
            return await base.AdjustVisibleQuantityAsync(executionState, currentVisibleQuantity);
        }
    }
}

/// <summary>
/// Interface for market analysis
/// </summary>
public interface IMarketAnalyzer
{
    /// <summary>
    /// Analyze current market conditions for a symbol
    /// </summary>
    Task<MarketConditions> AnalyzeMarketConditionsAsync(string symbol);
}

/// <summary>
/// Market conditions analysis result
/// </summary>
public record MarketConditions
{
    public string Symbol { get; set; }
    public decimal Volatility { get; set; } // 0.0 to 1.0
    public decimal Liquidity { get; set; } // 0.0 to 1.0
    public MarketTrend Trend { get; set; }
    public decimal Spread { get; set; }
    public DateTime AnalysisTime { get; set; }
}

/// <summary>
/// Market trend enumeration
/// </summary>
public enum MarketTrend
{
    Up,
    Down,
    Sideways
}

Monitoring and Alerting

Iceberg Metrics Export

/// <summary>
/// Exports Iceberg metrics for monitoring
/// </summary>
public class IcebergMetricsExporter
{
    private readonly IcebergExecutor _icebergExecutor;
    
    public IcebergMetricsExporter(IcebergExecutor icebergExecutor)
    {
        _icebergExecutor = icebergExecutor ?? throw new ArgumentNullException(nameof(icebergExecutor));
    }
    
    public string ExportToPrometheus()
    {
        var executions = _icebergExecutor.GetAllExecutionStates();
        var sb = new StringBuilder();
        
        // Overall Iceberg metrics
        var activeExecutions = executions.Count(e => e.Status == IcebergExecutionStatus.Running);
        var completedExecutions = executions.Count(e => e.Status == IcebergExecutionStatus.Completed);
        var failedExecutions = executions.Count(e => e.Status == IcebergExecutionStatus.Failed);
        
        sb.AppendLine($"# HELP iceberg_active_executions Number of active Iceberg executions");
        sb.AppendLine($"# TYPE iceberg_active_executions gauge");
        sb.AppendLine($"iceberg_active_executions {activeExecutions}");
        
        sb.AppendLine($"# HELP iceberg_completed_executions Total number of completed Iceberg executions");
        sb.AppendLine($"# TYPE iceberg_completed_executions counter");
        sb.AppendLine($"iceberg_completed_executions {completedExecutions}");
        
        sb.AppendLine($"# HELP iceberg_failed_executions Total number of failed Iceberg executions");
        sb.AppendLine($"# TYPE iceberg_failed_executions counter");
        sb.AppendLine($"iceberg_failed_executions {failedExecutions}");
        
        // Performance metrics for completed executions
        var completed = executions.Where(e => e.Status == IcebergExecutionStatus.Completed).ToList();
        if (completed.Any())
        {
            var avgSlippage = completed.Average(e => (double)e.PerformanceMetrics.Slippage);
            var avgCommission = (double)completed.Average(e => e.PerformanceMetrics.TotalCommission);
            var avgVisibility = completed.Average(e => (double)e.PerformanceMetrics.AverageVisibility);
            
            sb.AppendLine($"# HELP iceberg_average_slippage Average slippage for completed executions");
            sb.AppendLine($"# TYPE iceberg_average_slippage gauge");
            sb.AppendLine($"iceberg_average_slippage {avgSlippage:F4}");
            
            sb.AppendLine($"# HELP iceberg_average_commission Average commission for completed executions");
            sb.AppendLine($"# TYPE iceberg_average_commission gauge");
            sb.AppendLine($"iceberg_average_commission {avgCommission:F2}");
            
            sb.AppendLine($"# HELP iceberg_average_visibility Average visibility for completed executions");
            sb.AppendLine($"# TYPE iceberg_average_visibility gauge");
            sb.AppendLine($"iceberg_average_visibility {avgVisibility:F4}");
        }
        
        return sb.ToString();
    }
}

Future Enhancements

  1. Machine Learning Optimization: Use ML to optimize Iceberg parameters based on historical performance
  2. Real-time Market Adaptation: Adjust Iceberg execution based on real-time market conditions
  3. Cross-Venue Iceberg: Execute Iceberg orders across multiple venues simultaneously
  4. Iceberg Analytics: Advanced analytics and reporting on Iceberg performance
  5. Iceberg Strategy Builder: Visual tools for building and testing Iceberg strategies
  6. Iceberg Benchmarking: Compare Iceberg performance against other execution algorithms
  7. Iceberg Risk Controls: Enhanced risk controls specific to algorithmic execution
  8. Iceberg Compliance: Ensure Iceberg execution complies with regulatory requirements
  9. Smart Iceberg: Iceberg orders that adapt visibility based on fill patterns
  10. Iceberg with TWAP/VWAP: Hybrid algorithms combining Iceberg with other strategies