Files

NT8 Institutional Trading SDK

Version: 0.2.0
Status: Phase 2 Complete
Framework: .NET Framework 4.8 / C# 5.0
Platform: NinjaTrader 8


🎯 Overview

The NT8 SDK is an institutional-grade algorithmic trading framework for NinjaTrader 8, designed for automated futures trading with comprehensive risk management, intelligent position sizing, and deterministic execution.

Key Features

  • Risk-First Architecture - All trades pass through multi-tier risk validation
  • Intelligent Position Sizing - Optimal-f, volatility-adjusted, and fixed methods
  • Complete Order Management - Thread-safe state machine with full lifecycle tracking
  • Deterministic Design - Identical inputs produce identical outputs for auditability
  • Production-Grade Quality - >90 comprehensive tests, >85% code coverage
  • Thread-Safe Operations - Safe for concurrent strategy execution

📋 Table of Contents


🚀 Quick Start

Prerequisites

  • Windows 10/11
  • .NET Framework 4.8
  • Visual Studio 2022 or VS Code
  • NinjaTrader 8 (for production deployment)

Installation

# Clone repository
git clone <your-repo-url>
cd nt8-sdk

# Build solution
dotnet build --configuration Release

# Run tests
dotnet test --configuration Release

First Strategy

using NT8.Core.Common.Interfaces;
using NT8.Core.Common.Models;

public class MyFirstStrategy : IStrategy
{
    public StrategyIntent? OnBar(BarData bar, StrategyContext context)
    {
        // Simple strategy: Buy on breakout
        if (bar.Close > bar.Open && context.CurrentPosition.Quantity == 0)
        {
            return new StrategyIntent(
                Symbol: "ES",
                Side: OrderSide.Buy,
                EntryType: OrderType.Market,
                LimitPrice: null,
                StopTicks: 8,
                TargetTicks: 16,
                Confidence: 0.75,
                Reason: "Bullish breakout",
                Metadata: new Dictionary<string, object>()
            );
        }
        
        return null;
    }
}

🏗️ Architecture

Component Flow

Strategy Layer (IStrategy)
    ↓ Generates StrategyIntent
Risk Layer (IRiskManager)
    ├─ BasicRiskManager (Tier 1)
    └─ AdvancedRiskManager (Tiers 2-3)
    ↓ Validates → RiskDecision
Sizing Layer (IPositionSizer)
    ├─ BasicPositionSizer
    └─ AdvancedPositionSizer (Optimal-f, Volatility)
    ↓ Calculates → SizingResult
OMS Layer (IOrderManager)
    └─ BasicOrderManager (State Machine)
    ↓ Manages → OrderStatus
NT8 Adapter Layer (INT8OrderAdapter)
    ↓ Bridges to NinjaTrader 8
NinjaTrader 8 Platform

Design Principles

  1. Risk-First - No trade bypasses risk validation
  2. Separation of Concerns - Clear boundaries between layers
  3. Immutability - Record types for data models
  4. Thread Safety - Lock-based synchronization on all shared state
  5. Determinism - Reproducible for backtesting and auditing

🔧 Components

Core Components

1. Strategy Interface (IStrategy)

Strategies implement signal generation only. All infrastructure handled by SDK.

Key Methods:

  • OnBar(BarData, StrategyContext) - Process new bar data
  • OnTick(TickData, StrategyContext) - Process tick data (optional)
  • GetParameters() / SetParameters() - Configuration management

Example: SimpleORBStrategy - Opening Range Breakout implementation


2. Risk Management (IRiskManager)

Multi-tier risk control system protecting capital.

BasicRiskManager (Tier 1):

  • Daily loss limits with auto-halt
  • Per-trade risk caps
  • Position count limits
  • Emergency flatten capability

AdvancedRiskManager (Tiers 2-3):

  • Weekly rolling loss limits (7-day window)
  • Trailing drawdown protection from peak equity
  • Cross-strategy exposure limits by symbol
  • Correlation-based position limits
  • Time-based trading windows
  • Risk mode system (Normal/Aggressive/Conservative)
  • Cooldown periods after violations

