# NT8 SDK - Architecture Overview

**Version:** 0.2.0  
**Last Updated:** February 15, 2026

---

## Table of Contents

- [System Architecture](#system-architecture)
- [Component Design](#component-design)
- [Data Flow](#data-flow)
- [Threading Model](#threading-model)
- [State Management](#state-management)
- [Error Handling](#error-handling)
- [Performance Considerations](#performance-considerations)

---

## System Architecture

### High-Level Overview

```
┌─────────────────────────────────────────────────────────────┐
│                    Strategy Layer                            │
│  ┌──────────────────────────────────────────────────────┐   │
│  │ IStrategy: Signal Generation                          │   │
│  │  • OnBar() / OnTick()                                 │   │
│  │  • Strategy-specific logic only                       │   │
│  └──────────────────────────────────────────────────────┘   │
└────────────────────────┬────────────────────────────────────┘
                         │ StrategyIntent
                         ↓
┌─────────────────────────────────────────────────────────────┐
│                      Risk Layer                              │
│  ┌──────────────────────────────────────────────────────┐   │
│  │ IRiskManager: Multi-Tier Validation                   │   │
│  │  • Tier 1: Daily limits, position limits              │   │
│  │  • Tier 2: Weekly limits, trailing drawdown          │   │
│  │  • Tier 3: Exposure, correlation, time windows       │   │
│  └──────────────────────────────────────────────────────┘   │
└────────────────────────┬────────────────────────────────────┘
                         │ RiskDecision
                         ↓
┌─────────────────────────────────────────────────────────────┐
│                     Sizing Layer                             │
│  ┌──────────────────────────────────────────────────────┐   │
│  │ IPositionSizer: Contract Quantity Calculation         │   │
│  │  • Fixed contracts / Fixed dollar risk                │   │
│  │  • Optimal-f (Ralph Vince)                            │   │
│  │  • Volatility-adjusted (ATR/StdDev)                   │   │
│  └──────────────────────────────────────────────────────┘   │
└────────────────────────┬────────────────────────────────────┘
                         │ SizingResult
                         ↓
┌─────────────────────────────────────────────────────────────┐
│                    OMS Layer                                 │
│  ┌──────────────────────────────────────────────────────┐   │
│  │ IOrderManager: Order Lifecycle Management             │   │
│  │  • State Machine: Pending → Working → Filled          │   │
│  │  • Partial fills, modifications, cancellations        │   │
│  │  • Position reconciliation                            │   │
│  └──────────────────────────────────────────────────────┘   │
└────────────────────────┬────────────────────────────────────┘
                         │ OrderRequest
                         ↓
┌─────────────────────────────────────────────────────────────┐
│                   NT8 Adapter Layer                          │
│  ┌──────────────────────────────────────────────────────┐   │
│  │ INT8OrderAdapter: Platform Integration                │   │
│  │  • Data conversion (NT8 ↔ SDK)                        │   │
│  │  • Order submission to NT8                            │   │
│  │  • Fill/update callbacks                              │   │
│  └──────────────────────────────────────────────────────┘   │
└────────────────────────┬────────────────────────────────────┘
                         │
                         ↓
                 ┌───────────────┐
                 │ NinjaTrader 8 │
                 └───────────────┘
```

---

## Component Design

### Strategy Component

**Purpose:** Generate trading signals based on market data

**Design Principles:**
- Strategies are **pure signal generators**
- No direct access to order management or risk
- Stateful but isolated
- Deterministic for backtesting

**Interface:**
```csharp
public interface IStrategy
{
    StrategyIntent? OnBar(BarData bar, StrategyContext context);
}
```

**Key Characteristics:**
- Receives market data and context
- Returns trading intent (or null)
- No side effects outside internal state
- All infrastructure handled by SDK

**Example Implementation:**
```csharp
public class SimpleORBStrategy : IStrategy
{
    private double _orbHigh, _orbLow;
    private bool _orbComplete;
    
    public StrategyIntent? OnBar(BarData bar, StrategyContext context)
    {
        // Update ORB during formation
        if (!_orbComplete && IsORBPeriod(bar.Time))
        {
            UpdateORB(bar);
            return null;
        }
        
        // Generate signal after ORB complete
        if (_orbComplete && bar.Close > _orbHigh)
        {
            return new StrategyIntent(/* long signal */);
        }
        
        return null;
    }
}
```

---

### Risk Management Component

**Purpose:** Validate all trading decisions against risk parameters

**Architecture:**

```
BasicRiskManager (Tier 1)
    ├─ Daily loss limits
    ├─ Per-trade risk caps
    ├─ Position count limits
    └─ Emergency flatten
         ↓ wraps
AdvancedRiskManager (Tiers 2-3)
    ├─ Weekly rolling limits (Tier 2)
    ├─ Trailing drawdown (Tier 2)
    ├─ Cross-strategy exposure (Tier 3)
    ├─ Correlation limits (Tier 3)
    └─ Time-based windows (Tier 3)
```

**Tier Classification:**

| Tier | Purpose | Scope |
|------|---------|-------|
| **Tier 1** | Core capital protection | Single account, single day |
| **Tier 2** | Extended protection | Multi-day, drawdown |
| **Tier 3** | Portfolio management | Cross-strategy, correlation |

**Validation Flow:**
```csharp
public RiskDecision ValidateOrder(StrategyIntent intent, StrategyContext context, RiskConfig config)
{
    // 1. Check Tier 1 (via BasicRiskManager)
    var tier1 = _basicRiskManager.ValidateOrder(intent, context, config);
    if (!tier1.Allow) return tier1;
    
    // 2. Check Tier 2
    if (IsWeeklyLimitBreached()) return Reject("Weekly limit");
    if (IsDrawdownExceeded()) return Reject("Drawdown limit");
    
    // 3. Check Tier 3
    if (IsExposureLimitBreached()) return Reject("Exposure limit");
    if (IsCorrelationTooHigh()) return Reject("Correlation limit");
    
    return Allow();
}
```

**State Management:**
- Thread-safe with locks
- Weekly window: 7-day rolling P&L tracking
- Peak equity: Updated on every P&L update
- Exposure tracking: Per-symbol aggregation
- Correlation matrix: Dynamic updates

---

### Position Sizing Component

**Purpose:** Calculate optimal contract quantities

**Architecture:**

```
BasicPositionSizer
    ├─ Fixed Contracts
    └─ Fixed Dollar Risk
         ↓ extended by
AdvancedPositionSizer
    ├─ OptimalFCalculator
    │   ├─ Historical trade analysis
    │   ├─ Risk of ruin calculation
    │   └─ Optimal leverage
    ├─ VolatilityAdjustedSizer
    │   ├─ ATR-based sizing
    │   ├─ StdDev-based sizing
    │   └─ Regime detection
    └─ Dollar-Risk Override
        ├─ Rounding modes
        └─ Contract constraints
```

**Sizing Methods:**

#### Fixed Contracts
Simplest method - always trade the same quantity.

```csharp
Contracts = ConfiguredContracts
```

#### Fixed Dollar Risk
Target specific dollar risk per trade.

```csharp
Contracts = TargetRisk / (StopTicks × TickValue)
```

#### Optimal-f (Ralph Vince)
Maximize geometric growth rate.

```csharp
f* = (Win% × AvgWin - Loss% × AvgLoss) / AvgWin
Contracts = (Capital × f*) / RiskPerContract
```

**Considerations:**
- Requires historical trade data
- Includes risk of ruin check
- Conservative approach recommended

#### Volatility-Adjusted
Scale position size based on market volatility.

```csharp
BaseSize = TargetRisk / (ATR × TickValue)
AdjustedSize = BaseSize × (NormalATR / CurrentATR)
```

**Volatility Regimes:**
- **Low:** CurrentATR < 0.8 × NormalATR → Increase size
- **Normal:** 0.8 ≤ ratio ≤ 1.2 → Standard size
- **High:** CurrentATR > 1.2 × NormalATR → Reduce size

---

### Order Management Component

**Purpose:** Manage complete order lifecycle

**State Machine:**

```
        SubmitOrder()
              ↓
         ┌─────────┐
         │ Pending │
         └────┬────┘
              │ NT8 Accepts
              ↓
         ┌─────────┐
         │ Working │────────→ CancelOrder() → Cancelled
         └────┬────┘
              │ Partial Fill
              ↓
    ┌──────────────────┐
    │ PartiallyFilled  │──→ More Fills
    └────┬─────────────┘     ↓
         │ Complete         Back to PartiallyFilled
         ↓                   or
    ┌─────────┐             ↓
    │ Filled  │         ┌─────────┐
    └─────────┘         │ Filled  │
                        └─────────┘
    
    ┌──────────┐
    │ Rejected │ ← NT8 Rejects at any point
    └──────────┘
```

**State Transitions:**

| From | To | Trigger | Validation |
|------|----|---------|-----------| 
| `Pending` | `Working` | NT8 accepts | Auto |
| `Pending` | `Rejected` | NT8 rejects | Auto |
| `Working` | `PartiallyFilled` | First partial fill | FilledQty < TotalQty |
| `Working` | `Filled` | Complete fill | FilledQty == TotalQty |
| `Working` | `Cancelled` | Cancel request | Must be working |
| `PartiallyFilled` | `Filled` | Final fill | FilledQty == TotalQty |
| `PartiallyFilled` | `Cancelled` | Cancel remainder | Allowed |

**Thread Safety:**
```csharp
private readonly Dictionary<string, OrderStatus> _orders;
private readonly object _lock = new object();

public OrderStatus? GetOrderStatus(string orderId)
{
    lock (_lock)
    {
        return _orders.TryGetValue(orderId, out var status) ? status : null;
    }
}
```

**Event Notifications:**
```csharp
private readonly List<Action<OrderStatus>> _callbacks;

public void SubscribeToOrderUpdates(Action<OrderStatus> callback)
{
    lock (_lock)
    {
        _callbacks.Add(callback);
    }
}

private void NotifyOrderUpdate(OrderStatus status)
{
    List<Action<OrderStatus>> callbacks;
    lock (_lock)
    {
        callbacks = new List<Action<OrderStatus>>(_callbacks);
    }
    
    // Raise events outside lock
    foreach (var callback in callbacks)
    {
        try { callback(status); }
        catch { /* Log and continue */ }
    }
}
```

---

### NT8 Adapter Component

**Purpose:** Bridge SDK and NinjaTrader 8 platform

**Responsibilities:**
1. **Data Conversion** - NT8 ↔ SDK format conversion
2. **Order Submission** - SDK requests → NT8 orders
3. **Event Handling** - NT8 callbacks → SDK notifications
4. **Error Translation** - NT8 errors → SDK exceptions

**Data Conversion Example:**
```csharp
public class NT8DataConverter
{
    public static BarData ConvertBar(/* NT8 bar parameters */)
    {
        return new BarData(
            symbol: Instrument.MasterInstrument.Name,
            time: Time[0],
            open: Open[0],
            high: High[0],
            low: Low[0],
            close: Close[0],
            volume: Volume[0],
            barSize: TimeSpan.FromMinutes(BarsPeriod.Value)
        );
    }
    
    public static Position ConvertPosition(/* NT8 position */)
    {
        return new Position(
            symbol: Instrument.MasterInstrument.Name,
            quantity: Position.Quantity,
            averagePrice: Position.AveragePrice,
            unrealizedPnL: Position.GetUnrealizedProfitLoss(PerformanceUnit.Currency),
            realizedPnL: SystemPerformance.AllTrades.TradesPerformance.Currency.CumProfit,
            lastUpdate: DateTime.UtcNow
        );
    }
}
```

**Order Submission Flow:**
```
SDK OrderRequest
    ↓ convert
NT8 Order Parameters
    ↓ submit
NT8 EnterLong() / EnterShort()
    ↓ callback
NT8 OnOrderUpdate()
    ↓ convert
SDK OrderStatus
    ↓ notify
Strategy Callbacks
```

---

## Data Flow

### Complete Trading Flow

```
1. Market Data Arrives
   │
   ├─ NT8: OnBarUpdate()
   │   ↓
   ├─ Adapter: Convert to BarData
   │   ↓
   ├─ Strategy: OnBar(BarData, StrategyContext)
   │   ↓
   ├─ Returns: StrategyIntent?
   │
2. Intent Validation (if intent != null)
   │
   ├─ Risk: ValidateOrder(intent, context, config)
   │   ├─ Tier 1 checks
   │   ├─ Tier 2 checks
   │   └─ Tier 3 checks
   │   ↓
   ├─ Returns: RiskDecision
   │   ├─ If rejected: Log and return
   │   └─ If approved: Continue
   │
3. Position Sizing
   │
   ├─ Sizer: CalculateSize(intent, context, config)
   │   ├─ Method-specific calculation
   │   ├─ Apply constraints
   │   └─ Round contracts
   │   ↓
   ├─ Returns: SizingResult
   │
4. Order Submission
   │
   ├─ OMS: SubmitOrderAsync(OrderRequest)
   │   ├─ Create order record
   │   ├─ State = Pending
   │   └─ Delegate to adapter
   │   ↓
   ├─ Adapter: SubmitToNT8(request)
   │   ├─ Convert to NT8 format
   │   ├─ EnterLong() / EnterShort()
   │   └─ Set stops/targets
   │   ↓
   ├─ Returns: OrderId
   │
5. Order Updates (async)
   │
   ├─ NT8: OnOrderUpdate()
   │   ↓
   ├─ Adapter: Convert to OrderStatus
   │   ↓
   ├─ OMS: OnOrderUpdate(status)
   │   ├─ Update state machine
   │   ├─ Update position tracker
   │   └─ Notify subscribers
   │   ↓
   ├─ Risk: OnFill(fill) [if filled]
   │   └─ Update P&L tracking
   │
6. Position Monitoring
   │
   ├─ NT8: OnPositionUpdate()
   │   ↓
   ├─ Adapter: Convert to Position
   │   ↓
   ├─ Risk: OnPnLUpdate(netPnL, dayPnL)
   │   ├─ Check daily limits
   │   ├─ Check weekly limits
   │   ├─ Update drawdown
   │   └─ Trigger alerts if needed
```

---

## Threading Model

### Thread Safety Strategy

**Principle:** All shared state protected by locks

**Shared State Identification:**
- Dictionaries (orders, positions, P&L tracking)
- Lists (callbacks, history)
- Mutable fields (counters, accumulators)

**Lock Pattern:**
```csharp
private readonly object _lock = new object();

// Read operation
public TValue GetValue(TKey key)
{
    lock (_lock)
    {
        return _dictionary.TryGetValue(key, out var value) ? value : default;
    }
}

// Write operation
public void SetValue(TKey key, TValue value)
{
    lock (_lock)
    {
        _dictionary[key] = value;
    }
}

// Complex operation
public void ComplexOperation()
{
    lock (_lock)
    {
        // Multiple operations under single lock
        var value = _dictionary[key];
        value = Transform(value);
        _dictionary[key] = value;
        _counter++;
    }
}
```

**Event Notification Pattern:**
```csharp
public void NotifySubscribers(TEventData data)
{
    List<Action<TEventData>> callbacks;
    
    // Copy callbacks under lock
    lock (_lock)
    {
        callbacks = new List<Action<TEventData>>(_callbacks);
    }
    
    // Raise events outside lock to prevent deadlocks
    foreach (var callback in callbacks)
    {
        try
        {
            callback(data);
        }
        catch (Exception ex)
        {
            _logger.LogError("Callback error: {0}", ex.Message);
            // Continue with other callbacks
        }
    }
}
```

### Threading Scenarios

**Scenario 1: Concurrent Strategy Execution**
- Multiple strategies call risk/sizing simultaneously
- Each component has own lock
- No shared state between strategies
- Result: Safe concurrent execution

**Scenario 2: Order Updates During Validation**
- Strategy validates order (holds risk lock)
- NT8 callback updates P&L (needs risk lock)
- Result: Callback waits for validation to complete
- Performance: <1ms typical lock contention

**Scenario 3: Emergency Flatten During Trading**
- Multiple strategies active
- EmergencyFlatten() called
- Result: All new orders rejected, existing orders cancelled
- Thread-safe state transition

---

## State Management

### Risk Manager State

```csharp
private class RiskState
{
    // Tier 1
    public double DailyPnL { get; set; }
    public bool TradingHalted { get; set; }
    
    // Tier 2
    public Queue<DailyPnL> WeeklyWindow { get; set; }  // 7 days
    public double PeakEquity { get; set; }
    public double CurrentEquity { get; set; }
    
    // Tier 3
    public Dictionary<string, double> SymbolExposure { get; set; }
    public CorrelationMatrix Correlations { get; set; }
    
    // All protected by _lock
}
```

**State Updates:**
- **Daily Reset:** Midnight UTC, clear daily P&L
- **Weekly Rollover:** Monday, drop oldest day
- **Peak Update:** On every positive P&L update
- **Exposure Update:** On every fill

### Order Manager State

```csharp
private class OrderManagerState
{
    public Dictionary<string, OrderStatus> Orders { get; set; }
    public Dictionary<string, List<OrderFill>> Fills { get; set; }
    public Dictionary<string, Position> Positions { get; set; }
    
    // State history for auditability
    public List<StateTransition> TransitionHistory { get; set; }
    
    // All protected by _lock
}
```

**State Persistence:**
- In-memory only (current implementation)
- Future: Optional database persistence
- Replay: State reconstructable from event log

---

## Error Handling

### Error Categories

**Level 1: Validation Errors**
- Expected during normal operation
- Example: Risk limit exceeded
- Handling: Return error result, log at Info/Warning

**Level 2: Operational Errors**
- Recoverable issues
- Example: Network timeout, order rejection
- Handling: Log error, retry if appropriate, notify user

**Level 3: System Errors**
- Unexpected critical issues
- Example: Null reference, state corruption
- Handling: Log critical, emergency flatten, halt trading

### Error Handling Pattern

```csharp
public ReturnType PublicMethod(Type parameter)
{
    // 1. Parameter validation
    if (parameter == null)
        throw new ArgumentNullException(nameof(parameter));
    
    if (!IsValid(parameter))
        throw new ArgumentException("Invalid parameter", nameof(parameter));
    
    try
    {
        // 2. Main logic
        return Implementation(parameter);
    }
    catch (ExpectedException ex)
    {
        // 3. Expected errors
        _logger.LogWarning("Expected error: {0}", ex.Message);
        return DefaultValue;
    }
    catch (Exception ex)
    {
        // 4. Unexpected errors
        _logger.LogError("Unexpected error in {0}: {1}", nameof(PublicMethod), ex.Message);
        throw;  // Re-throw for caller to handle
    }
}
```

### Circuit Breaker Pattern

```csharp
private int _consecutiveErrors = 0;
private const int MaxConsecutiveErrors = 5;

public RiskDecision ValidateOrder(StrategyIntent intent, StrategyContext context, RiskConfig config)
{
    try
    {
        var result = ValidateOrderInternal(intent, context, config);
        _consecutiveErrors = 0;  // Reset on success
        return result;
    }
    catch (Exception ex)
    {
        _consecutiveErrors++;
        
        if (_consecutiveErrors >= MaxConsecutiveErrors)
        {
            _logger.LogCritical("Circuit breaker triggered: {0} consecutive errors", _consecutiveErrors);
            _ = EmergencyFlatten("Circuit breaker");
        }
        
        throw;
    }
}
```

---

## Performance Considerations

### Latency Targets

| Component | Target | Achieved | Criticality |
|-----------|--------|----------|-------------|
| Risk Validation | <5ms | <3ms | High |
| Position Sizing | <3ms | <2ms | Medium |
| Order Submission | <10ms | <8ms | High |
| State Update | <1ms | <0.5ms | Medium |
| **Total Tick-to-Trade** | **<200ms** | **<150ms** | **Critical** |

### Optimization Techniques

**1. Lock Granularity**
```csharp
// Bad: Single lock for everything
private readonly object _globalLock = new object();

// Good: Separate locks for independent state
private readonly object _ordersLock = new object();
private readonly object _positionsLock = new object();
private readonly object _pnlLock = new object();
```

**2. Copy-on-Read for Collections**
```csharp
// Minimize lock duration
public List<OrderStatus> GetActiveOrders()
{
    lock (_lock)
    {
        return _orders.Values
            .Where(o => IsActive(o.State))
            .ToList();  // Copy under lock
    }
    // Processing happens outside lock
}
```

**3. Lazy Initialization**
```csharp
private OptimalFCalculator _calculator;
private readonly object _calculatorLock = new object();

private OptimalFCalculator GetCalculator()
{
    if (_calculator == null)
    {
        lock (_calculatorLock)
        {
            if (_calculator == null)  // Double-check
            {
                _calculator = new OptimalFCalculator(_logger);
            }
        }
    }
    return _calculator;
}
```

**4. String Formatting**
```csharp
// C# 5.0 compliant, minimal allocations
_logger.LogDebug("Order {0}: {1} {2} @ {3:F2}",
    orderId, side, quantity, price);
```

**5. Avoid LINQ in Hot Paths**
```csharp
// Bad: LINQ in critical path
var activeOrders = _orders.Values.Where(o => o.State == OrderState.Working).Count();

// Good: Direct iteration
int activeCount = 0;
foreach (var order in _orders.Values)
{
    if (order.State == OrderState.Working)
        activeCount++;
}
```

### Memory Management

**Avoid Allocations in Hot Paths:**
```csharp
// Reuse dictionaries for metadata
private readonly Dictionary<string, object> _reuseableMetadata = new Dictionary<string, object>();

public RiskDecision ValidateOrder(...)
{
    lock (_lock)
    {
        _reuseableMetadata.Clear();
        _reuseableMetadata["daily_pnl"] = _dailyPnL;
        _reuseableMetadata["limit"] = config.DailyLossLimit;
        
        return new RiskDecision(allow, reason, null, level, _reuseableMetadata);
    }
}
```

**Object Pooling for Events:**
```csharp
// Future optimization: Pool frequently-created objects
private readonly ObjectPool<OrderStatus> _statusPool;

public OrderStatus CreateOrderStatus(...)
{
    var status = _statusPool.Get();
    status.OrderId = orderId;
    // ... populate
    return status;
}
```

---

## Design Patterns Used

### Strategy Pattern
- Multiple risk managers (Basic, Advanced)
- Multiple position sizers (Basic, Advanced)
- Pluggable strategies

### State Machine Pattern
- Order lifecycle management
- Risk mode transitions
- Defined states and transitions

### Observer Pattern
- Order update subscriptions
- Event notifications
- Callback registration

### Facade Pattern
- Simple SDK interface hiding complexity
- Unified entry point for trading operations

### Template Method Pattern
- BaseRiskManager with extension points
- BasePositionSizer with method overrides

### Factory Pattern
- Strategy creation
- Component initialization

---

## Future Architecture Considerations

### Phase 3: Market Microstructure
- Add liquidity monitoring component
- Execution quality tracker
- Smart order routing

### Phase 4: Intelligence & Grading
- Confluence scoring engine
- Regime detection system
- ML model integration

### Phase 5: Analytics
- Performance attribution engine
- Trade analytics pipeline
- Portfolio optimization

### Phase 6: Production Hardening
- High availability setup
- Disaster recovery
- Enhanced monitoring

---

**For implementation details, see [API Reference](API_REFERENCE.md)**  
**For usage examples, see [README](README.md)**
