# Risk Validation Logic Implementation Design

## Overview

This document details the implementation of risk validation logic in the Order Management System (OMS), which integrates with the existing risk management system to ensure all orders comply with defined risk parameters before submission.

## Integration Approach

The OMS integrates with the existing IRiskManager interface to validate all orders before submission. This ensures consistency with the risk management system already implemented in the NT8 SDK.

## Risk Validation Flow

### 1. Order Request Conversion
Before validation, OMS order requests are converted to StrategyIntent objects that the risk manager can understand:

```csharp
private StrategyIntent ConvertToStrategyIntent(OrderRequest request)
{
    return new StrategyIntent(
        request.Symbol,
        ConvertOrderSide(request.Side),
        ConvertOrderType(request.Type),
        (double?)request.LimitPrice,
        GetStopTicks(request),
        GetTargetTicks(request),
        1.0, // Confidence - maximum for OMS orders
        $"OMS {request.Type} Order", // Reason
        new Dictionary<string, object>
        {
            ["OrderId"] = Guid.NewGuid().ToString(),
            ["Algorithm"] = request.Algorithm,
            ["TimeInForce"] = request.TimeInForce.ToString()
        }
    );
}

private OrderSide ConvertOrderSide(NT8.Core.Orders.OrderSide side)
{
    return side switch
    {
        NT8.Core.Orders.OrderSide.Buy => OrderSide.Buy,
        NT8.Core.Orders.OrderSide.Sell => OrderSide.Sell,
        _ => OrderSide.Flat
    };
}

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

private int GetStopTicks(OrderRequest request)
{
    // Calculate stop ticks based on stop price and current market price
    // This is a simplified implementation
    if (request.StopPrice.HasValue)
    {
        // In a real implementation, this would calculate the actual tick difference
        return 10; // Placeholder value
    }
    
    return 0;
}

private int? GetTargetTicks(OrderRequest request)
{
    // Calculate target ticks for profit targets if applicable
    // This would be used for strategies with predefined profit targets
    return null; // Not applicable for OMS orders
}
```

### 2. Risk Configuration
The risk validation uses a configuration that aligns with the existing risk management system:

```csharp
private RiskConfig GetRiskConfig()
{
    // In a real implementation, this would be configurable
    // For now, using values consistent with the existing risk management system
    return new RiskConfig(
        DailyLossLimit: 1000,      // $1000 daily loss limit
        MaxTradeRisk: 200,        // $200 maximum per-trade risk
        MaxOpenPositions: 10,     // Maximum 10 open positions
        EmergencyFlattenEnabled: true // Emergency flatten functionality enabled
    );
}
```

### 3. Risk Validation Implementation
The core risk validation logic that integrates with the existing risk manager:

```csharp
public async Task<RiskDecision> ValidateOrderAsync(OrderRequest request, StrategyContext context)
{
    if (request == null) throw new ArgumentNullException(nameof(request));
    
    try
    {
        _logger.LogInformation("Validating order for {Symbol} {Side} {Quantity}", 
            request.Symbol, request.Side, request.Quantity);
        
        // Convert order request to strategy intent
        var intent = ConvertToStrategyIntent(request);
        
        // Validate intent
        if (!intent.IsValid())
        {
            _logger.LogWarning("Invalid strategy intent generated from order request");
            return new RiskDecision(
                Allow: false,
                RejectReason: "Invalid order parameters",
                ModifiedIntent: null,
                RiskLevel: RiskLevel.Critical,
                RiskMetrics: new Dictionary<string, object> { ["error"] = "Invalid intent" }
            );
        }
        
        // Get risk configuration
        var config = GetRiskConfig();
        
        // Validate with risk manager
        var decision = _riskManager.ValidateOrder(intent, context, config);
        
        if (decision.Allow)
        {
            _logger.LogInformation("Order validation passed for {Symbol}", request.Symbol);
        }
        else
        {
            _logger.LogWarning("Order validation failed for {Symbol}: {Reason}", 
                request.Symbol, decision.RejectReason);
        }
        
        return decision;
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error validating order for {Symbol}", request.Symbol);
        return new RiskDecision(
            Allow: false,
            RejectReason: $"Risk validation error: {ex.Message}",
            ModifiedIntent: null,
            RiskLevel: RiskLevel.Critical,
            RiskMetrics: new Dictionary<string, object> { ["error"] = ex.Message }
        );
    }
}
```

