Production hardening: kill switch, circuit breaker, trailing stops, log level, holiday calendar
Some checks failed
Build and Test / build (push) Has been cancelled

This commit is contained in:
2026-02-24 15:00:41 -05:00
parent 0e36fe5d23
commit a87152effb
50 changed files with 12849 additions and 752 deletions

View File

@@ -1,272 +1,195 @@
# Mandatory Coding Patterns
# Coding Patterns — NT8 SDK Required Patterns
These patterns MUST be followed in all code you write for the NT8 SDK.
All code in the NT8 SDK MUST follow these patterns without exception.
## Thread Safety - Dictionary Access
---
ALL access to shared dictionaries MUST use locks.
## 1. Thread Safety — Lock Everything Shared
### ❌ WRONG - No Lock
```csharp
_activeOrders[orderId] = orderStatus; // DANGEROUS!
```
### ✅ CORRECT - With Lock
```csharp
lock (_lock)
{
_activeOrders[orderId] = orderStatus;
}
```
### Rule
Every class with shared state MUST have:
Every class with shared state must have a lock object:
```csharp
private readonly object _lock = new object();
```
Every access to shared collections MUST be inside:
Every access to shared `Dictionary`, `List`, `Queue`, or any field touched by multiple threads:
```csharp
// ❌ NEVER
_activeOrders[orderId] = status;
// ✅ ALWAYS
lock (_lock)
{
// Dictionary/List operations here
_activeOrders[orderId] = status;
}
```
## Error Handling - Try-Catch Required
ALL public methods MUST have try-catch blocks.
### ❌ WRONG - No Error Handling
### Read-then-write must be atomic
```csharp
public async Task<string> SubmitOrder(OrderRequest request)
// ❌ WRONG — race condition between check and write
if (!_orders.ContainsKey(id))
_orders[id] = newOrder;
// ✅ CORRECT
lock (_lock)
{
var orderId = GenerateOrderId();
await _nt8Adapter.SubmitToNT8(orderStatus);
return orderId;
if (!_orders.ContainsKey(id))
_orders[id] = newOrder;
}
```
### ✅ CORRECT - With Error Handling
```csharp
public async Task<string> SubmitOrder(OrderRequest request)
{
if (request == null)
throw new ArgumentNullException("request");
try
{
request.Validate();
}
catch (ArgumentException ex)
{
_logger.LogError("Order validation failed: {0}", ex.Message);
throw;
}
try
{
var orderId = GenerateOrderId();
await _nt8Adapter.SubmitToNT8(orderStatus);
return orderId;
}
catch (Exception ex)
{
_logger.LogError("Order submission failed: {0}", ex.Message);
throw;
}
}
```
---
## 2. Error Handling — Try-Catch on All Public Methods
### Pattern Template
```csharp
public ReturnType MethodName(Type parameter)
{
// 1. Validate parameters (throw ArgumentNullException/ArgumentException)
// 1. Validate parameters first
if (parameter == null)
throw new ArgumentNullException("parameter");
// 2. Try-catch for operation-specific errors
// 2. Wrap the main logic
try
{
// Main logic
// Implementation
return result;
}
catch (SpecificException ex)
{
_logger.LogError("Specific error: {0}", ex.Message);
// Handle or re-throw
_logger.LogError("Specific failure in MethodName: {0}", ex.Message);
throw;
}
catch (Exception ex)
{
_logger.LogError("Unexpected error: {0}", ex.Message);
_logger.LogError("Unexpected failure in MethodName: {0}", ex.Message);
throw;
}
}
```
## Logging - Structured and Consistent
---
Use structured logging with string.Format (NOT string interpolation).
## 3. Logging — Always string.Format, Never $""
### Log Levels
#### LogTrace - Detailed Flow
```csharp
_logger.LogTrace("Entering method {0} with parameter {1}", methodName, param);
// ❌ NEVER — C# 6 syntax, breaks NT8 compile
_logger.LogInformation($"Order {orderId} filled");
// ✅ ALWAYS
_logger.LogInformation("Order {0} filled", orderId);
_logger.LogWarning("Risk check failed for {0}: {1}", symbol, reason);
_logger.LogError("Exception in {0}: {1}", "MethodName", ex.Message);
_logger.LogCritical("Emergency flatten triggered: {0}", reason);
```
#### LogDebug - Normal Operations
### Log level guide
| Level | When to use |
|---|---|
| `LogTrace` | Entering/exiting methods, fine-grained flow |
| `LogDebug` | State reads, normal data flow |
| `LogInformation` | Important events: order submitted, filled, cancelled |
| `LogWarning` | Recoverable issues: validation failed, limit approaching |
| `LogError` | Failures: exceptions, unexpected states |
| `LogCritical` | System integrity issues: emergency flatten, data corruption |
---
## 4. Events — Never Raise Inside Locks
Raising events inside a lock causes deadlocks when event handlers acquire other locks.
```csharp
_logger.LogDebug("Order {0} state is {1}", orderId, state);
```
#### LogInformation - Important Events
```csharp
_logger.LogInformation("Order {0} submitted successfully at {1}", orderId, timestamp);
_logger.LogInformation("Order {0} filled: {1} contracts @ {2:F2}", orderId, qty, price);
```
#### LogWarning - Recoverable Issues
```csharp
_logger.LogWarning("Order validation failed: {0}", validationError);
_logger.LogWarning("Maximum active orders reached: {0}", maxOrders);
```
#### LogError - Failures
```csharp
_logger.LogError("Failed to submit order {0} to NT8: {1}", orderId, ex.Message);
_logger.LogError("Invalid state transition: {0} -> {1}", fromState, toState);
```
#### LogCritical - System Integrity Issues
```csharp
_logger.LogCritical("Emergency flatten failed for {0}: {1}", symbol, ex.Message);
```
### ❌ WRONG - String Interpolation
```csharp
_logger.LogInformation($"Order {orderId} submitted"); // C# 6+ feature!
```
### ✅ CORRECT - string.Format
```csharp
_logger.LogInformation("Order {0} submitted", orderId);
```
## XML Documentation - Required
ALL public and protected members MUST have XML documentation.
### ❌ WRONG - No Documentation
```csharp
public interface IOrderManager
// ❌ DEADLOCK RISK
lock (_lock)
{
Task<string> SubmitOrder(OrderRequest request);
_state = newState;
OrderStateChanged?.Invoke(this, args); // handler may try to acquire _lock
}
```
### ✅ CORRECT - With Documentation
```csharp
/// <summary>
/// Order management interface - manages complete order lifecycle
/// </summary>
public interface IOrderManager
// ✅ CORRECT
OrderState newState;
lock (_lock)
{
/// <summary>
/// Submit new order for execution
/// </summary>
/// <param name="request">Order request with all parameters</param>
/// <returns>Unique order ID for tracking</returns>
/// <exception cref="ArgumentNullException">Request is null</exception>
/// <exception cref="ArgumentException">Request validation fails</exception>
Task<string> SubmitOrder(OrderRequest request);
newState = CalculateNewState();
_state = newState;
}
// Raise AFTER releasing lock
RaiseOrderStateChanged(orderId, previousState, newState);
```
### Template
```csharp
/// <summary>
/// Brief description of what this does (one line)
/// </summary>
/// <param name="paramName">What this parameter represents</param>
/// <returns>What this method returns</returns>
/// <exception cref="ExceptionType">When this exception is thrown</exception>
public ReturnType MethodName(Type paramName)
{
// Implementation
}
```
---
## Constructor Pattern
## 5. Constructor — Validate All Dependencies
### ❌ WRONG - No Validation
```csharp
public BasicOrderManager(ILogger logger, INT8OrderAdapter adapter)
{
_logger = logger;
_adapter = adapter;
}
```
### ✅ CORRECT - Validate Dependencies
```csharp
public BasicOrderManager(ILogger<BasicOrderManager> logger, INT8OrderAdapter adapter)
public MyClass(ILogger<MyClass> logger, ISomeDependency dep)
{
if (logger == null)
throw new ArgumentNullException("logger");
if (adapter == null)
throw new ArgumentNullException("adapter");
if (dep == null)
throw new ArgumentNullException("dep");
_logger = logger;
_adapter = adapter;
_dep = dep;
// Initialize collections
_activeOrders = new Dictionary<string, OrderStatus>();
_completedOrders = new Dictionary<string, OrderStatus>();
// Register callbacks
_adapter.RegisterOrderCallback(OnNT8OrderUpdate);
_logger.LogInformation("BasicOrderManager initialized");
_logger.LogInformation("MyClass initialized");
}
```
## Event Raising Pattern
---
NEVER raise events inside locks (prevents deadlocks).
## 6. XML Documentation — Required on All Public Members
### ❌ WRONG - Event Inside Lock
```csharp
lock (_lock)
/// <summary>
/// Brief one-line description of what this does.
/// </summary>
/// <param name="intent">The trading intent to validate.</param>
/// <param name="context">Current strategy context with account state.</param>
/// <returns>Risk decision indicating allow or reject.</returns>
/// <exception cref="ArgumentNullException">Thrown when intent or context is null.</exception>
public RiskDecision ValidateOrder(StrategyIntent intent, StrategyContext context)
{
order.State = newState;
OrderStateChanged?.Invoke(this, eventArgs); // DEADLOCK RISK!
...
}
```
### ✅ CORRECT - Event Outside Lock
---
## 7. NT8-Specific Patterns (NinjaScript)
When writing code that runs inside NinjaTrader (in `NT8.Adapters/`):
```csharp
OrderState previousState;
OrderState newState;
lock (_lock)
// Always guard OnBarUpdate
protected override void OnBarUpdate()
{
previousState = order.State;
order.State = newState;
// Update state inside lock
if (BarsInProgress != 0) return;
if (CurrentBar < BarsRequiredToTrade) return;
// ...
}
// Raise event OUTSIDE lock
RaiseOrderStateChanged(orderId, previousState, newState, reason);
// Managed order pattern — set stops BEFORE entry
SetStopLoss("SignalName", CalculationMode.Ticks, stopTicks, false);
SetProfitTarget("SignalName", CalculationMode.Ticks, targetTicks);
EnterLong(contracts, "SignalName");
// Use string.Format for Print() too
Print(string.Format("Order submitted: {0} contracts at {1}", qty, price));
```
## Verification Checklist
---
Before completing ANY method, verify:
- [ ] Parameter validation (ArgumentNullException/ArgumentException)
- [ ] Try-catch on operation
- [ ] Logging at appropriate level
- [ ] Lock around shared state access
- [ ] Events raised outside locks
- [ ] XML documentation on public members
- [ ] C# 5.0 syntax only (no $, ?., =>, etc.)
## 8. Checklist Before Marking Any Method Complete
- [ ] Parameter null checks at the top
- [ ] `try-catch` wrapping the body
- [ ] All `Dictionary`/collection access inside `lock (_lock)`
- [ ] All logging uses `string.Format()` (no `$""`)
- [ ] XML `/// <summary>` on every public method, property, class
- [ ] No C# 6+ syntax
- [ ] Events raised outside lock blocks
- [ ] `verify-build.bat` passes

