Files
nt8-sdk/DIAGNOSTIC_LOGGING_SPEC.md
2026-02-24 15:00:41 -05:00

277 lines
8.7 KiB
Markdown

# NT8 Strategy Diagnostic Logging Enhancement
**For:** Kilocode AI Agent
**Priority:** HIGH
**Mode:** Code Mode
**Estimated Time:** 30-40 minutes
**Files to Edit:** 1 file (NT8StrategyBase.cs)
---
## 🎯 Objective
Add comprehensive diagnostic logging to NT8StrategyBase so we can see exactly
what's happening during backtesting when zero trades occur. This will help
diagnose if the issue is:
- Strategy not generating intents
- Risk manager rejecting trades
- Position sizer issues
- Data feed issues
---
## 🔧 Changes to NT8StrategyBase.cs
### Change 1: Enhanced OnBarUpdate logging
**Find:**
```csharp
protected override void OnBarUpdate()
{
if (!_sdkInitialized || _sdkStrategy == null)
return;
if (CurrentBar < BarsRequiredToTrade)
return;
if (Time[0] == _lastBarTime)
return;
_lastBarTime = Time[0];
try
{
var barData = ConvertCurrentBar();
var context = BuildStrategyContext();
StrategyIntent intent;
lock (_lock)
{
intent = _sdkStrategy.OnBar(barData, context);
}
if (intent != null)
ProcessStrategyIntent(intent, context);
}
catch (Exception ex)
{
if (_logger != null)
_logger.LogError("OnBarUpdate failed: {0}", ex.Message);
Print(string.Format("[SDK ERROR] OnBarUpdate: {0}", ex.Message));
Log(string.Format("[SDK ERROR] {0}", ex.ToString()), LogLevel.Error);
}
}
```
**Replace with:**
```csharp
protected override void OnBarUpdate()
{
if (!_sdkInitialized || _sdkStrategy == null)
{
if (CurrentBar == 0)
Print(string.Format("[SDK] Not initialized: sdkInit={0}, strategy={1}",
_sdkInitialized, _sdkStrategy != null));
return;
}
if (CurrentBar < BarsRequiredToTrade)
{
if (CurrentBar == 0)
Print(string.Format("[SDK] Waiting for bars: current={0}, required={1}",
CurrentBar, BarsRequiredToTrade));
return;
}
if (Time[0] == _lastBarTime)
return;
_lastBarTime = Time[0];
// Log first bar and every 100th bar to show activity
if (CurrentBar == BarsRequiredToTrade || CurrentBar % 100 == 0)
{
Print(string.Format("[SDK] Processing bar {0}: {1} O={2:F2} H={3:F2} L={4:F2} C={5:F2}",
CurrentBar, Time[0].ToString("yyyy-MM-dd HH:mm"),
Open[0], High[0], Low[0], Close[0]));
}
try
{
var barData = ConvertCurrentBar();
var context = BuildStrategyContext();
StrategyIntent intent;
lock (_lock)
{
intent = _sdkStrategy.OnBar(barData, context);
}
if (intent != null)
{
Print(string.Format("[SDK] Intent generated: {0} {1} @ {2}",
intent.Side, intent.Symbol, intent.EntryType));
ProcessStrategyIntent(intent, context);
}
}
catch (Exception ex)
{
if (_logger != null)
_logger.LogError("OnBarUpdate failed: {0}", ex.Message);
Print(string.Format("[SDK ERROR] OnBarUpdate: {0}", ex.Message));
Log(string.Format("[SDK ERROR] {0}", ex.ToString()), LogLevel.Error);
}
}
```
---
### Change 2: Enhanced ProcessStrategyIntent logging
**Find:**
```csharp
private void ProcessStrategyIntent(StrategyIntent intent, StrategyContext context)
{
var riskDecision = _riskManager.ValidateOrder(intent, context, _riskConfig);
if (!riskDecision.Allow)
{
if (_logger != null)
_logger.LogWarning("Intent rejected by risk manager: {0}", riskDecision.RejectReason);
return;
}
var sizingResult = _positionSizer.CalculateSize(intent, context, _sizingConfig);
if (sizingResult.Contracts < MinContracts)
return;
var request = new OmsOrderRequest();
request.Symbol = intent.Symbol;
request.Side = MapOrderSide(intent.Side);
request.Type = MapOrderType(intent.EntryType);
request.Quantity = sizingResult.Contracts;
request.LimitPrice = intent.LimitPrice.HasValue ? (decimal?)intent.LimitPrice.Value : null;
request.StopPrice = null;
SubmitOrderToNT8(request, intent);
_ordersSubmittedToday++;
}
```
**Replace with:**
```csharp
private void ProcessStrategyIntent(StrategyIntent intent, StrategyContext context)
{
Print(string.Format("[SDK] Validating intent: {0} {1}", intent.Side, intent.Symbol));
var riskDecision = _riskManager.ValidateOrder(intent, context, _riskConfig);
if (!riskDecision.Allow)
{
Print(string.Format("[SDK] Risk REJECTED: {0}", riskDecision.RejectReason));
if (_logger != null)
_logger.LogWarning("Intent rejected by risk manager: {0}", riskDecision.RejectReason);
return;
}
Print(string.Format("[SDK] Risk approved"));
var sizingResult = _positionSizer.CalculateSize(intent, context, _sizingConfig);
Print(string.Format("[SDK] Position size: {0} contracts (min={1}, max={2})",
sizingResult.Contracts, MinContracts, MaxContracts));
if (sizingResult.Contracts < MinContracts)
{
Print(string.Format("[SDK] Size too small: {0} < {1}", sizingResult.Contracts, MinContracts));
return;
}
var request = new OmsOrderRequest();
request.Symbol = intent.Symbol;
request.Side = MapOrderSide(intent.Side);
request.Type = MapOrderType(intent.EntryType);
request.Quantity = sizingResult.Contracts;
request.LimitPrice = intent.LimitPrice.HasValue ? (decimal?)intent.LimitPrice.Value : null;
request.StopPrice = null;
Print(string.Format("[SDK] Submitting order: {0} {1} {2} @ {3}",
request.Side, request.Quantity, request.Symbol, request.Type));
SubmitOrderToNT8(request, intent);
_ordersSubmittedToday++;
}
```
---
### Change 3: Enhanced InitializeSdkComponents logging
**Find:**
```csharp
private void InitializeSdkComponents()
{
_logger = new BasicLogger(Name);
_riskConfig = new RiskConfig(DailyLossLimit, MaxTradeRisk, MaxOpenPositions, true);
```
**Replace with:**
```csharp
private void InitializeSdkComponents()
{
_logger = new BasicLogger(Name);
Print(string.Format("[SDK] Initializing with: DailyLoss={0:C}, TradeRisk={1:C}, MaxPos={2}",
DailyLossLimit, MaxTradeRisk, MaxOpenPositions));
_riskConfig = new RiskConfig(DailyLossLimit, MaxTradeRisk, MaxOpenPositions, true);
```
---
## ✅ Verification
```bash
# Build must succeed
dotnet build src\NT8.Adapters\NT8.Adapters.csproj --configuration Release
# Deploy
.\deployment\Deploy-To-NT8.ps1
```
**Expected in NT8 Output Window after backtest:**
```
[SDK] Initializing with: DailyLoss=$1,000.00, TradeRisk=$200.00, MaxPos=3
[SDK] Simple ORB NT8 initialized successfully
[SDK] Waiting for bars: current=0, required=50
[SDK] Processing bar 50: 2026-02-10 09:30 O=4200.00 H=4210.00 L=4195.00 C=4208.00
[SDK] Processing bar 150: 2026-02-10 12:30 O=4215.00 H=4220.00 L=4210.00 C=4218.00
[SDK] Intent generated: Buy ES @ Market
[SDK] Validating intent: Buy ES
[SDK] Risk approved
[SDK] Position size: 1 contracts (min=1, max=3)
[SDK] Submitting order: Buy 1 ES @ Market
```
This will show exactly where the strategy is failing.
---
## 📋 Git Commit
```bash
git add src/NT8.Adapters/Strategies/NT8StrategyBase.cs
git commit -m "feat: Add comprehensive diagnostic logging
- Log initialization parameters
- Log bar processing activity (every 100 bars)
- Log intent generation
- Log risk validation results
- Log position sizing calculations
- Log order submission
Makes it easy to diagnose why strategy isn't trading"
```
---
**READY FOR KILOCODE - CODE MODE**