### 4. Enhanced Validation for Algorithmic Orders
Special validation logic for algorithmic orders (TWAP, VWAP, Iceberg):

```csharp
private RiskDecision ValidateAlgorithmicOrder(OrderRequest request, StrategyContext context, RiskConfig config)
{
    // For algorithmic orders, we need to validate the total risk of the entire order
    // rather than just individual slices
    
    var intent = ConvertToStrategyIntent(request);
    
    // Adjust risk calculation for algorithmic orders
    if (!string.IsNullOrEmpty(request.Algorithm))
    {
        // Modify intent to reflect total order size for risk calculation
        var modifiedIntent = ModifyIntentForAlgorithmicRisk(intent, request);
        return _riskManager.ValidateOrder(modifiedIntent, context, config);
    }
    
    // Standard validation for regular orders
    return _riskManager.ValidateOrder(intent, context, config);
}

private StrategyIntent ModifyIntentForAlgorithmicRisk(StrategyIntent intent, OrderRequest request)
{
    // For algorithmic orders, the risk manager needs to understand that this is
    // part of a larger strategy and may need to adjust risk calculations
    
    var metadata = new Dictionary<string, object>(intent.Metadata ?? new Dictionary<string, object>())
    {
        ["IsAlgorithmic"] = true,
        ["AlgorithmType"] = request.Algorithm,
        ["TotalQuantity"] = request.Quantity
    };
    
    // If this is a slice of a larger order, we might need to adjust the risk calculation
    // to account for the total order size rather than just this slice
    
    return new StrategyIntent(
        intent.Symbol,
        intent.Side,
        intent.EntryType,
        intent.LimitPrice,
        intent.StopTicks,
        intent.TargetTicks,
        intent.Confidence,
        intent.Reason,
        metadata
    );
}
```

## Risk Integration with Order Processing

### Pre-Submission Validation
All order submission methods validate orders through the risk management system:

```csharp
public async Task<OrderResult> SubmitOrderAsync(OrderRequest request, StrategyContext context)
{
    // Validate request parameters
    if (!request.IsValid(out var errors))
    {
        return new OrderResult(false, null, string.Join("; ", errors), null);
    }
    
    // Validate 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, $"Risk validation failed: {riskDecision.RejectReason}", null);
    }
    
    // Continue with order processing if validation passes
    // ... (rest of order processing logic)
}
```

### Real-time Risk Updates
The OMS also updates the risk manager with real-time information about order fills:

```csharp
private async Task NotifyRiskManagerOfFillAsync(OrderFill fill)
{
    try
    {
        _riskManager.OnFill(fill);
        _logger.LogInformation("Risk manager notified of fill for order {OrderId}", fill.OrderId);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error notifying risk manager of fill for order {OrderId}", fill.OrderId);
    }
}

private async Task NotifyRiskManagerOfPnLAsync(double netPnL, double dayPnL)
{
    try
    {
        _riskManager.OnPnLUpdate(netPnL, dayPnL);
        _logger.LogInformation("Risk manager updated with P&L: Net={NetPnL}, Day={DayPnL}", netPnL, dayPnL);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error updating risk manager with P&L");
    }
}
```

## Emergency Handling

### Emergency Flatten Integration
The OMS can trigger emergency flattening through the risk management system:

