Files
nt8-sdk/deployment/backups/20260224_160457/BaseNT8StrategyWrapper.cs
mo a283ef4673 chore: checkpoint before NT8 execution wiring fix
Current state: Strategy builds and loads correctly, passes 240+ tests,
backtest (Strategy Analyzer) works but zero trades execute on live/SIM.

Root cause identified: NT8OrderAdapter.ExecuteInNT8() is a stub - it logs
to an internal list but never calls EnterLong/EnterShort/SetStopLoss/
SetProfitTarget. Fix is ready in TASK_01_WIRE_NT8_EXECUTION.md.

Task files added (ready for Kilocode):
- TASK_01_WIRE_NT8_EXECUTION.md (CRITICAL - INT8ExecutionBridge + wiring)
- TASK_02_EMERGENCY_KILL_SWITCH.md (CRITICAL - kill switch + verbose logging)
- TASK_03_WIRE_CIRCUIT_BREAKER.md (HIGH - wire ExecutionCircuitBreaker)

Build Status: All 240+ tests passing, zero errors
Next: Run Kilocode against TASK_01, TASK_02, TASK_03 in order
2026-03-10 15:49:59 -04:00

230 lines
6.9 KiB
C#

using System;
using System.Collections.Generic;
using NT8.Core.Common.Interfaces;
using NT8.Core.Common.Models;
using NT8.Core.Logging;
using NT8.Core.Risk;
using NT8.Core.Sizing;
using NT8.Adapters.NinjaTrader;
namespace NT8.Adapters.Wrappers
{
/// <summary>
/// Base wrapper class for NT8 strategies that integrate with the SDK
/// This is a template that would be extended in actual NT8 strategy files
/// </summary>
public abstract class BaseNT8StrategyWrapper
{
private readonly object _lock = new object();
#region SDK Components
protected IStrategy _sdkStrategy;
protected IRiskManager _riskManager;
protected IPositionSizer _positionSizer;
protected NT8Adapter _nt8Adapter;
protected StrategyConfig _strategyConfig;
protected ILogger _logger;
#endregion
#region Properties
/// <summary>
/// Stop loss in ticks
/// </summary>
public int StopTicks { get; set; }
/// <summary>
/// Profit target in ticks (optional)
/// </summary>
public int TargetTicks { get; set; }
/// <summary>
/// Risk amount per trade in dollars
/// </summary>
public double RiskAmount { get; set; }
#endregion
#region Constructor
/// <summary>
/// Constructor for BaseNT8StrategyWrapper
/// </summary>
public BaseNT8StrategyWrapper()
{
// Set default values
StopTicks = 10;
TargetTicks = 20;
RiskAmount = 100.0;
// Initialize SDK components with default implementations.
// Derived wrappers can replace these through InitializeSdkComponents.
_logger = new BasicLogger("BaseNT8StrategyWrapper");
_riskManager = new BasicRiskManager(_logger);
_positionSizer = new BasicPositionSizer(_logger);
InitializeSdkComponents(_riskManager, _positionSizer, _logger);
}
#endregion
#region Abstract Methods
/// <summary>
/// Create the SDK strategy implementation
/// </summary>
protected abstract IStrategy CreateSdkStrategy();
#endregion
#region Public Methods
/// <summary>
/// Process a bar update (would be called from NT8's OnBarUpdate)
/// </summary>
public void ProcessBarUpdate(BarData barData, StrategyContext context)
{
if (barData == null)
throw new ArgumentNullException("barData");
if (context == null)
throw new ArgumentNullException("context");
try
{
StrategyIntent intent;
lock (_lock)
{
if (_sdkStrategy == null)
{
throw new InvalidOperationException("SDK strategy has not been initialized.");
}
intent = _sdkStrategy.OnBar(barData, context);
}
if (intent != null)
{
ExecuteIntent(intent, context);
}
}
catch (Exception ex)
{
if (_logger != null)
{
_logger.LogError("Failed processing bar update for {0}: {1}", context.Symbol, ex.Message);
}
throw;
}
}
#endregion
#region Private Methods
/// <summary>
/// Initialize SDK components
/// </summary>
protected virtual void InitializeSdkComponents(IRiskManager riskManager, IPositionSizer positionSizer, ILogger logger)
{
if (riskManager == null)
throw new ArgumentNullException("riskManager");
if (positionSizer == null)
throw new ArgumentNullException("positionSizer");
if (logger == null)
throw new ArgumentNullException("logger");
_riskManager = riskManager;
_positionSizer = positionSizer;
_logger = logger;
_nt8Adapter = new NT8Adapter();
_nt8Adapter.Initialize(_riskManager, _positionSizer);
CreateSdkConfiguration();
_sdkStrategy = CreateSdkStrategy();
if (_sdkStrategy == null)
throw new InvalidOperationException("CreateSdkStrategy returned null.");
_sdkStrategy.Initialize(_strategyConfig, null, _logger);
_logger.LogInformation("Base NT8 strategy wrapper initialized for symbol {0}", _strategyConfig.Symbol);
}
/// <summary>
/// Create SDK configuration from parameters
/// </summary>
private void CreateSdkConfiguration()
{
// Create risk configuration
var riskConfig = new RiskConfig(
dailyLossLimit: 500.0,
maxTradeRisk: RiskAmount,
maxOpenPositions: 5,
emergencyFlattenEnabled: true
);
// Create sizing configuration
var sizingConfig = new SizingConfig(
method: SizingMethod.FixedDollarRisk,
minContracts: 1,
maxContracts: 100,
riskPerTrade: RiskAmount,
methodParameters: new Dictionary<string, object>()
);
// Create strategy configuration
_strategyConfig = new StrategyConfig(
name: "NT8Strategy",
symbol: "Unknown",
parameters: new Dictionary<string, object>(),
riskSettings: riskConfig,
sizingSettings: sizingConfig
);
}
/// <summary>
/// Execute strategy intent through NT8
/// </summary>
private void ExecuteIntent(StrategyIntent intent, StrategyContext context)
{
if (intent == null)
throw new ArgumentNullException("intent");
if (context == null)
throw new ArgumentNullException("context");
try
{
SizingResult sizingResult;
lock (_lock)
{
if (_positionSizer == null)
{
throw new InvalidOperationException("Position sizer has not been initialized.");
}
sizingResult = _positionSizer.CalculateSize(intent, context, _strategyConfig.SizingSettings);
}
_nt8Adapter.ExecuteIntent(intent, sizingResult);
}
catch (Exception ex)
{
if (_logger != null)
{
_logger.LogError("Failed executing intent for {0}: {1}", intent.Symbol, ex.Message);
}
throw;
}
}
#endregion
}
}