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
- Architecture
- Components
- Configuration
- Usage Examples
- Testing
- Deployment
- Development
- API Reference
🚀 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
- Risk-First - No trade bypasses risk validation
- Separation of Concerns - Clear boundaries between layers
- Immutability - Record types for data models
- Thread Safety - Lock-based synchronization on all shared state
- 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 dataOnTick(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 orderModifyOrderAsync()- Modify working orderCancelOrderAsync()- Cancel orderFlattenPosition()- Emergency position closeGetOrderStatus()/GetActiveOrders()- Order queriesSubscribeToOrderUpdates()- 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 positionsEmergencyFlattenEnabled- 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 limitsTradingHours- Allowed trading time windows
Sizing Configuration Options
Methods:
FixedContracts- Simple fixed quantityFixedDollarRisk- Target dollar risk per tradeOptimalF- Ralph Vince optimal leverageVolatilityAdjusted- ATR/StdDev based sizing
Common Parameters:
MinContracts- Minimum position sizeMaxContracts- Maximum position sizeRiskPerTrade- Target risk amount ($)RoundingMode- Floor/Ceiling/NearestLotSize- 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:
-
Unit Tests (
tests/NT8.Core.Tests/)- Risk management (25+ tests)
- Position sizing (35+ tests)
- Order management (34+ tests)
-
Integration Tests (
tests/NT8.Integration.Tests/)- Full flow validation
- Component integration
-
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
- Open NinjaTrader 8
- Tools → NinjaScript Editor
- Compile → Compile All
- Verify no errors
Step 5: Test on Simulation
- Create new strategy instance
- Set parameters
- Enable on simulation account
- Monitor for 1+ hours
- Verify risk controls trigger correctly
Step 6: Deploy to Live (only after simulation success)
- Create new strategy instance
- Use conservative parameters
- Start with minimum position sizes
- 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"(usestring.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
-
Design Phase
- Document requirements
- Create interface definitions
- Design data models
-
Implementation Phase
- Write implementation
- Follow coding standards
- Add comprehensive logging
-
Testing Phase
- Write unit tests (>80% coverage)
- Write integration tests
- Performance benchmarks
-
Review Phase
- Code review
- Build verification
- Test execution
-
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:
/docsdirectory - Issues: GitHub Issues
- Examples:
src/NT8.Strategies/Examples/
Contributing
- Fork the repository
- Create feature branch
- Follow coding standards
- Write tests
- 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 🚀