```csharp
public async Task<bool> EmergencyFlattenAsync(string reason)
{
    if (string.IsNullOrEmpty(reason)) throw new ArgumentException("Reason required", nameof(reason));
    
    try
    {
        _logger.LogCritical("Emergency flatten triggered: {Reason}", reason);
        
        // Cancel all active orders
        var activeOrders = await GetActiveOrdersAsync();
        foreach (var order in activeOrders)
        {
            await CancelOrderAsync(order.OrderId);
        }
        
        // Trigger emergency flatten in risk manager
        var result = await _riskManager.EmergencyFlatten(reason);
        
        _logger.LogInformation("Emergency flatten completed: {Result}", result);
        return result;
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error during emergency flatten: {Reason}", reason);
        return false;
    }
}
```

### Circuit Breaker Integration
The OMS respects circuit breaker status from the risk management system:

```csharp
private bool IsTradingHalted()
{
    try
    {
        var riskStatus = _riskManager.GetRiskStatus();
        return !riskStatus.TradingEnabled;
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error checking trading halt status");
        // Err on the side of caution - assume trading is halted if we can't determine status
        return true;
    }
}

public async Task<OrderResult> SubmitOrderAsync(OrderRequest request, StrategyContext context)
{
    // Check if trading is halted
    if (IsTradingHalted())
    {
        _logger.LogWarning("Order submission blocked - trading is currently halted");
        return new OrderResult(false, null, "Trading is currently halted by risk management", null);
    }
    
    // Continue with normal order processing
    // ... (rest of order processing logic)
}
```

## Risk Metrics Collection

### Order-Level Risk Metrics
Collect risk metrics for each order:

```csharp
private Dictionary<string, object> CollectRiskMetrics(OrderRequest request, RiskDecision decision)
{
    var metrics = new Dictionary<string, object>
    {
        ["Symbol"] = request.Symbol,
        ["OrderType"] = request.Type.ToString(),
        ["Quantity"] = request.Quantity,
        ["RiskLevel"] = decision.RiskLevel.ToString(),
        ["ValidationTime"] = DateTime.UtcNow
    };
    
    if (decision.RiskMetrics != null)
    {
        foreach (var kvp in decision.RiskMetrics)
        {
            metrics[$"Risk_{kvp.Key}"] = kvp.Value;
        }
    }
    
    return metrics;
}
```

### Aggregated Risk Metrics
Maintain aggregated risk metrics for monitoring:

```csharp
private void UpdateAggregatedRiskMetrics(RiskDecision decision)
{
    lock (_lock)
    {
        // Update counters based on risk decision
        switch (decision.RiskLevel)
        {
            case RiskLevel.Low:
                _riskMetrics.LowRiskOrders++;
                break;
            case RiskLevel.Medium:
                _riskMetrics.MediumRiskOrders++;
                break;
            case RiskLevel.High:
                _riskMetrics.HighRiskOrders++;
                break;
            case RiskLevel.Critical:
                _riskMetrics.CriticalRiskOrders++;
                break;
        }
        
        // Track rejected orders
        if (!decision.Allow)
        {
            _riskMetrics.RejectedOrders++;
        }
        
        _riskMetrics.LastUpdated = DateTime.UtcNow;
    }
}
```

## Error Handling and Fallbacks

### Graceful Degradation
If the risk manager is unavailable, the system can implement fallback behavior:

```csharp
public async Task<RiskDecision> ValidateOrderAsync(OrderRequest request, StrategyContext context)
{
    try
    {
        // Normal risk validation
        var intent = ConvertToStrategyIntent(request);
        var config = GetRiskConfig();
        return _riskManager.ValidateOrder(intent, context, config);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Risk manager unavailable, applying fallback validation for {Symbol}", request.Symbol);
        
        // Fallback validation - more conservative approach
        return ApplyFallbackValidation(request, context);
    }
}

private RiskDecision ApplyFallbackValidation(OrderRequest request, StrategyContext context)
{
    // Conservative fallback validation
    // Reject orders that are clearly problematic
    
    // Reject if order size is too large
    if (request.Quantity > 100) // Arbitrary large size
    {
        return new RiskDecision(
            Allow: false,
            RejectReason: "Order size exceeds fallback limit",
            ModifiedIntent: null,
            RiskLevel: RiskLevel.Critical,
            RiskMetrics: new Dictionary<string, object> { ["fallback_reject"] = "size" }
        );
    }
    
    // Allow other orders with high risk level
    return new RiskDecision(
        Allow: true,
        RejectReason: null,
        ModifiedIntent: null,
        RiskLevel: RiskLevel.High, // Conservative risk level
        RiskMetrics: new Dictionary<string, object> { ["fallback_allow"] = true }
    );
}
```