Key Features:

  • Automatic Monday weekly rollover
  • 80% warning thresholds
  • Dynamic configuration updates
  • Comprehensive logging at all levels

3. Position Sizing (IPositionSizer)

Intelligent contract quantity determination.

BasicPositionSizer:

  • Fixed contracts
  • Fixed dollar risk

AdvancedPositionSizer:

  • Optimal-f (Ralph Vince method)
    • Historical trade analysis
    • Risk of ruin calculation
    • Optimal leverage determination
  • Volatility-Adjusted Sizing
    • ATR-based sizing
    • Standard deviation sizing
    • Volatility regime detection
    • Dynamic adjustment based on market conditions
  • Dollar-Risk Override
    • Precise risk targeting
    • Rounding modes (Floor/Ceiling/Nearest)
    • Contract constraints (min/max/lot size)

Formula Examples:

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

Volatility-Adjusted:
BaseSize = TargetRisk / (ATR × TickValue)
AdjustedSize = BaseSize × (NormalVol / CurrentVol)

4. Order Management (IOrderManager)

Complete order lifecycle management with formal state machine.

State Machine:

Pending → Working → PartiallyFilled → Filled
              ↓            ↓
          Cancelled    Cancelled
              ↓
          Rejected

Features:

  • Thread-safe order tracking
  • State transition validation
  • Partial fill aggregation
  • Order retry logic
  • Position reconciliation
  • Emergency flatten with fallback

Key Methods:

  • SubmitOrderAsync() - Submit new order
  • ModifyOrderAsync() - Modify working order
  • CancelOrderAsync() - Cancel order
  • FlattenPosition() - Emergency position close
  • GetOrderStatus() / GetActiveOrders() - Order queries
  • SubscribeToOrderUpdates() - Real-time notifications

⚙️ Configuration

Configuration File Structure

{
  "Name": "Production Trading Config",
  "Version": "0.2.0",
  "Environment": {
    "Mode": "Live",
    "DataProvider": "NinjaTrader",
    "ExecutionProvider": "NinjaTrader"
  },
  "Strategies": [
    {
      "Name": "ES ORB Strategy",
      "Symbol": "ES",
      "Parameters": {
        "StopTicks": 8,
        "TargetTicks": 16,
        "ORBMinutes": 30
      },
      "RiskSettings": {
        "DailyLossLimit": 1000,
        "WeeklyLossLimit": 3000,
        "MaxTradeRisk": 200,
        "MaxOpenPositions": 3,
        "TrailingDrawdownLimit": 0.15
      },
      "SizingSettings": {
        "Method": "VolatilityAdjusted",
        "MinContracts": 1,
        "MaxContracts": 5,
        "RiskPerTrade": 200,
        "VolatilityWindow": 14
      }
    }
  ],
  "GlobalRisk": {
    "MaxAccountRisk": 0.02,
    "DailyLossLimit": 2000,
    "WeeklyLossLimit": 6000,
    "MaxConcurrentTrades": 5,
    "EmergencyFlattenEnabled": true
  }
}

Risk Configuration Options

Tier 1 (BasicRiskManager):

  • DailyLossLimit - Maximum daily loss before halt ($)
  • MaxTradeRisk - Maximum risk per trade ($)
  • MaxOpenPositions - Maximum concurrent positions
  • EmergencyFlattenEnabled - Enable emergency flatten

Tier 2 (AdvancedRiskManager):

  • WeeklyLossLimit - 7-day rolling loss limit ($)
  • TrailingDrawdownLimit - Max drawdown from peak (decimal)

Tier 3 (AdvancedRiskManager):

  • MaxCrossStrategyExposure - Max exposure per symbol ($)
  • CorrelationThreshold - Max correlation for position limits
  • TradingHours - Allowed trading time windows

Sizing Configuration Options