View File

@@ -1,88 +1,126 @@
# C# 5.0 Syntax Requirements
# C# 5.0 Syntax Required for NT8 SDK
You are working on a .NET Framework 4.8 project that MUST use C# 5.0 syntax only.
This project targets **.NET Framework 4.8** and must use **C# 5.0 syntax only**.
NinjaTrader 8's NinjaScript compiler does not support C# 6+ features.
## Forbidden C# 6+ Features
---
## Forbidden Patterns (with fixes)
### String Interpolation (C# 6)
❌ NEVER use: `$"Order {orderId} at {price}"`
✅ ALWAYS use: `string.Format("Order {0} at {1}", orderId, price)`
### Null-Conditional Operators (C# 6)
❌ NEVER use: `var name = order?.Name`
❌ NEVER use: `var value = dict?[key]`
✅ ALWAYS use explicit null checks:
```csharp
var name = order != null ? order.Name : null;
if (dict != null && dict.ContainsKey(key)) { }
// ❌ NEVER
_logger.LogInformation($"Order {orderId} filled at {price}");
// ✅ ALWAYS
_logger.LogInformation("Order {0} filled at {1}", orderId, price);
```
### Null-Conditional Operator (C# 6)
```csharp
// ❌ NEVER
var name = order?.Symbol;
// ✅ ALWAYS
var name = order != null ? order.Symbol : null;
```
### Null-Coalescing Assignment (C# 8)
❌ NEVER use: `value ??= defaultValue;`
✅ ALWAYS use: `if (value == null) value = defaultValue;`
```csharp
// ❌ NEVER
value ??= defaultValue;
// ✅ ALWAYS
if (value == null) value = defaultValue;
```
### Expression-Bodied Members (C# 6)
❌ NEVER use: `public int Property => value;`
❌ NEVER use: `public void Method() => DoSomething();`
✅ ALWAYS use full syntax:
```csharp
public int Property
{
get { return value; }
}
// ❌ NEVER
public int Contracts => _contracts;
public void Reset() => _contracts = 0;
public void Method()
{
DoSomething();
}
// ✅ ALWAYS
public int Contracts { get { return _contracts; } }
public void Reset() { _contracts = 0; }
```
### nameof Operator (C# 6)
❌ NEVER use: `throw new ArgumentNullException(nameof(param));`
✅ ALWAYS use: `throw new ArgumentNullException("param");`
```csharp
// ❌ NEVER
throw new ArgumentNullException(nameof(intent));
// ✅ ALWAYS
throw new ArgumentNullException("intent");
```
### Auto-Property Initializers (C# 6)
❌ NEVER use: `public int Property { get; set; } = 10;`
✅ ALWAYS use constructor initialization:
```csharp
public int Property { get; set; }
// ❌ NEVER
public bool IsEnabled { get; set; } = true;
public ClassName()
{
Property = 10;
}
// ✅ ALWAYS — initialize in constructor
public bool IsEnabled { get; set; }
public MyClass() { IsEnabled = true; }
```
### Using Static (C# 6)
❌ NEVER use: `using static System.Math;`
✅ ALWAYS use: `System.Math.Floor(...)`
### Inline Out Variable Declaration (C# 7)
```csharp
// ❌ NEVER
if (_orders.TryGetValue(id, out var status)) { ... }
### Tuple Syntax (C# 7)
❌ NEVER use: `var tuple = (name: "test", value: 1);`
✅ ALWAYS use: `Tuple<string, int>` or custom classes
// ✅ ALWAYS
OrderStatus status;
if (_orders.TryGetValue(id, out status)) { ... }
```
### Pattern Matching (C# 7+)
❌ NEVER use: `if (obj is string str)`
✅ ALWAYS use: `if (obj is string) { var str = (string)obj; }`
### Pattern Matching (C# 7)
```csharp
// ❌ NEVER
if (obj is string s) { ... }
// ✅ ALWAYS
if (obj is string) { var s = (string)obj; ... }
```
### Local Functions (C# 7)
❌ NEVER use functions inside methods
✅ ALWAYS use private methods
### Out Variables (C# 7)
❌ NEVER use: `if (dict.TryGetValue(key, out var value))`
✅ ALWAYS use:
```csharp
OrderStatus value;
if (dict.TryGetValue(key, out value))
{
// Use value
// ❌ NEVER — function inside a method
public void Execute() {
void Helper() { ... }
Helper();
}
// ✅ ALWAYS — use private methods
private void Helper() { ... }
public void Execute() { Helper(); }
```
## Verification
After writing ANY code, verify C# 5.0 compliance:
- No `$` signs except in string literals
- No `?.` or `?[` operators
- No `=>` except in lambda expressions
- No inline variable declarations in out parameters
### Tuple Literals (C# 7)
```csharp
// ❌ NEVER
var result = (price: 100.0, qty: 5);
// ✅ ALWAYS — use Tuple<T1,T2> or a named class
var result = Tuple.Create(100.0, 5);
```
### using static (C# 6)
```csharp
// ❌ NEVER
using static System.Math;
// ✅ ALWAYS
System.Math.Floor(x);
Math.Floor(x); // (via standard using System;)
```
---
## Quick Self-Check Before Saving
- Search your code for `$"` — if found, replace every occurrence
- Search for `?.` — if found, replace with null check
- Search for `=>` — if on a property or method, rewrite as full block
- Search for `nameof` — replace with string literal
- Search for `out var` — split into declaration + assignment

