chore: Improve wrapper thread safety and logging
- Add thread-safe locking to BaseNT8StrategyWrapper - Add BasicLogger initialization - Improve null checking and error handling - Minor adapter enhancements
This commit is contained in:
@@ -2,6 +2,7 @@ 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;
|
||||
@@ -14,6 +15,8 @@ namespace NT8.Adapters.Wrappers
|
||||
/// </summary>
|
||||
public abstract class BaseNT8StrategyWrapper
|
||||
{
|
||||
private readonly object _lock = new object();
|
||||
|
||||
#region SDK Components
|
||||
|
||||
protected IStrategy _sdkStrategy;
|
||||
@@ -21,6 +24,7 @@ namespace NT8.Adapters.Wrappers
|
||||
protected IPositionSizer _positionSizer;
|
||||
protected NT8Adapter _nt8Adapter;
|
||||
protected StrategyConfig _strategyConfig;
|
||||
protected ILogger _logger;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -55,8 +59,13 @@ namespace NT8.Adapters.Wrappers
|
||||
TargetTicks = 20;
|
||||
RiskAmount = 100.0;
|
||||
|
||||
// Initialize SDK components
|
||||
InitializeSdkComponents();
|
||||
// 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
|
||||
@@ -77,12 +86,38 @@ namespace NT8.Adapters.Wrappers
|
||||
/// </summary>
|
||||
public void ProcessBarUpdate(BarData barData, StrategyContext context)
|
||||
{
|
||||
// Call SDK strategy logic
|
||||
var intent = _sdkStrategy.OnBar(barData, context);
|
||||
if (intent != null)
|
||||
if (barData == null)
|
||||
throw new ArgumentNullException("barData");
|
||||
if (context == null)
|
||||
throw new ArgumentNullException("context");
|
||||
|
||||
try
|
||||
{
|
||||
// Convert SDK results to NT8 actions
|
||||
ExecuteIntent(intent, context);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,19 +128,31 @@ namespace NT8.Adapters.Wrappers
|
||||
/// <summary>
|
||||
/// Initialize SDK components
|
||||
/// </summary>
|
||||
private void InitializeSdkComponents()
|
||||
protected virtual void InitializeSdkComponents(IRiskManager riskManager, IPositionSizer positionSizer, ILogger logger)
|
||||
{
|
||||
// In a real implementation, these would be injected or properly instantiated
|
||||
// For now, we'll create placeholder instances
|
||||
_riskManager = null; // This would be properly instantiated
|
||||
_positionSizer = null; // This would be properly instantiated
|
||||
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;
|
||||
|
||||
// Create NT8 adapter
|
||||
_nt8Adapter = new NT8Adapter();
|
||||
_nt8Adapter.Initialize(_riskManager, _positionSizer);
|
||||
|
||||
// Create SDK strategy
|
||||
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>
|
||||
@@ -145,13 +192,36 @@ namespace NT8.Adapters.Wrappers
|
||||
/// </summary>
|
||||
private void ExecuteIntent(StrategyIntent intent, StrategyContext context)
|
||||
{
|
||||
// Calculate position size
|
||||
var sizingResult = _positionSizer != null ?
|
||||
_positionSizer.CalculateSize(intent, context, _strategyConfig.SizingSettings) :
|
||||
new SizingResult(1, RiskAmount, SizingMethod.FixedDollarRisk, new Dictionary<string, object>());
|
||||
if (intent == null)
|
||||
throw new ArgumentNullException("intent");
|
||||
if (context == null)
|
||||
throw new ArgumentNullException("context");
|
||||
|
||||
// Execute through NT8 adapter
|
||||
_nt8Adapter.ExecuteIntent(intent, sizingResult);
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user