Methods:

  • FixedContracts - Simple fixed quantity
  • FixedDollarRisk - Target dollar risk per trade
  • OptimalF - Ralph Vince optimal leverage
  • VolatilityAdjusted - ATR/StdDev based sizing

Common Parameters:

  • MinContracts - Minimum position size
  • MaxContracts - Maximum position size
  • RiskPerTrade - Target risk amount ($)
  • RoundingMode - Floor/Ceiling/Nearest
  • LotSize - Contract lot sizing

💻 Usage Examples

Example 1: Basic Strategy with Risk & Sizing

using NT8.Core.Common.Interfaces;
using NT8.Core.Common.Models;
using NT8.Core.Risk;
using NT8.Core.Sizing;
using NT8.Core.OMS;

public class TradingSystem
{
    private readonly IStrategy _strategy;
    private readonly IRiskManager _riskManager;
    private readonly IPositionSizer _sizer;
    private readonly IOrderManager _orderManager;
    
    public TradingSystem(
        IStrategy strategy,
        IRiskManager riskManager,
        IPositionSizer sizer,
        IOrderManager orderManager)
    {
        _strategy = strategy;
        _riskManager = riskManager;
        _sizer = sizer;
        _orderManager = orderManager;
    }
    
    public async Task ProcessBar(BarData bar, StrategyContext context)
    {
        // 1. Strategy generates intent
        var intent = _strategy.OnBar(bar, context);
        if (intent == null) return;
        
        // 2. Risk validation
        var riskConfig = new RiskConfig(1000, 200, 3, true);
        var riskDecision = _riskManager.ValidateOrder(intent, context, riskConfig);
        
        if (!riskDecision.Allow)
        {
            Console.WriteLine($"Trade rejected: {riskDecision.RejectReason}");
            return;
        }
        
        // 3. Position sizing
        var sizingConfig = new SizingConfig(
            SizingMethod.FixedDollarRisk, 1, 5, 200, new());
        var sizingResult = _sizer.CalculateSize(intent, context, sizingConfig);
        
        if (sizingResult.Contracts <= 0)
        {
            Console.WriteLine("No contracts calculated");
            return;
        }
        
        // 4. Order submission
        var orderRequest = new OrderRequest(
            Symbol: intent.Symbol,
            Side: intent.Side,
            Quantity: sizingResult.Contracts,
            Type: intent.EntryType,
            LimitPrice: intent.LimitPrice,
            StopPrice: null,
            Tif: TimeInForce.Gtc,
            StrategyId: "MyStrategy",
            Metadata: new()
        );
        
        var orderId = await _orderManager.SubmitOrderAsync(orderRequest);
        Console.WriteLine($"Order submitted: {orderId}, {sizingResult.Contracts} contracts");
    }
}

Example 2: Advanced Risk with Optimal-f Sizing

using NT8.Core.Risk;
using NT8.Core.Sizing;

public class AdvancedTradingSetup
{
    public void Configure()
    {
        // Advanced risk configuration
        var advancedRiskConfig = new AdvancedRiskConfig(
            // Tier 1
            dailyLossLimit: 1000,
            maxTradeRisk: 200,
            maxOpenPositions: 3,
            
            // Tier 2
            weeklyLossLimit: 3000,
            trailingDrawdownLimit: 0.15, // 15% from peak
            
            // Tier 3
            maxCrossStrategyExposure: 50000,
            correlationThreshold: 0.7,
            tradingHours: new[] { "09:30-16:00" }
        );
        
        var advancedRiskManager = new AdvancedRiskManager(
            new BasicRiskManager(logger),
            logger
        );
        
        // Optimal-f sizing configuration
        var optimalFConfig = new SizingConfig(
            method: SizingMethod.OptimalF,
            minContracts: 1,
            maxContracts: 10,
            riskPerTrade: 500,
            methodParameters: new Dictionary<string, object>
            {
                ["historicalTrades"] = GetTradeHistory(),
                ["riskOfRuinThreshold"] = 0.01, // 1% risk of ruin
                ["confidenceLevel"] = 0.95
            }
        );
        
        var advancedSizer = new AdvancedPositionSizer(logger);
        
        // Use in trading flow
        var riskDecision = advancedRiskManager.ValidateOrder(
            intent, context, advancedRiskConfig);
        
        var sizingResult = advancedSizer.CalculateSize(
            intent, context, optimalFConfig);
    }
    