View File

@@ -1,147 +1,52 @@
# File Modification Boundaries - Phase 2
# File Modification Boundaries Production Hardening
You are implementing **Phase 2: Enhanced Risk & Sizing** for the NT8 SDK project.
You are fixing specific gaps. These are the ONLY files you may touch.
## Allowed Modifications
---
You MAY create and modify files in these directories ONLY:
## ✅ Files You MAY Modify
### Phase 2 Implementation
- `src/NT8.Core/Risk/**/*.cs` - All risk management files
- `src/NT8.Core/Sizing/**/*.cs` - All sizing files
- `src/NT8.Core/OMS/OrderStateMachine.cs` - NEW file only
| File | What to Change |
|---|---|
| `src/NT8.Adapters/Strategies/NT8StrategyBase.cs` | Add `EnableKillSwitch`, `EnableVerboseLogging` NinjaScript params; add kill switch early-exit in `OnBarUpdate`; wire `ExecutionCircuitBreaker`; call `_circuitBreaker.RecordOrderRejection()` from `OnOrderUpdate` |
| `src/NT8.Core/Execution/TrailingStopManager.cs` | Fix `CalculateNewStopPrice()` — replace placeholder math with real formulas for `FixedTrailing`, `ATRTrailing`, `Chandelier` |
| `src/NT8.Core/Logging/BasicLogger.cs` | Add `LogLevel MinimumLevel` property; skip writes below minimum level |
| `src/NT8.Core/MarketData/SessionManager.cs` | Add static CME holiday list; update `IsRegularTradingHours()` to return `false` on holidays |
### Limited Modifications (Add Only, Don't Change)
- `src/NT8.Core/Risk/RiskConfig.cs` - ADD properties only (don't modify existing)
- `src/NT8.Core/OMS/OrderModels.cs` - ADD records only (don't modify existing)
- `src/NT8.Core/OMS/BasicOrderManager.cs` - ADD methods only (don't modify existing)
---
### Testing
- `tests/NT8.Core.Tests/Risk/**/*.cs` - Risk tests
- `tests/NT8.Core.Tests/Sizing/**/*.cs` - Sizing tests
- `tests/NT8.Core.Tests/OMS/EnhancedOMSTests.cs` - NEW file
- `tests/NT8.Integration.Tests/RiskSizingIntegrationTests.cs` - NEW file
- `tests/NT8.Performance.Tests/Phase2PerformanceTests.cs` - NEW file
## ✅ Files You MAY Create (New)
## Strictly Forbidden Modifications
| File | Purpose |
|---|---|
| `tests/NT8.Core.Tests/Execution/TrailingStopManagerFixedTests.cs` | Unit tests for fixed trailing stop calculations |
You MUST NOT modify:
---
### Interfaces (Breaking Changes)
- `src/NT8.Core/Common/Interfaces/IStrategy.cs`
- `src/NT8.Core/Risk/IRiskManager.cs` - Interface itself
- `src/NT8.Core/Sizing/IPositionSizer.cs` - Interface itself
- `src/NT8.Core/OMS/IOrderManager.cs` - Interface itself
- `src/NT8.Core/OMS/INT8OrderAdapter.cs` - Interface itself
## ❌ Files You Must NOT Touch
### Phase 1 Implementations
- `src/NT8.Core/Risk/BasicRiskManager.cs` - Keep as-is
- `src/NT8.Core/Sizing/BasicPositionSizer.cs` - Keep as-is
- `src/NT8.Core/OMS/BasicOrderManager.cs` - ADD only, don't modify existing methods
| File / Directory | Reason |
|---|---|
| `src/NT8.Adapters/NinjaTrader/NT8OrderAdapter.cs` | The stub does NOT block execution — `NT8StrategyBase.SubmitOrderToNT8()` is what submits orders. Leave the adapter alone. |
| `src/NT8.Adapters/Strategies/SimpleORBNT8.cs` | Strategy wrapper is correct |
| `src/NT8.Strategies/Examples/SimpleORBStrategy.cs` | Strategy logic is correct |
| `src/NT8.Core/OMS/**` | Complete and tested |
| `src/NT8.Core/Risk/**` | Complete and tested |
| `src/NT8.Core/Sizing/**` | Complete and tested |
| `src/NT8.Core/Intelligence/**` | Complete and tested |
| `src/NT8.Core/Analytics/**` | Complete and tested |
| `src/NT8.Core/Execution/ExecutionCircuitBreaker.cs` | Already correct — only instantiate and use it, don't modify |
| `src/NT8.Core/Common/**` | Interfaces and models — never touch |
| `Directory.Build.props` | Never touch |
| `*.csproj` | Never touch |
| Any existing passing test file | Do not break passing tests |
### Common Models
- `src/NT8.Core/Common/Models/**` - Don't modify existing models
---
### Build Configuration
- `Directory.Build.props`
- `*.csproj` files (unless adding new files)
- `.gitignore`
## Quick Self-Check
### Documentation (Read-Only)
- `nt8_phasing_plan.md`
- `nt8_dev_spec.md`
- Phase 1 guides
## New File Creation Rules
### When creating new files:
1. Use proper namespace:
- `NT8.Core.Risk` for risk files
- `NT8.Core.Sizing` for sizing files
- `NT8.Core.OMS` for OMS files
- `NT8.Core.Tests.Risk` for risk tests
- `NT8.Core.Tests.Sizing` for sizing tests
2. Include XML documentation on all public members
3. Follow existing file naming patterns (PascalCase)
4. Add to appropriate project file if needed
### File naming examples:
`AdvancedRiskManager.cs` - Implementation class
`AdvancedRiskModels.cs` - Model classes
`OptimalFCalculator.cs` - Calculator utility
`EnhancedPositionSizer.cs` - Sizer implementation
`AdvancedRiskManagerTests.cs` - Test class
## Modification Patterns
### ✅ CORRECT: Adding to existing file
```csharp
// In RiskConfig.cs - ADD new properties
public record RiskConfig(
// Phase 1 properties - DON'T TOUCH
double DailyLossLimit,
double MaxTradeRisk,
int MaxOpenPositions,
bool EmergencyFlattenEnabled,
// Phase 2 properties - ADD THESE
double? WeeklyLossLimit = null,
double? TrailingDrawdownLimit = null,
int? MaxCrossStrategyExposure = null
);
```
### ❌ WRONG: Modifying existing
```csharp
// DON'T change existing property types or remove them
public record RiskConfig(
int DailyLossLimit, // ❌ Changed type from double
// ❌ Removed MaxTradeRisk property
);
```
### ✅ CORRECT: Adding methods to BasicOrderManager
```csharp
public class BasicOrderManager : IOrderManager
{
// Existing methods - DON'T TOUCH
public async Task<string> SubmitOrderAsync(...) { }
// NEW Phase 2 methods - ADD THESE
public async Task<bool> HandlePartialFillAsync(...) { }
public async Task<bool> RetryOrderAsync(...) { }
}
```
## Verification
Before any file operation, ask yourself:
1. Is this file in an allowed directory?
2. Am I modifying an existing interface signature? (FORBIDDEN)
3. Am I changing existing Phase 1 behavior? (FORBIDDEN)
4. Am I only ADDING to existing files? (ALLOWED)
If unsure, DO NOT proceed - ask for clarification first.
## Phase 2 Specific Rules
### Risk Files
- ✅ Create AdvancedRiskManager.cs (NEW)
- ✅ Create AdvancedRiskModels.cs (NEW)
- ✅ Extend RiskConfig.cs (ADD ONLY)
### Sizing Files
- ✅ Create OptimalFCalculator.cs (NEW)
- ✅ Create VolatilityAdjustedSizer.cs (NEW)
- ✅ Create EnhancedPositionSizer.cs (NEW)
- ✅ Create SizingModels.cs (NEW)
### OMS Files
- ✅ Create OrderStateMachine.cs (NEW)
- ✅ Extend OrderModels.cs (ADD ONLY)
- ✅ Extend BasicOrderManager.cs (ADD METHODS ONLY)
### Test Files
- ✅ Create all new test files
- ✅ Don't modify existing test files unless fixing bugs
Before editing any file, ask:
1. Is this file in the allowed list above?
2. Am I changing an interface? → STOP
3. Am I modifying existing Risk/Sizing/OMS/Intelligence/Analytics code? → STOP
4. Am I breaking a passing test? → STOP

View File

@@ -1,200 +1,96 @@
# Project Context - Phase 2
# Project Context — NT8 SDK (Production Hardening Phase)
You are working on the **NT8 SDK** - an institutional-grade trading SDK for NinjaTrader 8.
You are working on the **NT8 SDK** an institutional-grade algorithmic trading framework for NinjaTrader 8.
This is production trading software. Bugs cause real financial losses.
## Project Purpose
---
This is production trading software used for automated futures trading (ES, NQ, MES, MNQ, CL, GC). Code quality is critical because:
- Bugs can cause real financial losses
- System runs 24/5 during market hours
- Performance requirements are strict (<200ms latency)
- This is institutional-grade, not hobbyist code
## What Is Already Built (Do Not Touch)
## Current Phase: Phase 2 - Enhanced Risk & Sizing
All core trading logic is complete and has 240+ passing tests:
You are implementing **advanced risk management and intelligent position sizing**.
| Layer | Status | Key Files |
|---|---|---|
| Risk (Tier 1-3) | ✅ Complete | `src/NT8.Core/Risk/` |
| Position Sizing | ✅ Complete | `src/NT8.Core/Sizing/` |
| OMS / Order Lifecycle | ✅ Complete | `src/NT8.Core/OMS/` |
| Intelligence | ✅ Complete | `src/NT8.Core/Intelligence/` |
| Analytics | ✅ Complete | `src/NT8.Core/Analytics/` |
| Execution Utilities | ✅ Complete | `src/NT8.Core/Execution/` |
| Market Data | ✅ Complete | `src/NT8.Core/MarketData/` |
### Phase 2 Responsibilities
- Advanced risk rules (Tiers 2-3)
- Optimal-f position sizing (Ralph Vince method)
- Volatility-adjusted sizing
- Enhanced OMS features (partial fills, retry, reconciliation)
**NT8 Order Execution is ALREADY WIRED.**
`NT8StrategyBase.SubmitOrderToNT8()` calls `EnterLong`, `EnterShort`, `SetStopLoss`, and
`SetProfitTarget` directly. The execution path works end-to-end. Do not re-implement it.
### What Phase 2 Does NOT Do (Other Components Handle)
- Basic risk validation (BasicRiskManager handles this - Phase 1)
- Strategy logic (IStrategy handles this - Phase 1)
- Order lifecycle management (BasicOrderManager handles this - Phase 1)
- Direct NT8 calls (NT8Adapter handles this - Future)
---
## Architecture Overview
## What You Are Fixing (The Active Task List)
### CRITICAL — `NT8StrategyBase.cs`
**Gap 1 — No kill switch**
`NT8StrategyBase` has no `EnableKillSwitch` NinjaScript parameter and no early-exit in `OnBarUpdate()`.
A runaway strategy cannot be stopped without killing NinjaTrader.
**Fix:** Add `EnableKillSwitch` (bool NinjaScript property) and `EnableVerboseLogging` property.
Add kill switch check as the FIRST thing in `OnBarUpdate()`.
→ See `TASK-01-kill-switch.md`
**Gap 2 — `ExecutionCircuitBreaker` not wired**
`src/NT8.Core/Execution/ExecutionCircuitBreaker.cs` is complete and tested.
It is never instantiated. Orders submit regardless of latency or rejection conditions.
**Fix:** Instantiate in `InitializeSdkComponents()`, gate orders in `SubmitOrderToNT8()`, wire rejections in `OnOrderUpdate()`.
→ See `TASK-02-circuit-breaker.md`
### HIGH — `TrailingStopManager.cs`
**Gap 3 — Placeholder stop math returns zero**
`CalculateNewStopPrice()` FixedTrailing branch: `marketPrice - (x - x)` = always zero movement.
ATRTrailing and Chandelier also have meaningless placeholder formulas.
**Fix:** Replace with real calculations using `TrailingStopConfig.TrailingAmountTicks` and `AtrMultiplier`.
→ See `TASK-03-trailing-stop.md`
### HIGH — `BasicLogger.cs`
**Gap 4 — No log-level filter**
Every log statement writes to console unconditionally. Cannot suppress debug noise in production.
**Fix:** Add `MinimumLevel` property (defaults to `Information`). Suppress messages below threshold.
→ See `TASK-04-log-level.md`
### MEDIUM — `SessionManager.cs`
**Gap 5 — No holiday awareness**
`IsRegularTradingHours()` checks session times only. Will attempt to trade on Christmas, Thanksgiving, etc.
**Fix:** Add static CME holiday set for 2025/2026. Return `false` on those dates.
→ See `TASK-05-session-holidays.md`
---
## Architecture (Read Before Touching Anything)
```
Strategy Layer (IStrategy) - Phase 1 ✅
generates StrategyIntent
Risk Layer (IRiskManager)
├─ BasicRiskManager - Phase 1 ✅
└─ AdvancedRiskManager - Phase 2 ← YOU ARE HERE
↓ validates and produces RiskDecision
Sizing Layer (IPositionSizer)
├─ BasicPositionSizer - Phase 1 ✅
└─ EnhancedPositionSizer - Phase 2 ← YOU ARE HERE
↓ calculates contracts and produces SizingResult
OMS Layer (IOrderManager) - Phase 1 ✅ (enhancing in Phase 2)
↓ manages order lifecycle
NT8 Adapter Layer (INT8OrderAdapter) - Future
↓ bridges to NinjaTrader 8
NinjaTrader 8 Platform
SimpleORBStrategy.OnBar()
returns StrategyIntent
NT8StrategyBase.OnBarUpdate()
↓ [TASK-01: kill switch check here, first]
↓ calls ProcessStrategyIntent()
↓ calls _riskManager.ValidateOrder()
↓ calls _positionSizer.CalculateSize()
↓ calls SubmitOrderToNT8()
↓ [TASK-02: circuit breaker gate here]
↓ calls EnterLong/EnterShort/SetStopLoss/SetProfitTarget (already works)
NT8 callbacks → OnOrderUpdate / OnExecutionUpdate
↓ [TASK-02: record rejections in circuit breaker here]
```
## Your Current Task
Implement **Enhanced Risk & Sizing** with these deliverables:
### Phase 2 Deliverables
**Risk Management:**
1. `AdvancedRiskModels.cs` - Weekly tracking, drawdown, exposure
2. `AdvancedRiskManager.cs` - All Tier 2-3 risk rules
3. Update `RiskConfig.cs` - Add new configuration properties
**Position Sizing:**
4. `SizingModels.cs` - Optimal-f, volatility models
5. `OptimalFCalculator.cs` - Ralph Vince algorithm
6. `VolatilityAdjustedSizer.cs` - ATR/StdDev sizing
7. `EnhancedPositionSizer.cs` - All advanced sizing methods
**Enhanced OMS:**
8. `OrderStateMachine.cs` - Formal state machine
9. Update `OrderModels.cs` - Add partial fill models
10. Update `BasicOrderManager.cs` - Add enhanced methods
**Testing:**
11. Comprehensive unit tests (90+ tests total)
12. Integration tests (risk + sizing flow)
13. Performance benchmarks (<5ms risk, <3ms sizing)
### Out of Scope (Future Phases)
- Market microstructure (Phase 3)
- Advanced order types (Phase 3)
- Confluence scoring (Phase 4)
- ML-based features (Phase 6)
## Key Design Principles
### 1. Risk-First Architecture
ALL trading operations flow through risk management before execution.
The pattern is: Strategy Risk Sizing OMS NT8
**NEVER bypass risk checks.**
### 2. Backward Compatibility
Phase 2 MUST NOT break Phase 1:
- BasicRiskManager still works
- BasicPositionSizer still works
- BasicOrderManager still works
- No interface signature changes
### 3. Thread Safety
This system will run with:
- Multiple strategies executing simultaneously
- Multiple NT8 callbacks firing
- UI queries happening during trading
- State changes from external events
ALL shared state MUST be protected with locks.
### 4. Performance Targets
- Risk validation: <5ms (was <10ms in Phase 1)
- Sizing calculation: <3ms (was <5ms in Phase 1)
- Overall tick-to-trade: <200ms (unchanged)
- No degradation to Phase 1 performance
### 5. Determinism
All calculations must be deterministic for:
- Backtesting accuracy
- Replay debugging
- Audit trails
---
## Technology Constraints
### Language & Framework
- C# 5.0 syntax ONLY (no C# 6+)
- .NET Framework 4.8 (not .NET Core/5+/6+)
- Target: Windows desktop environment
### Libraries
- Newtonsoft.Json (for serialization)
- Microsoft.Extensions.Logging (for logging)
- Microsoft.Extensions.DependencyInjection (for DI)
- System.Text.Json (not available)
- Any .NET Core/5+/6+ libraries
### Testing
- xUnit for test framework
- FluentAssertions for assertions
- Bogus for test data generation (if needed)
- Mock adapters for isolation
## Reference Documents
You have access to these design documents:
- `Phase2_Implementation_Guide.md` - Step-by-step tasks
- `nt8_phasing_plan.md` - Overall project plan
- `nt8_dev_spec.md` - Technical specifications
When uncertain about design decisions, reference these documents.
## Success Criteria
Your implementation is complete when:
- [ ] All 15 Phase 2 files created
- [ ] `verify-build.bat` passes
- [ ] >90 total tests passing
- [ ] >80% test coverage for new code
- [ ] No C# 6+ syntax
- [ ] Thread safety verified
- [ ] Performance targets met
- [ ] No breaking changes to Phase 1
- [ ] Integration tests pass
- [ ] Documentation complete
## Phase 1 Foundation (What You're Building On)
### Already Complete ✅
- OrderModels with all enums
- IOrderManager interface
- BasicOrderManager with state machine
- BasicRiskManager with Tier 1 rules
- BasicPositionSizer with fixed methods
- 34 passing unit tests
- Mock adapters for testing
### Phase 1 Code You Can Reference
- `src/NT8.Core/Risk/BasicRiskManager.cs` - Pattern to follow
- `src/NT8.Core/Sizing/BasicPositionSizer.cs` - Pattern to follow
- `src/NT8.Core/OMS/BasicOrderManager.cs` - Pattern to extend
- `tests/NT8.Core.Tests/Risk/BasicRiskManagerTests.cs` - Test pattern
## Communication
When you need clarification:
1. Check `Phase2_Implementation_Guide.md` first
2. Check existing Phase 1 code patterns
3. If still uncertain, ask before implementing
**Remember:** This is production trading code. When in doubt, ask rather than guess.
## Current Status
**Completed:**
- ✅ Phase 0: Foundation
- ✅ Phase 1: Basic OMS, Risk, Sizing (34 tests passing)
**In Progress:**
- 🔄 Phase 2: Enhanced Risk & Sizing ← **YOU ARE HERE**
**Next:**
- ⏭️ Phase 3: Market Microstructure
- ⏭️ Phase 4: Intelligence & Grading
- ⏭️ Phase 5: Analytics
- ⏭️ Phase 6: Advanced Features
**Progress:** ~10% → ~20% (Phase 2 will double completed functionality)
- **C# 5.0 only** — no `$""`, no `?.`, no `=>` on methods/properties, no `nameof()`, no `out var`
- **.NET Framework 4.8** — not .NET Core/5+/6+
- **NinjaScript managed orders** — `EnterLong`, `EnterShort`, `SetStopLoss`, `SetProfitTarget`
- `string.Format()` everywhere, never string interpolation
- All `Dictionary`, `HashSet` access inside `lock (_lock)` blocks
- XML doc comments on all public members
- `try/catch` on all public methods with `LogError` in the catch

View File

@@ -1,164 +1,79 @@
# Verification Requirements
You MUST verify your work at each checkpoint to ensure code quality and prevent errors.
Run `.\verify-build.bat` from `C:\dev\nt8-sdk\` after **every single file change**.
Do not proceed to the next task until this passes.
## After EVERY File Creation or Modification
---
### Step 1: Run Build Verification
```bash
## After Every File Change
### Step 1 — Build verification
```bat
cd C:\dev\nt8-sdk
.\verify-build.bat
```
**Expected Output:**
```
✅ All checks passed!
```
Expected: `✅ All checks passed!`
**If build fails:**
1. Read the error message carefully
2. Fix the error immediately
3. Re-run verify-build.bat
4. DO NOT proceed to next file until build passes
If it fails:
1. Read the compiler error carefully
2. Fix it immediately
3. Re-run before continuing
4. NEVER move to the next file with a broken build
### Step 2: Verify File Location
Check that the file is in an allowed directory:
-`src/NT8.Core/OMS/` - Implementation files
-`tests/NT8.Core.Tests/OMS/` - Test files
-`tests/NT8.Core.Tests/Mocks/` - Mock files
- ❌ Anywhere else - STOP and ask
### Step 3: Check Syntax Compliance
### Step 2 — Syntax check (self-audit before running)
Scan your code for forbidden patterns:
- No `$"..."` - Use `string.Format()`
- No `?.` or `?[` - Use explicit null checks
- No `=>` in properties/methods - Use full syntax
- No `nameof()` - Use string literals
- No `$"..."` (string interpolation) → use `string.Format("...", a, b)`
- No `?.` or `?[` → use explicit null checks
- No `=>` on properties or methods → use full `{ get { return x; } }` syntax
- No `nameof(x)` → use `"x"` string literal
- No `var x; ...TryGetValue(key, out var x)` inline → declare var separately
## After Completing Each Class
### Step 3 — After completing a whole class
```bat
dotnet test tests\NT8.Core.Tests --verbosity minimal
```
All existing tests must still pass. Zero regressions allowed.
### Step 4: Run Unit Tests (if applicable)
```bash
dotnet test tests\NT8.Core.Tests --filter "FullyQualifiedName~OMS"
---
## Specific Test Commands by Area
```bat
# Test execution layer (TrailingStopManager etc.)
dotnet test tests\NT8.Core.Tests --filter "FullyQualifiedName~Execution"
# Test adapters
dotnet test tests\NT8.Core.Tests --filter "FullyQualifiedName~Adapters"
# Test all integration tests
dotnet test tests\NT8.Integration.Tests --verbosity minimal
# Full suite
dotnet test NT8-SDK.sln --verbosity minimal
```
**Expected Output:**
```
Passed! - Failed: 0, Passed: X
```
### Step 5: Review Against Checklist
- [ ] All public members have XML documentation
- [ ] All dictionary access uses `lock (_lock)`
- [ ] All public methods have try-catch
- [ ] All logging uses `string.Format()`
- [ ] No C# 6+ syntax anywhere
- [ ] File compiles without warnings
## After Completing Full Task
### Step 6: Comprehensive Build
```bash
dotnet build NT8-SDK.sln --configuration Release
```
### Step 7: Full Test Suite
```bash
dotnet test tests\NT8.Core.Tests --verbosity normal
```
### Step 8: Code Coverage (Optional but Recommended)
```bash
dotnet test tests\NT8.Core.Tests --collect:"XPlat Code Coverage"
```
**Target:** >80% coverage for new code
## Common Verification Failures
### "Feature 'string interpolation' is not available"
**Cause:** Used `$"text {var}"`
**Fix:** Replace with `string.Format("text {0}", var)`
### "Feature 'null-conditional operator' is not available"
**Cause:** Used `obj?.Property`
**Fix:** Replace with explicit null check
### "Cannot access member before initialization"
**Cause:** Used auto-property initializer
**Fix:** Move initialization to constructor
### Lock-related warnings
**Cause:** Dictionary access outside lock
**Fix:** Wrap in `lock (_lock) { ... }`
---
## Emergency Stop Conditions
STOP immediately and ask for help if:
1. Build fails with errors you don't understand
2. ❌ Tests fail unexpectedly after your changes
3. You need to modify files outside allowed directories
4. You're unsure about a design decision
5. ❌ Performance is severely degraded
STOP and report back if:
- Build fails with errors you do not understand
- Existing tests fail after your changes
- You need to touch a file outside allowed boundaries
- You are unsure about a design decision
- You are about to modify a NinjaTrader API call signature
## Verification Workflow Summary
---
```
Write Code
Run verify-build.bat
Build passes? → NO → Fix errors, repeat
↓ YES
Check syntax (no C# 6+)
Check patterns (locks, try-catch, logging)
Check documentation (XML docs)
Run unit tests (if applicable)
All pass? → NO → Fix tests, repeat
↓ YES
Mark file complete ✅
Move to next file
```
## Quality Gates (ALL must pass before task is complete)
## Quality Gates
Your code MUST pass these gates before being considered complete:
### Gate 1: Compilation
-`verify-build.bat` outputs "All checks passed!"
- ✅ No compiler warnings
- ✅ All references resolve
### Gate 2: Syntax Compliance
- ✅ No C# 6+ features detected
- ✅ Only .NET Framework 4.8 APIs used
- ✅ Proper using statements
### Gate 3: Pattern Compliance
- ✅ Thread-safe operations
- ✅ Error handling present
- ✅ Logging at correct levels
- ✅ XML documentation complete
### Gate 4: Testing
- ✅ Unit tests written and passing
- ✅ Coverage >80% (target)
- ✅ Edge cases tested
## Self-Check Questions
Before marking a file complete, ask:
1. Does `verify-build.bat` pass?
2. Did I use any C# 6+ syntax?
3. Is all dictionary access inside locks?
4. Do all public methods have try-catch?
5. Does all logging use string.Format?
6. Do all public members have XML docs?
7. Are there unit tests for this code?
8. Do the tests pass?
**If any answer is "No" or "I'm not sure" → DO NOT PROCEED**
| Gate | Check |
|---|---|
| ✅ Compilation | `verify-build.bat` outputs "All checks passed!" |
| ✅ Syntax | No C# 6+ features |
| ✅ Thread safety | All shared `Dictionary`/`List` access inside `lock (_lock)` |
| ✅ Error handling | All public methods have `try-catch` |
| ✅ Logging | All log calls use `string.Format()` not `$""` |
| ✅ XML docs | All public members have `/// <summary>` |
| ✅ No regressions | 240+ existing tests still pass |