## Testing Considerations

### Unit Tests for Risk Validation
1. **Valid Orders**: Orders that should pass risk validation
2. **Invalid Orders**: Orders that should be rejected by risk management
3. **Edge Cases**: Boundary conditions for risk limits
4. **Algorithmic Orders**: Special handling for TWAP, VWAP, Iceberg orders
5. **Emergency Scenarios**: Trading halt and emergency flatten scenarios

### Integration Tests
1. **Risk Manager Integration**: Verify proper integration with IRiskManager
2. **Configuration Changes**: Test behavior with different risk configurations
3. **State Management**: Verify risk state is properly maintained
4. **Error Handling**: Test fallback behavior when risk manager is unavailable

## Performance Considerations

### Validation Caching
Cache risk validation results for identical orders within a short time window:

```csharp
private readonly Dictionary<string, (RiskDecision decision, DateTime timestamp)> _validationCache 
    = new Dictionary<string, (RiskDecision, DateTime)>();

private string GenerateValidationCacheKey(OrderRequest request, StrategyContext context)
{
    // Generate a cache key based on order parameters and context
    return $"{request.Symbol}_{request.Side}_{request.Quantity}_{request.Type}_{context?.CurrentTime:yyyyMMdd}";
}

private RiskDecision GetCachedValidationResult(string cacheKey)
{
    if (_validationCache.ContainsKey(cacheKey))
    {
        var (decision, timestamp) = _validationCache[cacheKey];
        // Expire cache after 1 second
        if (DateTime.UtcNow.Subtract(timestamp).TotalSeconds < 1)
        {
            return decision;
        }
        else
        {
            _validationCache.Remove(cacheKey);
        }
    }
    
    return null;
}
```

### Asynchronous Validation
Perform risk validation asynchronously to avoid blocking order submission:

```csharp
public async Task<OrderResult> SubmitOrderAsync(OrderRequest request, StrategyContext context)
{
    // Start risk validation in background
    var validationTask = ValidateOrderAsync(request, context);
    
    // Continue with other order processing steps
    
    // Wait for validation result
    var riskDecision = await validationTask;
    
    // Process validation result
    // ... (rest of logic)
}
```

## Monitoring and Alerting

### Risk Alerts
Generate alerts for high-risk orders or risk limit breaches:

```csharp
private void GenerateRiskAlerts(RiskDecision decision, OrderRequest request)
{
    if (decision.RiskLevel == RiskLevel.High || decision.RiskLevel == RiskLevel.Critical)
    {
        _logger.LogWarning("High-risk order detected: {Symbol} {Side} {Quantity} - Risk Level: {RiskLevel}", 
            request.Symbol, request.Side, request.Quantity, decision.RiskLevel);
            
        // In a real implementation, this might trigger:
        // - Email alerts to risk managers
        // - Slack notifications
        // - Dashboard warnings
    }
}
```

### Risk Dashboard Integration
Provide metrics for risk dashboard integration:

```csharp
public RiskMetrics GetRiskMetrics()
{
    lock (_lock)
    {
        return _riskMetrics;
    }
}
```

## Future Enhancements

1. **Dynamic Risk Limits**: Adjust risk limits based on market conditions
2. **Machine Learning**: Use ML models to predict risk levels
3. **Real-time Market Data**: Integrate real-time volatility data into risk calculations
4. **Cross-Asset Risk**: Calculate risk across multiple asset classes
5. **Scenario Analysis**: Simulate risk under different market conditions