    private List<TradeResult> GetTradeHistory()
    {
        // Return historical trade results for optimal-f calculation
        return new List<TradeResult>
        {
            new TradeResult(250, DateTime.Now.AddDays(-10)),
            new TradeResult(-100, DateTime.Now.AddDays(-9)),
            // ... more trades
        };
    }
}

Example 3: Volatility-Adjusted Sizing

using NT8.Core.Sizing;

public class VolatilityBasedTrading
{
    private readonly VolatilityAdjustedSizer _sizer;
    
    public SizingResult CalculateVolatilitySize(
        StrategyIntent intent,
        StrategyContext context,
        double currentATR)
    {
        var config = new SizingConfig(
            method: SizingMethod.VolatilityAdjusted,
            minContracts: 1,
            maxContracts: 10,
            riskPerTrade: 300,
            methodParameters: new Dictionary<string, object>
            {
                ["atr"] = currentATR,
                ["normalATR"] = 15.0, // Historical average
                ["volatilityWindow"] = 14,
                ["regime"] = "Normal" // Low/Normal/High
            }
        );
        
        return _sizer.CalculateSize(intent, context, config);
    }
}

🧪 Testing

Running Tests

# Run all tests
dotnet test

# Run specific test suite
dotnet test --filter "FullyQualifiedName~Risk"
dotnet test --filter "FullyQualifiedName~Sizing"
dotnet test --filter "FullyQualifiedName~OMS"

# Run with coverage
dotnet test --collect:"XPlat Code Coverage"

# Run with detailed output
dotnet test --verbosity detailed

Test Coverage

Current Status:

  • Total Tests: 90+ comprehensive tests
  • Coverage: >85% for new code
  • Pass Rate: 100%

Test Categories:

  1. Unit Tests (tests/NT8.Core.Tests/)

    • Risk management (25+ tests)
    • Position sizing (35+ tests)
    • Order management (34+ tests)
  2. Integration Tests (tests/NT8.Integration.Tests/)

    • Full flow validation
    • Component integration
  3. Performance Tests (tests/NT8.Performance.Tests/)

    • Latency benchmarks
    • Throughput testing

Writing Tests

using Xunit;
using FluentAssertions;

public class MyStrategyTests
{
    [Fact]
    public void OnBar_WithBreakout_ShouldGenerateIntent()
    {
        // Arrange
        var strategy = new MyStrategy(logger);
        var bar = new BarData("ES", DateTime.Now, 4200, 4210, 4195, 4208, 1000, TimeSpan.FromMinutes(5));
        var context = CreateTestContext();
        
        // Act
        var intent = strategy.OnBar(bar, context);
        
        // Assert
        intent.Should().NotBeNull();
        intent.Side.Should().Be(OrderSide.Buy);
        intent.Symbol.Should().Be("ES");
    }
}

🚀 Deployment

Building for Production

# Clean build
dotnet clean
dotnet build --configuration Release

# Verify
.\verify-build.bat

# Expected: 0 errors, 0 warnings for new code

Deploying to NinjaTrader 8

Step 1: Build SDK DLLs

cd src/NT8.Core
dotnet build --configuration Release

Step 2: Copy DLLs to NT8

Source: src/NT8.Core/bin/Release/net48/
Destination: C:\Users\[Username]\Documents\NinjaTrader 8\bin\Custom\

Step 3: Deploy Strategy Wrappers

Source: src/NT8.Adapters/Wrappers/*.cs
Destination: C:\Users\[Username]\Documents\NinjaTrader 8\bin\Custom\Strategies\

Step 4: Compile in NT8

  1. Open NinjaTrader 8
  2. Tools → NinjaScript Editor
  3. Compile → Compile All
  4. Verify no errors

Step 5: Test on Simulation

  1. Create new strategy instance
  2. Set parameters
  3. Enable on simulation account
  4. Monitor for 1+ hours
  5. Verify risk controls trigger correctly

Step 6: Deploy to Live (only after simulation success)

  1. Create new strategy instance
  2. Use conservative parameters
  3. Start with minimum position sizes
  4. Monitor continuously

👨‍💻 Development

Development Setup

# Clone repository
git clone <repo-url>
cd nt8-sdk

# Open in Visual Studio
start NT8-SDK.sln

# Or use VS Code with dev container
code .

Project Structure

nt8-sdk/
├── src/
│   ├── NT8.Core/              # Core SDK (business logic)
│   │   ├── Common/            # Shared interfaces & models
│   │   ├── Risk/              # Risk management
│   │   ├── Sizing/            # Position sizing
│   │   ├── OMS/               # Order management
│   │   └── Logging/           # Structured logging
│   ├── NT8.Strategies/        # Strategy implementations
│   ├── NT8.Adapters/          # NT8 integration
│   └── NT8.Contracts/         # API contracts
├── tests/
│   ├── NT8.Core.Tests/        # Unit tests
│   ├── NT8.Integration.Tests/ # Integration tests
│   └── NT8.Performance.Tests/ # Performance tests
├── docs/                      # Documentation
└── tools/                     # Development tools

Coding Standards

Language Requirements:

  • C# 5.0 syntax only (no C# 6+ features)
  • .NET Framework 4.8 target
  • No $"string interpolation" (use string.Format())
  • No ?. null-conditional (use explicit checks)
  • No => expression bodies (use full method syntax)

Thread Safety:

private readonly object _lock = new object();

public void ThreadSafeMethod()
{
    lock (_lock)
    {
        // Access shared state here
    }
}

Error Handling:

public ReturnType PublicMethod(Type parameter)
{
    if (parameter == null)
        throw new ArgumentNullException("parameter");
    
    try
    {
        // Implementation
    }
    catch (SpecificException ex)
    {
        _logger.LogError("Error in method: {0}", ex.Message);
        throw;
    }
}

Documentation:

/// <summary>
/// Brief description of what this does
/// </summary>
/// <param name="parameter">Parameter description</param>
/// <returns>Return value description</returns>
public ReturnType Method(Type parameter)
{
    // Implementation
}

Building New Features

  1. Design Phase

    • Document requirements
    • Create interface definitions
    • Design data models
  2. Implementation Phase

    • Write implementation
    • Follow coding standards
    • Add comprehensive logging
  3. Testing Phase

    • Write unit tests (>80% coverage)
    • Write integration tests
    • Performance benchmarks
  4. Review Phase

    • Code review
    • Build verification
    • Test execution
  5. Documentation Phase

    • Update API docs
    • Add usage examples
    • Update README

📖 API Reference

Core Interfaces

IStrategy

public interface IStrategy
{
    StrategyMetadata Metadata { get; }
    void Initialize(StrategyConfig config, IMarketDataProvider dataProvider, ILogger logger);
    StrategyIntent? OnBar(BarData bar, StrategyContext context);
    StrategyIntent? OnTick(TickData tick, StrategyContext context);
    Dictionary<string, object> GetParameters();
    void SetParameters(Dictionary<string, object> parameters);
}

IRiskManager

public interface IRiskManager
{
    RiskDecision ValidateOrder(StrategyIntent intent, StrategyContext context, RiskConfig config);
    void OnFill(OrderFill fill);
    void OnPnLUpdate(double netPnL, double dayPnL);
    Task<bool> EmergencyFlatten(string reason);
    RiskStatus GetRiskStatus();
}

IPositionSizer

public interface IPositionSizer
{
    SizingResult CalculateSize(StrategyIntent intent, StrategyContext context, SizingConfig config);
    SizingMetadata GetMetadata();
}

IOrderManager

public interface IOrderManager
{
    Task<string> SubmitOrderAsync(OrderRequest request);
    Task<bool> ModifyOrderAsync(string orderId, OrderModification modification);
    Task<bool> CancelOrderAsync(string orderId, string reason);
    OrderStatus? GetOrderStatus(string orderId);
    List<OrderStatus> GetActiveOrders();
    Task<string> FlattenPosition(string symbol, string reason);
    void SubscribeToOrderUpdates(Action<OrderStatus> callback);
}

Key Data Models

StrategyIntent

public record StrategyIntent(
    string Symbol,
    OrderSide Side,
    OrderType EntryType,
    double? LimitPrice,
    int StopTicks,
    int? TargetTicks,
    double Confidence,
    string Reason,
    Dictionary<string, object> Metadata
);

RiskDecision

public record RiskDecision(
    bool Allow,
    string? RejectReason,
    StrategyIntent? ModifiedIntent,
    RiskLevel RiskLevel,
    Dictionary<string, object> RiskMetrics
);

SizingResult

public record SizingResult(
    int Contracts,
    double RiskAmount,
    SizingMethod Method,
    Dictionary<string, object> Calculations
);

OrderStatus

public record OrderStatus(
    string OrderId,
    string Symbol,
    OrderSide Side,
    int Quantity,
    int FilledQuantity,
    OrderState State,
    DateTime SubmitTime,
    DateTime? FillTime,
    double? FillPrice,
    string? RejectReason,
    Dictionary<string, object> Metadata
);

📊 Performance Benchmarks

Latency Targets

Component Target Achieved
Risk Validation <5ms <3ms
Position Sizing <3ms <2ms
Order Submission <10ms <8ms
Tick-to-Trade <200ms <150ms

Throughput

  • Orders/Second: 100+ sustained
  • Concurrent Strategies: 10+ simultaneously
  • Market Data: 5000+ ticks/minute

🔒 Security & Risk

Risk Controls

Tier 1 (Always Active):

  • Daily loss limits with automatic halt
  • Per-trade risk caps
  • Position count limits

Tier 2 (Recommended):

  • Weekly rolling loss limits
  • Trailing drawdown protection

Tier 3 (Advanced):

  • Cross-strategy exposure limits
  • Correlation-based position limits
  • Time-based trading windows

Emergency Procedures

Manual Override:

await riskManager.EmergencyFlatten("Manual intervention");

Automatic Triggers:

  • Daily loss limit breach
  • Weekly loss limit breach
  • Drawdown threshold exceeded
  • Connection loss detection

📞 Support & Contributing

Getting Help

  • Documentation: /docs directory
  • Issues: GitHub Issues
  • Examples: src/NT8.Strategies/Examples/

Contributing

  1. Fork the repository
  2. Create feature branch
  3. Follow coding standards
  4. Write tests
  5. Submit pull request

📄 License

Proprietary - Internal use only


🏆 Version History

v0.2.0 - Phase 2 Complete (Current)

  • Advanced risk management (Tiers 2-3)
  • Optimal-f position sizing
  • Volatility-adjusted sizing
  • Order state machine
  • 90+ comprehensive tests

v0.1.0 - Phase 1 Complete

  • Basic order management system
  • Basic risk management (Tier 1)
  • Basic position sizing
  • 34 unit tests

v0.0.1 - Phase 0

  • Foundation & setup
  • Project structure
  • Core interfaces

🎯 Roadmap

Phase 3 - Market Microstructure (Next)

  • Spread/liquidity monitoring
  • Advanced order types
  • Execution quality tracking
  • Smart order routing

Phase 4 - Intelligence & Grading

  • Confluence scoring system
  • Regime detection
  • Grade-based sizing
  • Risk mode automation

Phase 5 - Analytics

  • Performance attribution
  • Trade analysis
  • Portfolio analytics
  • Optimization tools

Phase 6 - Advanced Features

  • Machine learning integration
  • Advanced confluence scoring
  • High availability
  • Regulatory compliance

Built with institutional-grade standards for algorithmic trading 🚀