diff --git a/commit-now.ps1 b/commit-now.ps1
new file mode 100644
index 0000000..302b1f4
--- /dev/null
+++ b/commit-now.ps1
@@ -0,0 +1,44 @@
+# commit-now.ps1 - Stage and commit all current changes to Gitea
+# Run from: C:\dev\nt8-sdk
+
+Set-Location "C:\dev\nt8-sdk"
+
+Write-Host "`n=== Current Git Status ===" -ForegroundColor Cyan
+git status
+
+Write-Host "`n=== Recent Commits ===" -ForegroundColor Cyan
+git log --oneline -5
+
+Write-Host "`n=== Staging all changes ===" -ForegroundColor Cyan
+git add -A
+
+Write-Host "`n=== Staged Files ===" -ForegroundColor Cyan
+git status
+
+$commitMessage = @"
+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
+"@
+
+Write-Host "`n=== Committing ===" -ForegroundColor Cyan
+git commit -m $commitMessage
+
+Write-Host "`n=== Pushing to Gitea ===" -ForegroundColor Cyan
+git push
+
+Write-Host "`n=== Done! ===" -ForegroundColor Green
+git log --oneline -3
diff --git a/deployment/backups/20260224_150604/NT8.Adapters.dll b/deployment/backups/20260224_150604/NT8.Adapters.dll
new file mode 100644
index 0000000..75f6e97
Binary files /dev/null and b/deployment/backups/20260224_150604/NT8.Adapters.dll differ
diff --git a/deployment/backups/20260224_150604/NT8.Core.dll b/deployment/backups/20260224_150604/NT8.Core.dll
new file mode 100644
index 0000000..dd42e3d
Binary files /dev/null and b/deployment/backups/20260224_150604/NT8.Core.dll differ
diff --git a/deployment/backups/20260224_150631/BaseNT8StrategyWrapper.cs b/deployment/backups/20260224_150631/BaseNT8StrategyWrapper.cs
new file mode 100644
index 0000000..5811382
--- /dev/null
+++ b/deployment/backups/20260224_150631/BaseNT8StrategyWrapper.cs
@@ -0,0 +1,229 @@
+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
+{
+ ///
+ /// Base wrapper class for NT8 strategies that integrate with the SDK
+ /// This is a template that would be extended in actual NT8 strategy files
+ ///
+ 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
+
+ ///
+ /// Stop loss in ticks
+ ///
+ public int StopTicks { get; set; }
+
+ ///
+ /// Profit target in ticks (optional)
+ ///
+ public int TargetTicks { get; set; }
+
+ ///
+ /// Risk amount per trade in dollars
+ ///
+ public double RiskAmount { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Constructor for BaseNT8StrategyWrapper
+ ///
+ 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
+
+ ///
+ /// Create the SDK strategy implementation
+ ///
+ protected abstract IStrategy CreateSdkStrategy();
+
+ #endregion
+
+ #region Public Methods
+
+ ///
+ /// Process a bar update (would be called from NT8's OnBarUpdate)
+ ///
+ 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
+
+ ///
+ /// Initialize SDK components
+ ///
+ 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);
+ }
+
+ ///
+ /// Create SDK configuration from parameters
+ ///
+ 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()
+ );
+
+ // Create strategy configuration
+ _strategyConfig = new StrategyConfig(
+ name: "NT8Strategy",
+ symbol: "Unknown",
+ parameters: new Dictionary(),
+ riskSettings: riskConfig,
+ sizingSettings: sizingConfig
+ );
+ }
+
+ ///
+ /// Execute strategy intent through NT8
+ ///
+ 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
+ }
+}
diff --git a/deployment/backups/20260224_150631/NT8.Adapters.dll b/deployment/backups/20260224_150631/NT8.Adapters.dll
new file mode 100644
index 0000000..0a12355
Binary files /dev/null and b/deployment/backups/20260224_150631/NT8.Adapters.dll differ
diff --git a/deployment/backups/20260224_150631/NT8.Core.dll b/deployment/backups/20260224_150631/NT8.Core.dll
new file mode 100644
index 0000000..ee14e46
Binary files /dev/null and b/deployment/backups/20260224_150631/NT8.Core.dll differ
diff --git a/deployment/backups/20260224_150631/SimpleORBNT8Wrapper.cs b/deployment/backups/20260224_150631/SimpleORBNT8Wrapper.cs
new file mode 100644
index 0000000..1c85459
--- /dev/null
+++ b/deployment/backups/20260224_150631/SimpleORBNT8Wrapper.cs
@@ -0,0 +1,280 @@
+using System;
+using System.Collections.Generic;
+using NT8.Core.Common.Interfaces;
+using NT8.Core.Common.Models;
+using NT8.Core.Logging;
+using NT8.Adapters.NinjaTrader;
+
+namespace NT8.Adapters.Wrappers
+{
+ ///
+ /// Simple ORB (Opening Range Breakout) strategy wrapper for NT8
+ /// This demonstrates how to implement a strategy that works with the SDK
+ ///
+ public class SimpleORBNT8Wrapper : BaseNT8StrategyWrapper
+ {
+ #region Strategy Parameters
+
+ ///
+ /// Opening range period in minutes
+ ///
+ public int OpeningRangeMinutes { get; set; }
+
+ ///
+ /// Number of standard deviations for breakout threshold
+ ///
+ public double StdDevMultiplier { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Constructor for SimpleORBNT8Wrapper
+ ///
+ public SimpleORBNT8Wrapper()
+ {
+ OpeningRangeMinutes = 30;
+ StdDevMultiplier = 1.0;
+ }
+
+ #endregion
+
+ #region Base Class Implementation
+
+ ///
+ /// Exposes adapter reference for integration test assertions.
+ ///
+ public NT8Adapter GetAdapterForTesting()
+ {
+ return _nt8Adapter;
+ }
+
+ ///
+ /// Create the SDK strategy implementation
+ ///
+ protected override IStrategy CreateSdkStrategy()
+ {
+ var openingRangeMinutes = OpeningRangeMinutes > 0 ? OpeningRangeMinutes : 30;
+ var stdDevMultiplier = StdDevMultiplier > 0.0 ? StdDevMultiplier : 1.0;
+ return new SimpleORBStrategy(openingRangeMinutes, stdDevMultiplier);
+ }
+
+ #endregion
+
+ #region Strategy Logic
+
+ ///
+ /// Simple ORB strategy implementation
+ ///
+ private class SimpleORBStrategy : IStrategy
+ {
+ private readonly int _openingRangeMinutes;
+ private readonly double _stdDevMultiplier;
+
+ private ILogger _logger;
+ private DateTime _currentSessionDate;
+ private DateTime _openingRangeStart;
+ private DateTime _openingRangeEnd;
+ private double _openingRangeHigh;
+ private double _openingRangeLow;
+ private bool _openingRangeReady;
+ private bool _tradeTaken;
+
+ public StrategyMetadata Metadata { get; private set; }
+
+ public SimpleORBStrategy(int openingRangeMinutes, double stdDevMultiplier)
+ {
+ if (openingRangeMinutes <= 0)
+ {
+ throw new ArgumentException("openingRangeMinutes");
+ }
+
+ if (stdDevMultiplier <= 0.0)
+ {
+ throw new ArgumentException("stdDevMultiplier");
+ }
+
+ _openingRangeMinutes = openingRangeMinutes;
+ _stdDevMultiplier = stdDevMultiplier;
+
+ _currentSessionDate = DateTime.MinValue;
+ _openingRangeStart = DateTime.MinValue;
+ _openingRangeEnd = DateTime.MinValue;
+ _openingRangeHigh = Double.MinValue;
+ _openingRangeLow = Double.MaxValue;
+ _openingRangeReady = false;
+ _tradeTaken = false;
+
+ Metadata = new StrategyMetadata(
+ name: "Simple ORB",
+ description: "Opening Range Breakout strategy",
+ version: "1.0",
+ author: "NT8 SDK Team",
+ symbols: new string[] { "ES", "NQ", "YM" },
+ requiredBars: 20
+ );
+ }
+
+ public void Initialize(StrategyConfig config, IMarketDataProvider dataProvider, ILogger logger)
+ {
+ if (logger == null)
+ {
+ throw new ArgumentNullException("logger");
+ }
+
+ _logger = logger;
+ _logger.LogInformation("SimpleORBStrategy initialized with OR period {0} minutes and multiplier {1:F2}", _openingRangeMinutes, _stdDevMultiplier);
+ }
+
+ public StrategyIntent OnBar(BarData bar, StrategyContext context)
+ {
+ if (bar == null)
+ {
+ throw new ArgumentNullException("bar");
+ }
+
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ try
+ {
+ if (_currentSessionDate != context.CurrentTime.Date)
+ {
+ ResetSession(context.Session.SessionStart);
+ }
+
+ if (bar.Time <= _openingRangeEnd)
+ {
+ UpdateOpeningRange(bar);
+ return null;
+ }
+
+ if (!_openingRangeReady)
+ {
+ if (_openingRangeHigh > _openingRangeLow)
+ {
+ _openingRangeReady = true;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ if (_tradeTaken)
+ {
+ return null;
+ }
+
+ var openingRange = _openingRangeHigh - _openingRangeLow;
+ var volatilityBuffer = openingRange * (_stdDevMultiplier - 1.0);
+ if (volatilityBuffer < 0)
+ {
+ volatilityBuffer = 0;
+ }
+
+ var longTrigger = _openingRangeHigh + volatilityBuffer;
+ var shortTrigger = _openingRangeLow - volatilityBuffer;
+
+ if (bar.Close > longTrigger)
+ {
+ _tradeTaken = true;
+ return CreateIntent(context.Symbol, OrderSide.Buy, openingRange, bar.Close);
+ }
+
+ if (bar.Close < shortTrigger)
+ {
+ _tradeTaken = true;
+ return CreateIntent(context.Symbol, OrderSide.Sell, openingRange, bar.Close);
+ }
+
+ return null;
+ }
+ catch (Exception ex)
+ {
+ if (_logger != null)
+ {
+ _logger.LogError("SimpleORBStrategy OnBar failed: {0}", ex.Message);
+ }
+
+ throw;
+ }
+ }
+
+ public StrategyIntent OnTick(TickData tick, StrategyContext context)
+ {
+ // Most strategies don't need tick-level logic
+ return null;
+ }
+
+ public Dictionary GetParameters()
+ {
+ var parameters = new Dictionary();
+ parameters.Add("opening_range_minutes", _openingRangeMinutes);
+ parameters.Add("std_dev_multiplier", _stdDevMultiplier);
+ return parameters;
+ }
+
+ public void SetParameters(Dictionary parameters)
+ {
+ // Parameters are constructor-bound for deterministic behavior in this wrapper.
+ // Method retained for interface compatibility.
+ }
+
+ private void ResetSession(DateTime sessionStart)
+ {
+ _currentSessionDate = sessionStart.Date;
+ _openingRangeStart = sessionStart;
+ _openingRangeEnd = sessionStart.AddMinutes(_openingRangeMinutes);
+ _openingRangeHigh = Double.MinValue;
+ _openingRangeLow = Double.MaxValue;
+ _openingRangeReady = false;
+ _tradeTaken = false;
+ }
+
+ private void UpdateOpeningRange(BarData bar)
+ {
+ if (bar.High > _openingRangeHigh)
+ {
+ _openingRangeHigh = bar.High;
+ }
+
+ if (bar.Low < _openingRangeLow)
+ {
+ _openingRangeLow = bar.Low;
+ }
+ }
+
+ private StrategyIntent CreateIntent(string symbol, OrderSide side, double openingRange, double lastPrice)
+ {
+ var metadata = new Dictionary();
+ metadata.Add("orb_high", _openingRangeHigh);
+ metadata.Add("orb_low", _openingRangeLow);
+ metadata.Add("orb_range", openingRange);
+ metadata.Add("trigger_price", lastPrice);
+ metadata.Add("multiplier", _stdDevMultiplier);
+
+ if (_logger != null)
+ {
+ _logger.LogInformation("SimpleORBStrategy generated {0} intent for {1}. OR High={2:F2}, OR Low={3:F2}, Last={4:F2}", side, symbol, _openingRangeHigh, _openingRangeLow, lastPrice);
+ }
+
+ return new StrategyIntent(
+ symbol,
+ side,
+ OrderType.Market,
+ null,
+ 8,
+ 16,
+ 0.75,
+ "ORB breakout signal",
+ metadata);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/deployment/backups/20260224_150834/BaseNT8StrategyWrapper.cs b/deployment/backups/20260224_150834/BaseNT8StrategyWrapper.cs
new file mode 100644
index 0000000..5811382
--- /dev/null
+++ b/deployment/backups/20260224_150834/BaseNT8StrategyWrapper.cs
@@ -0,0 +1,229 @@
+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
+{
+ ///
+ /// Base wrapper class for NT8 strategies that integrate with the SDK
+ /// This is a template that would be extended in actual NT8 strategy files
+ ///
+ 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
+
+ ///
+ /// Stop loss in ticks
+ ///
+ public int StopTicks { get; set; }
+
+ ///
+ /// Profit target in ticks (optional)
+ ///
+ public int TargetTicks { get; set; }
+
+ ///
+ /// Risk amount per trade in dollars
+ ///
+ public double RiskAmount { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Constructor for BaseNT8StrategyWrapper
+ ///
+ 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
+
+ ///
+ /// Create the SDK strategy implementation
+ ///
+ protected abstract IStrategy CreateSdkStrategy();
+
+ #endregion
+
+ #region Public Methods
+
+ ///
+ /// Process a bar update (would be called from NT8's OnBarUpdate)
+ ///
+ 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
+
+ ///
+ /// Initialize SDK components
+ ///
+ 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);
+ }
+
+ ///
+ /// Create SDK configuration from parameters
+ ///
+ 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()
+ );
+
+ // Create strategy configuration
+ _strategyConfig = new StrategyConfig(
+ name: "NT8Strategy",
+ symbol: "Unknown",
+ parameters: new Dictionary(),
+ riskSettings: riskConfig,
+ sizingSettings: sizingConfig
+ );
+ }
+
+ ///
+ /// Execute strategy intent through NT8
+ ///
+ 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
+ }
+}
diff --git a/deployment/backups/20260224_150834/NT8.Adapters.dll b/deployment/backups/20260224_150834/NT8.Adapters.dll
new file mode 100644
index 0000000..0a12355
Binary files /dev/null and b/deployment/backups/20260224_150834/NT8.Adapters.dll differ
diff --git a/deployment/backups/20260224_150834/NT8.Core.dll b/deployment/backups/20260224_150834/NT8.Core.dll
new file mode 100644
index 0000000..ee14e46
Binary files /dev/null and b/deployment/backups/20260224_150834/NT8.Core.dll differ
diff --git a/deployment/backups/20260224_150834/SimpleORBNT8Wrapper.cs b/deployment/backups/20260224_150834/SimpleORBNT8Wrapper.cs
new file mode 100644
index 0000000..1c85459
--- /dev/null
+++ b/deployment/backups/20260224_150834/SimpleORBNT8Wrapper.cs
@@ -0,0 +1,280 @@
+using System;
+using System.Collections.Generic;
+using NT8.Core.Common.Interfaces;
+using NT8.Core.Common.Models;
+using NT8.Core.Logging;
+using NT8.Adapters.NinjaTrader;
+
+namespace NT8.Adapters.Wrappers
+{
+ ///
+ /// Simple ORB (Opening Range Breakout) strategy wrapper for NT8
+ /// This demonstrates how to implement a strategy that works with the SDK
+ ///
+ public class SimpleORBNT8Wrapper : BaseNT8StrategyWrapper
+ {
+ #region Strategy Parameters
+
+ ///
+ /// Opening range period in minutes
+ ///
+ public int OpeningRangeMinutes { get; set; }
+
+ ///
+ /// Number of standard deviations for breakout threshold
+ ///
+ public double StdDevMultiplier { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Constructor for SimpleORBNT8Wrapper
+ ///
+ public SimpleORBNT8Wrapper()
+ {
+ OpeningRangeMinutes = 30;
+ StdDevMultiplier = 1.0;
+ }
+
+ #endregion
+
+ #region Base Class Implementation
+
+ ///
+ /// Exposes adapter reference for integration test assertions.
+ ///
+ public NT8Adapter GetAdapterForTesting()
+ {
+ return _nt8Adapter;
+ }
+
+ ///
+ /// Create the SDK strategy implementation
+ ///
+ protected override IStrategy CreateSdkStrategy()
+ {
+ var openingRangeMinutes = OpeningRangeMinutes > 0 ? OpeningRangeMinutes : 30;
+ var stdDevMultiplier = StdDevMultiplier > 0.0 ? StdDevMultiplier : 1.0;
+ return new SimpleORBStrategy(openingRangeMinutes, stdDevMultiplier);
+ }
+
+ #endregion
+
+ #region Strategy Logic
+
+ ///
+ /// Simple ORB strategy implementation
+ ///
+ private class SimpleORBStrategy : IStrategy
+ {
+ private readonly int _openingRangeMinutes;
+ private readonly double _stdDevMultiplier;
+
+ private ILogger _logger;
+ private DateTime _currentSessionDate;
+ private DateTime _openingRangeStart;
+ private DateTime _openingRangeEnd;
+ private double _openingRangeHigh;
+ private double _openingRangeLow;
+ private bool _openingRangeReady;
+ private bool _tradeTaken;
+
+ public StrategyMetadata Metadata { get; private set; }
+
+ public SimpleORBStrategy(int openingRangeMinutes, double stdDevMultiplier)
+ {
+ if (openingRangeMinutes <= 0)
+ {
+ throw new ArgumentException("openingRangeMinutes");
+ }
+
+ if (stdDevMultiplier <= 0.0)
+ {
+ throw new ArgumentException("stdDevMultiplier");
+ }
+
+ _openingRangeMinutes = openingRangeMinutes;
+ _stdDevMultiplier = stdDevMultiplier;
+
+ _currentSessionDate = DateTime.MinValue;
+ _openingRangeStart = DateTime.MinValue;
+ _openingRangeEnd = DateTime.MinValue;
+ _openingRangeHigh = Double.MinValue;
+ _openingRangeLow = Double.MaxValue;
+ _openingRangeReady = false;
+ _tradeTaken = false;
+
+ Metadata = new StrategyMetadata(
+ name: "Simple ORB",
+ description: "Opening Range Breakout strategy",
+ version: "1.0",
+ author: "NT8 SDK Team",
+ symbols: new string[] { "ES", "NQ", "YM" },
+ requiredBars: 20
+ );
+ }
+
+ public void Initialize(StrategyConfig config, IMarketDataProvider dataProvider, ILogger logger)
+ {
+ if (logger == null)
+ {
+ throw new ArgumentNullException("logger");
+ }
+
+ _logger = logger;
+ _logger.LogInformation("SimpleORBStrategy initialized with OR period {0} minutes and multiplier {1:F2}", _openingRangeMinutes, _stdDevMultiplier);
+ }
+
+ public StrategyIntent OnBar(BarData bar, StrategyContext context)
+ {
+ if (bar == null)
+ {
+ throw new ArgumentNullException("bar");
+ }
+
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ try
+ {
+ if (_currentSessionDate != context.CurrentTime.Date)
+ {
+ ResetSession(context.Session.SessionStart);
+ }
+
+ if (bar.Time <= _openingRangeEnd)
+ {
+ UpdateOpeningRange(bar);
+ return null;
+ }
+
+ if (!_openingRangeReady)
+ {
+ if (_openingRangeHigh > _openingRangeLow)
+ {
+ _openingRangeReady = true;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ if (_tradeTaken)
+ {
+ return null;
+ }
+
+ var openingRange = _openingRangeHigh - _openingRangeLow;
+ var volatilityBuffer = openingRange * (_stdDevMultiplier - 1.0);
+ if (volatilityBuffer < 0)
+ {
+ volatilityBuffer = 0;
+ }
+
+ var longTrigger = _openingRangeHigh + volatilityBuffer;
+ var shortTrigger = _openingRangeLow - volatilityBuffer;
+
+ if (bar.Close > longTrigger)
+ {
+ _tradeTaken = true;
+ return CreateIntent(context.Symbol, OrderSide.Buy, openingRange, bar.Close);
+ }
+
+ if (bar.Close < shortTrigger)
+ {
+ _tradeTaken = true;
+ return CreateIntent(context.Symbol, OrderSide.Sell, openingRange, bar.Close);
+ }
+
+ return null;
+ }
+ catch (Exception ex)
+ {
+ if (_logger != null)
+ {
+ _logger.LogError("SimpleORBStrategy OnBar failed: {0}", ex.Message);
+ }
+
+ throw;
+ }
+ }
+
+ public StrategyIntent OnTick(TickData tick, StrategyContext context)
+ {
+ // Most strategies don't need tick-level logic
+ return null;
+ }
+
+ public Dictionary GetParameters()
+ {
+ var parameters = new Dictionary();
+ parameters.Add("opening_range_minutes", _openingRangeMinutes);
+ parameters.Add("std_dev_multiplier", _stdDevMultiplier);
+ return parameters;
+ }
+
+ public void SetParameters(Dictionary parameters)
+ {
+ // Parameters are constructor-bound for deterministic behavior in this wrapper.
+ // Method retained for interface compatibility.
+ }
+
+ private void ResetSession(DateTime sessionStart)
+ {
+ _currentSessionDate = sessionStart.Date;
+ _openingRangeStart = sessionStart;
+ _openingRangeEnd = sessionStart.AddMinutes(_openingRangeMinutes);
+ _openingRangeHigh = Double.MinValue;
+ _openingRangeLow = Double.MaxValue;
+ _openingRangeReady = false;
+ _tradeTaken = false;
+ }
+
+ private void UpdateOpeningRange(BarData bar)
+ {
+ if (bar.High > _openingRangeHigh)
+ {
+ _openingRangeHigh = bar.High;
+ }
+
+ if (bar.Low < _openingRangeLow)
+ {
+ _openingRangeLow = bar.Low;
+ }
+ }
+
+ private StrategyIntent CreateIntent(string symbol, OrderSide side, double openingRange, double lastPrice)
+ {
+ var metadata = new Dictionary();
+ metadata.Add("orb_high", _openingRangeHigh);
+ metadata.Add("orb_low", _openingRangeLow);
+ metadata.Add("orb_range", openingRange);
+ metadata.Add("trigger_price", lastPrice);
+ metadata.Add("multiplier", _stdDevMultiplier);
+
+ if (_logger != null)
+ {
+ _logger.LogInformation("SimpleORBStrategy generated {0} intent for {1}. OR High={2:F2}, OR Low={3:F2}, Last={4:F2}", side, symbol, _openingRangeHigh, _openingRangeLow, lastPrice);
+ }
+
+ return new StrategyIntent(
+ symbol,
+ side,
+ OrderType.Market,
+ null,
+ 8,
+ 16,
+ 0.75,
+ "ORB breakout signal",
+ metadata);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/deployment/backups/20260224_154420/BaseNT8StrategyWrapper.cs b/deployment/backups/20260224_154420/BaseNT8StrategyWrapper.cs
new file mode 100644
index 0000000..5811382
--- /dev/null
+++ b/deployment/backups/20260224_154420/BaseNT8StrategyWrapper.cs
@@ -0,0 +1,229 @@
+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
+{
+ ///
+ /// Base wrapper class for NT8 strategies that integrate with the SDK
+ /// This is a template that would be extended in actual NT8 strategy files
+ ///
+ 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
+
+ ///
+ /// Stop loss in ticks
+ ///
+ public int StopTicks { get; set; }
+
+ ///
+ /// Profit target in ticks (optional)
+ ///
+ public int TargetTicks { get; set; }
+
+ ///
+ /// Risk amount per trade in dollars
+ ///
+ public double RiskAmount { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Constructor for BaseNT8StrategyWrapper
+ ///
+ 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
+
+ ///
+ /// Create the SDK strategy implementation
+ ///
+ protected abstract IStrategy CreateSdkStrategy();
+
+ #endregion
+
+ #region Public Methods
+
+ ///
+ /// Process a bar update (would be called from NT8's OnBarUpdate)
+ ///
+ 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
+
+ ///
+ /// Initialize SDK components
+ ///
+ 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);
+ }
+
+ ///
+ /// Create SDK configuration from parameters
+ ///
+ 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()
+ );
+
+ // Create strategy configuration
+ _strategyConfig = new StrategyConfig(
+ name: "NT8Strategy",
+ symbol: "Unknown",
+ parameters: new Dictionary(),
+ riskSettings: riskConfig,
+ sizingSettings: sizingConfig
+ );
+ }
+
+ ///
+ /// Execute strategy intent through NT8
+ ///
+ 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
+ }
+}
diff --git a/deployment/backups/20260224_154420/NT8.Adapters.dll b/deployment/backups/20260224_154420/NT8.Adapters.dll
new file mode 100644
index 0000000..0a12355
Binary files /dev/null and b/deployment/backups/20260224_154420/NT8.Adapters.dll differ
diff --git a/deployment/backups/20260224_154420/NT8.Core.dll b/deployment/backups/20260224_154420/NT8.Core.dll
new file mode 100644
index 0000000..ee14e46
Binary files /dev/null and b/deployment/backups/20260224_154420/NT8.Core.dll differ
diff --git a/deployment/backups/20260224_154420/SimpleORBNT8Wrapper.cs b/deployment/backups/20260224_154420/SimpleORBNT8Wrapper.cs
new file mode 100644
index 0000000..1c85459
--- /dev/null
+++ b/deployment/backups/20260224_154420/SimpleORBNT8Wrapper.cs
@@ -0,0 +1,280 @@
+using System;
+using System.Collections.Generic;
+using NT8.Core.Common.Interfaces;
+using NT8.Core.Common.Models;
+using NT8.Core.Logging;
+using NT8.Adapters.NinjaTrader;
+
+namespace NT8.Adapters.Wrappers
+{
+ ///
+ /// Simple ORB (Opening Range Breakout) strategy wrapper for NT8
+ /// This demonstrates how to implement a strategy that works with the SDK
+ ///
+ public class SimpleORBNT8Wrapper : BaseNT8StrategyWrapper
+ {
+ #region Strategy Parameters
+
+ ///
+ /// Opening range period in minutes
+ ///
+ public int OpeningRangeMinutes { get; set; }
+
+ ///
+ /// Number of standard deviations for breakout threshold
+ ///
+ public double StdDevMultiplier { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Constructor for SimpleORBNT8Wrapper
+ ///
+ public SimpleORBNT8Wrapper()
+ {
+ OpeningRangeMinutes = 30;
+ StdDevMultiplier = 1.0;
+ }
+
+ #endregion
+
+ #region Base Class Implementation
+
+ ///
+ /// Exposes adapter reference for integration test assertions.
+ ///
+ public NT8Adapter GetAdapterForTesting()
+ {
+ return _nt8Adapter;
+ }
+
+ ///
+ /// Create the SDK strategy implementation
+ ///
+ protected override IStrategy CreateSdkStrategy()
+ {
+ var openingRangeMinutes = OpeningRangeMinutes > 0 ? OpeningRangeMinutes : 30;
+ var stdDevMultiplier = StdDevMultiplier > 0.0 ? StdDevMultiplier : 1.0;
+ return new SimpleORBStrategy(openingRangeMinutes, stdDevMultiplier);
+ }
+
+ #endregion
+
+ #region Strategy Logic
+
+ ///
+ /// Simple ORB strategy implementation
+ ///
+ private class SimpleORBStrategy : IStrategy
+ {
+ private readonly int _openingRangeMinutes;
+ private readonly double _stdDevMultiplier;
+
+ private ILogger _logger;
+ private DateTime _currentSessionDate;
+ private DateTime _openingRangeStart;
+ private DateTime _openingRangeEnd;
+ private double _openingRangeHigh;
+ private double _openingRangeLow;
+ private bool _openingRangeReady;
+ private bool _tradeTaken;
+
+ public StrategyMetadata Metadata { get; private set; }
+
+ public SimpleORBStrategy(int openingRangeMinutes, double stdDevMultiplier)
+ {
+ if (openingRangeMinutes <= 0)
+ {
+ throw new ArgumentException("openingRangeMinutes");
+ }
+
+ if (stdDevMultiplier <= 0.0)
+ {
+ throw new ArgumentException("stdDevMultiplier");
+ }
+
+ _openingRangeMinutes = openingRangeMinutes;
+ _stdDevMultiplier = stdDevMultiplier;
+
+ _currentSessionDate = DateTime.MinValue;
+ _openingRangeStart = DateTime.MinValue;
+ _openingRangeEnd = DateTime.MinValue;
+ _openingRangeHigh = Double.MinValue;
+ _openingRangeLow = Double.MaxValue;
+ _openingRangeReady = false;
+ _tradeTaken = false;
+
+ Metadata = new StrategyMetadata(
+ name: "Simple ORB",
+ description: "Opening Range Breakout strategy",
+ version: "1.0",
+ author: "NT8 SDK Team",
+ symbols: new string[] { "ES", "NQ", "YM" },
+ requiredBars: 20
+ );
+ }
+
+ public void Initialize(StrategyConfig config, IMarketDataProvider dataProvider, ILogger logger)
+ {
+ if (logger == null)
+ {
+ throw new ArgumentNullException("logger");
+ }
+
+ _logger = logger;
+ _logger.LogInformation("SimpleORBStrategy initialized with OR period {0} minutes and multiplier {1:F2}", _openingRangeMinutes, _stdDevMultiplier);
+ }
+
+ public StrategyIntent OnBar(BarData bar, StrategyContext context)
+ {
+ if (bar == null)
+ {
+ throw new ArgumentNullException("bar");
+ }
+
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ try
+ {
+ if (_currentSessionDate != context.CurrentTime.Date)
+ {
+ ResetSession(context.Session.SessionStart);
+ }
+
+ if (bar.Time <= _openingRangeEnd)
+ {
+ UpdateOpeningRange(bar);
+ return null;
+ }
+
+ if (!_openingRangeReady)
+ {
+ if (_openingRangeHigh > _openingRangeLow)
+ {
+ _openingRangeReady = true;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ if (_tradeTaken)
+ {
+ return null;
+ }
+
+ var openingRange = _openingRangeHigh - _openingRangeLow;
+ var volatilityBuffer = openingRange * (_stdDevMultiplier - 1.0);
+ if (volatilityBuffer < 0)
+ {
+ volatilityBuffer = 0;
+ }
+
+ var longTrigger = _openingRangeHigh + volatilityBuffer;
+ var shortTrigger = _openingRangeLow - volatilityBuffer;
+
+ if (bar.Close > longTrigger)
+ {
+ _tradeTaken = true;
+ return CreateIntent(context.Symbol, OrderSide.Buy, openingRange, bar.Close);
+ }
+
+ if (bar.Close < shortTrigger)
+ {
+ _tradeTaken = true;
+ return CreateIntent(context.Symbol, OrderSide.Sell, openingRange, bar.Close);
+ }
+
+ return null;
+ }
+ catch (Exception ex)
+ {
+ if (_logger != null)
+ {
+ _logger.LogError("SimpleORBStrategy OnBar failed: {0}", ex.Message);
+ }
+
+ throw;
+ }
+ }
+
+ public StrategyIntent OnTick(TickData tick, StrategyContext context)
+ {
+ // Most strategies don't need tick-level logic
+ return null;
+ }
+
+ public Dictionary GetParameters()
+ {
+ var parameters = new Dictionary();
+ parameters.Add("opening_range_minutes", _openingRangeMinutes);
+ parameters.Add("std_dev_multiplier", _stdDevMultiplier);
+ return parameters;
+ }
+
+ public void SetParameters(Dictionary parameters)
+ {
+ // Parameters are constructor-bound for deterministic behavior in this wrapper.
+ // Method retained for interface compatibility.
+ }
+
+ private void ResetSession(DateTime sessionStart)
+ {
+ _currentSessionDate = sessionStart.Date;
+ _openingRangeStart = sessionStart;
+ _openingRangeEnd = sessionStart.AddMinutes(_openingRangeMinutes);
+ _openingRangeHigh = Double.MinValue;
+ _openingRangeLow = Double.MaxValue;
+ _openingRangeReady = false;
+ _tradeTaken = false;
+ }
+
+ private void UpdateOpeningRange(BarData bar)
+ {
+ if (bar.High > _openingRangeHigh)
+ {
+ _openingRangeHigh = bar.High;
+ }
+
+ if (bar.Low < _openingRangeLow)
+ {
+ _openingRangeLow = bar.Low;
+ }
+ }
+
+ private StrategyIntent CreateIntent(string symbol, OrderSide side, double openingRange, double lastPrice)
+ {
+ var metadata = new Dictionary();
+ metadata.Add("orb_high", _openingRangeHigh);
+ metadata.Add("orb_low", _openingRangeLow);
+ metadata.Add("orb_range", openingRange);
+ metadata.Add("trigger_price", lastPrice);
+ metadata.Add("multiplier", _stdDevMultiplier);
+
+ if (_logger != null)
+ {
+ _logger.LogInformation("SimpleORBStrategy generated {0} intent for {1}. OR High={2:F2}, OR Low={3:F2}, Last={4:F2}", side, symbol, _openingRangeHigh, _openingRangeLow, lastPrice);
+ }
+
+ return new StrategyIntent(
+ symbol,
+ side,
+ OrderType.Market,
+ null,
+ 8,
+ 16,
+ 0.75,
+ "ORB breakout signal",
+ metadata);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/deployment/backups/20260224_154420/manifest.txt b/deployment/backups/20260224_154420/manifest.txt
new file mode 100644
index 0000000..e081251
--- /dev/null
+++ b/deployment/backups/20260224_154420/manifest.txt
@@ -0,0 +1,6 @@
+Deployment manifest
+Timestamp: 20260224_154420
+Source Core DLL: C:\dev\nt8-sdk\deployment\..\src\NT8.Core\bin\Release\net48\NT8.Core.dll
+Source Adapters DLL: C:\dev\nt8-sdk\deployment\..\src\NT8.Adapters\bin\Release\net48\NT8.Adapters.dll
+Destination Custom Folder: C:\Users\billy\Documents\NinjaTrader 8\bin\Custom
+Destination Strategies Folder: C:\Users\billy\Documents\NinjaTrader 8\bin\Custom\Strategies
diff --git a/deployment/backups/20260224_155513/BaseNT8StrategyWrapper.cs b/deployment/backups/20260224_155513/BaseNT8StrategyWrapper.cs
new file mode 100644
index 0000000..5811382
--- /dev/null
+++ b/deployment/backups/20260224_155513/BaseNT8StrategyWrapper.cs
@@ -0,0 +1,229 @@
+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
+{
+ ///
+ /// Base wrapper class for NT8 strategies that integrate with the SDK
+ /// This is a template that would be extended in actual NT8 strategy files
+ ///
+ 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
+
+ ///
+ /// Stop loss in ticks
+ ///
+ public int StopTicks { get; set; }
+
+ ///
+ /// Profit target in ticks (optional)
+ ///
+ public int TargetTicks { get; set; }
+
+ ///
+ /// Risk amount per trade in dollars
+ ///
+ public double RiskAmount { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Constructor for BaseNT8StrategyWrapper
+ ///
+ 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
+
+ ///
+ /// Create the SDK strategy implementation
+ ///
+ protected abstract IStrategy CreateSdkStrategy();
+
+ #endregion
+
+ #region Public Methods
+
+ ///
+ /// Process a bar update (would be called from NT8's OnBarUpdate)
+ ///
+ 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
+
+ ///
+ /// Initialize SDK components
+ ///
+ 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);
+ }
+
+ ///
+ /// Create SDK configuration from parameters
+ ///
+ 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()
+ );
+
+ // Create strategy configuration
+ _strategyConfig = new StrategyConfig(
+ name: "NT8Strategy",
+ symbol: "Unknown",
+ parameters: new Dictionary(),
+ riskSettings: riskConfig,
+ sizingSettings: sizingConfig
+ );
+ }
+
+ ///
+ /// Execute strategy intent through NT8
+ ///
+ 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
+ }
+}
diff --git a/deployment/backups/20260224_155513/NT8.Adapters.dll b/deployment/backups/20260224_155513/NT8.Adapters.dll
new file mode 100644
index 0000000..0a12355
Binary files /dev/null and b/deployment/backups/20260224_155513/NT8.Adapters.dll differ
diff --git a/deployment/backups/20260224_155513/NT8.Core.dll b/deployment/backups/20260224_155513/NT8.Core.dll
new file mode 100644
index 0000000..ee14e46
Binary files /dev/null and b/deployment/backups/20260224_155513/NT8.Core.dll differ
diff --git a/deployment/backups/20260224_155513/SimpleORBNT8Wrapper.cs b/deployment/backups/20260224_155513/SimpleORBNT8Wrapper.cs
new file mode 100644
index 0000000..1c85459
--- /dev/null
+++ b/deployment/backups/20260224_155513/SimpleORBNT8Wrapper.cs
@@ -0,0 +1,280 @@
+using System;
+using System.Collections.Generic;
+using NT8.Core.Common.Interfaces;
+using NT8.Core.Common.Models;
+using NT8.Core.Logging;
+using NT8.Adapters.NinjaTrader;
+
+namespace NT8.Adapters.Wrappers
+{
+ ///
+ /// Simple ORB (Opening Range Breakout) strategy wrapper for NT8
+ /// This demonstrates how to implement a strategy that works with the SDK
+ ///
+ public class SimpleORBNT8Wrapper : BaseNT8StrategyWrapper
+ {
+ #region Strategy Parameters
+
+ ///
+ /// Opening range period in minutes
+ ///
+ public int OpeningRangeMinutes { get; set; }
+
+ ///
+ /// Number of standard deviations for breakout threshold
+ ///
+ public double StdDevMultiplier { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Constructor for SimpleORBNT8Wrapper
+ ///
+ public SimpleORBNT8Wrapper()
+ {
+ OpeningRangeMinutes = 30;
+ StdDevMultiplier = 1.0;
+ }
+
+ #endregion
+
+ #region Base Class Implementation
+
+ ///
+ /// Exposes adapter reference for integration test assertions.
+ ///
+ public NT8Adapter GetAdapterForTesting()
+ {
+ return _nt8Adapter;
+ }
+
+ ///
+ /// Create the SDK strategy implementation
+ ///
+ protected override IStrategy CreateSdkStrategy()
+ {
+ var openingRangeMinutes = OpeningRangeMinutes > 0 ? OpeningRangeMinutes : 30;
+ var stdDevMultiplier = StdDevMultiplier > 0.0 ? StdDevMultiplier : 1.0;
+ return new SimpleORBStrategy(openingRangeMinutes, stdDevMultiplier);
+ }
+
+ #endregion
+
+ #region Strategy Logic
+
+ ///
+ /// Simple ORB strategy implementation
+ ///
+ private class SimpleORBStrategy : IStrategy
+ {
+ private readonly int _openingRangeMinutes;
+ private readonly double _stdDevMultiplier;
+
+ private ILogger _logger;
+ private DateTime _currentSessionDate;
+ private DateTime _openingRangeStart;
+ private DateTime _openingRangeEnd;
+ private double _openingRangeHigh;
+ private double _openingRangeLow;
+ private bool _openingRangeReady;
+ private bool _tradeTaken;
+
+ public StrategyMetadata Metadata { get; private set; }
+
+ public SimpleORBStrategy(int openingRangeMinutes, double stdDevMultiplier)
+ {
+ if (openingRangeMinutes <= 0)
+ {
+ throw new ArgumentException("openingRangeMinutes");
+ }
+
+ if (stdDevMultiplier <= 0.0)
+ {
+ throw new ArgumentException("stdDevMultiplier");
+ }
+
+ _openingRangeMinutes = openingRangeMinutes;
+ _stdDevMultiplier = stdDevMultiplier;
+
+ _currentSessionDate = DateTime.MinValue;
+ _openingRangeStart = DateTime.MinValue;
+ _openingRangeEnd = DateTime.MinValue;
+ _openingRangeHigh = Double.MinValue;
+ _openingRangeLow = Double.MaxValue;
+ _openingRangeReady = false;
+ _tradeTaken = false;
+
+ Metadata = new StrategyMetadata(
+ name: "Simple ORB",
+ description: "Opening Range Breakout strategy",
+ version: "1.0",
+ author: "NT8 SDK Team",
+ symbols: new string[] { "ES", "NQ", "YM" },
+ requiredBars: 20
+ );
+ }
+
+ public void Initialize(StrategyConfig config, IMarketDataProvider dataProvider, ILogger logger)
+ {
+ if (logger == null)
+ {
+ throw new ArgumentNullException("logger");
+ }
+
+ _logger = logger;
+ _logger.LogInformation("SimpleORBStrategy initialized with OR period {0} minutes and multiplier {1:F2}", _openingRangeMinutes, _stdDevMultiplier);
+ }
+
+ public StrategyIntent OnBar(BarData bar, StrategyContext context)
+ {
+ if (bar == null)
+ {
+ throw new ArgumentNullException("bar");
+ }
+
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ try
+ {
+ if (_currentSessionDate != context.CurrentTime.Date)
+ {
+ ResetSession(context.Session.SessionStart);
+ }
+
+ if (bar.Time <= _openingRangeEnd)
+ {
+ UpdateOpeningRange(bar);
+ return null;
+ }
+
+ if (!_openingRangeReady)
+ {
+ if (_openingRangeHigh > _openingRangeLow)
+ {
+ _openingRangeReady = true;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ if (_tradeTaken)
+ {
+ return null;
+ }
+
+ var openingRange = _openingRangeHigh - _openingRangeLow;
+ var volatilityBuffer = openingRange * (_stdDevMultiplier - 1.0);
+ if (volatilityBuffer < 0)
+ {
+ volatilityBuffer = 0;
+ }
+
+ var longTrigger = _openingRangeHigh + volatilityBuffer;
+ var shortTrigger = _openingRangeLow - volatilityBuffer;
+
+ if (bar.Close > longTrigger)
+ {
+ _tradeTaken = true;
+ return CreateIntent(context.Symbol, OrderSide.Buy, openingRange, bar.Close);
+ }
+
+ if (bar.Close < shortTrigger)
+ {
+ _tradeTaken = true;
+ return CreateIntent(context.Symbol, OrderSide.Sell, openingRange, bar.Close);
+ }
+
+ return null;
+ }
+ catch (Exception ex)
+ {
+ if (_logger != null)
+ {
+ _logger.LogError("SimpleORBStrategy OnBar failed: {0}", ex.Message);
+ }
+
+ throw;
+ }
+ }
+
+ public StrategyIntent OnTick(TickData tick, StrategyContext context)
+ {
+ // Most strategies don't need tick-level logic
+ return null;
+ }
+
+ public Dictionary GetParameters()
+ {
+ var parameters = new Dictionary();
+ parameters.Add("opening_range_minutes", _openingRangeMinutes);
+ parameters.Add("std_dev_multiplier", _stdDevMultiplier);
+ return parameters;
+ }
+
+ public void SetParameters(Dictionary parameters)
+ {
+ // Parameters are constructor-bound for deterministic behavior in this wrapper.
+ // Method retained for interface compatibility.
+ }
+
+ private void ResetSession(DateTime sessionStart)
+ {
+ _currentSessionDate = sessionStart.Date;
+ _openingRangeStart = sessionStart;
+ _openingRangeEnd = sessionStart.AddMinutes(_openingRangeMinutes);
+ _openingRangeHigh = Double.MinValue;
+ _openingRangeLow = Double.MaxValue;
+ _openingRangeReady = false;
+ _tradeTaken = false;
+ }
+
+ private void UpdateOpeningRange(BarData bar)
+ {
+ if (bar.High > _openingRangeHigh)
+ {
+ _openingRangeHigh = bar.High;
+ }
+
+ if (bar.Low < _openingRangeLow)
+ {
+ _openingRangeLow = bar.Low;
+ }
+ }
+
+ private StrategyIntent CreateIntent(string symbol, OrderSide side, double openingRange, double lastPrice)
+ {
+ var metadata = new Dictionary();
+ metadata.Add("orb_high", _openingRangeHigh);
+ metadata.Add("orb_low", _openingRangeLow);
+ metadata.Add("orb_range", openingRange);
+ metadata.Add("trigger_price", lastPrice);
+ metadata.Add("multiplier", _stdDevMultiplier);
+
+ if (_logger != null)
+ {
+ _logger.LogInformation("SimpleORBStrategy generated {0} intent for {1}. OR High={2:F2}, OR Low={3:F2}, Last={4:F2}", side, symbol, _openingRangeHigh, _openingRangeLow, lastPrice);
+ }
+
+ return new StrategyIntent(
+ symbol,
+ side,
+ OrderType.Market,
+ null,
+ 8,
+ 16,
+ 0.75,
+ "ORB breakout signal",
+ metadata);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/deployment/backups/20260224_155513/manifest.txt b/deployment/backups/20260224_155513/manifest.txt
new file mode 100644
index 0000000..d76899b
--- /dev/null
+++ b/deployment/backups/20260224_155513/manifest.txt
@@ -0,0 +1,6 @@
+Deployment manifest
+Timestamp: 20260224_155513
+Source Core DLL: C:\dev\nt8-sdk\deployment\..\src\NT8.Core\bin\Release\net48\NT8.Core.dll
+Source Adapters DLL: C:\dev\nt8-sdk\deployment\..\src\NT8.Adapters\bin\Release\net48\NT8.Adapters.dll
+Destination Custom Folder: C:\Users\billy\Documents\NinjaTrader 8\bin\Custom
+Destination Strategies Folder: C:\Users\billy\Documents\NinjaTrader 8\bin\Custom\Strategies
diff --git a/deployment/backups/20260224_160009/BaseNT8StrategyWrapper.cs b/deployment/backups/20260224_160009/BaseNT8StrategyWrapper.cs
new file mode 100644
index 0000000..5811382
--- /dev/null
+++ b/deployment/backups/20260224_160009/BaseNT8StrategyWrapper.cs
@@ -0,0 +1,229 @@
+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
+{
+ ///
+ /// Base wrapper class for NT8 strategies that integrate with the SDK
+ /// This is a template that would be extended in actual NT8 strategy files
+ ///
+ 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
+
+ ///
+ /// Stop loss in ticks
+ ///
+ public int StopTicks { get; set; }
+
+ ///
+ /// Profit target in ticks (optional)
+ ///
+ public int TargetTicks { get; set; }
+
+ ///
+ /// Risk amount per trade in dollars
+ ///
+ public double RiskAmount { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Constructor for BaseNT8StrategyWrapper
+ ///
+ 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
+
+ ///
+ /// Create the SDK strategy implementation
+ ///
+ protected abstract IStrategy CreateSdkStrategy();
+
+ #endregion
+
+ #region Public Methods
+
+ ///
+ /// Process a bar update (would be called from NT8's OnBarUpdate)
+ ///
+ 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
+
+ ///
+ /// Initialize SDK components
+ ///
+ 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);
+ }
+
+ ///
+ /// Create SDK configuration from parameters
+ ///
+ 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()
+ );
+
+ // Create strategy configuration
+ _strategyConfig = new StrategyConfig(
+ name: "NT8Strategy",
+ symbol: "Unknown",
+ parameters: new Dictionary(),
+ riskSettings: riskConfig,
+ sizingSettings: sizingConfig
+ );
+ }
+
+ ///
+ /// Execute strategy intent through NT8
+ ///
+ 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
+ }
+}
diff --git a/deployment/backups/20260224_160009/NT8.Adapters.dll b/deployment/backups/20260224_160009/NT8.Adapters.dll
new file mode 100644
index 0000000..0a12355
Binary files /dev/null and b/deployment/backups/20260224_160009/NT8.Adapters.dll differ
diff --git a/deployment/backups/20260224_160009/NT8.Core.dll b/deployment/backups/20260224_160009/NT8.Core.dll
new file mode 100644
index 0000000..ee14e46
Binary files /dev/null and b/deployment/backups/20260224_160009/NT8.Core.dll differ
diff --git a/deployment/backups/20260224_160009/SimpleORBNT8Wrapper.cs b/deployment/backups/20260224_160009/SimpleORBNT8Wrapper.cs
new file mode 100644
index 0000000..1c85459
--- /dev/null
+++ b/deployment/backups/20260224_160009/SimpleORBNT8Wrapper.cs
@@ -0,0 +1,280 @@
+using System;
+using System.Collections.Generic;
+using NT8.Core.Common.Interfaces;
+using NT8.Core.Common.Models;
+using NT8.Core.Logging;
+using NT8.Adapters.NinjaTrader;
+
+namespace NT8.Adapters.Wrappers
+{
+ ///
+ /// Simple ORB (Opening Range Breakout) strategy wrapper for NT8
+ /// This demonstrates how to implement a strategy that works with the SDK
+ ///
+ public class SimpleORBNT8Wrapper : BaseNT8StrategyWrapper
+ {
+ #region Strategy Parameters
+
+ ///
+ /// Opening range period in minutes
+ ///
+ public int OpeningRangeMinutes { get; set; }
+
+ ///
+ /// Number of standard deviations for breakout threshold
+ ///
+ public double StdDevMultiplier { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Constructor for SimpleORBNT8Wrapper
+ ///
+ public SimpleORBNT8Wrapper()
+ {
+ OpeningRangeMinutes = 30;
+ StdDevMultiplier = 1.0;
+ }
+
+ #endregion
+
+ #region Base Class Implementation
+
+ ///
+ /// Exposes adapter reference for integration test assertions.
+ ///
+ public NT8Adapter GetAdapterForTesting()
+ {
+ return _nt8Adapter;
+ }
+
+ ///
+ /// Create the SDK strategy implementation
+ ///
+ protected override IStrategy CreateSdkStrategy()
+ {
+ var openingRangeMinutes = OpeningRangeMinutes > 0 ? OpeningRangeMinutes : 30;
+ var stdDevMultiplier = StdDevMultiplier > 0.0 ? StdDevMultiplier : 1.0;
+ return new SimpleORBStrategy(openingRangeMinutes, stdDevMultiplier);
+ }
+
+ #endregion
+
+ #region Strategy Logic
+
+ ///
+ /// Simple ORB strategy implementation
+ ///
+ private class SimpleORBStrategy : IStrategy
+ {
+ private readonly int _openingRangeMinutes;
+ private readonly double _stdDevMultiplier;
+
+ private ILogger _logger;
+ private DateTime _currentSessionDate;
+ private DateTime _openingRangeStart;
+ private DateTime _openingRangeEnd;
+ private double _openingRangeHigh;
+ private double _openingRangeLow;
+ private bool _openingRangeReady;
+ private bool _tradeTaken;
+
+ public StrategyMetadata Metadata { get; private set; }
+
+ public SimpleORBStrategy(int openingRangeMinutes, double stdDevMultiplier)
+ {
+ if (openingRangeMinutes <= 0)
+ {
+ throw new ArgumentException("openingRangeMinutes");
+ }
+
+ if (stdDevMultiplier <= 0.0)
+ {
+ throw new ArgumentException("stdDevMultiplier");
+ }
+
+ _openingRangeMinutes = openingRangeMinutes;
+ _stdDevMultiplier = stdDevMultiplier;
+
+ _currentSessionDate = DateTime.MinValue;
+ _openingRangeStart = DateTime.MinValue;
+ _openingRangeEnd = DateTime.MinValue;
+ _openingRangeHigh = Double.MinValue;
+ _openingRangeLow = Double.MaxValue;
+ _openingRangeReady = false;
+ _tradeTaken = false;
+
+ Metadata = new StrategyMetadata(
+ name: "Simple ORB",
+ description: "Opening Range Breakout strategy",
+ version: "1.0",
+ author: "NT8 SDK Team",
+ symbols: new string[] { "ES", "NQ", "YM" },
+ requiredBars: 20
+ );
+ }
+
+ public void Initialize(StrategyConfig config, IMarketDataProvider dataProvider, ILogger logger)
+ {
+ if (logger == null)
+ {
+ throw new ArgumentNullException("logger");
+ }
+
+ _logger = logger;
+ _logger.LogInformation("SimpleORBStrategy initialized with OR period {0} minutes and multiplier {1:F2}", _openingRangeMinutes, _stdDevMultiplier);
+ }
+
+ public StrategyIntent OnBar(BarData bar, StrategyContext context)
+ {
+ if (bar == null)
+ {
+ throw new ArgumentNullException("bar");
+ }
+
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ try
+ {
+ if (_currentSessionDate != context.CurrentTime.Date)
+ {
+ ResetSession(context.Session.SessionStart);
+ }
+
+ if (bar.Time <= _openingRangeEnd)
+ {
+ UpdateOpeningRange(bar);
+ return null;
+ }
+
+ if (!_openingRangeReady)
+ {
+ if (_openingRangeHigh > _openingRangeLow)
+ {
+ _openingRangeReady = true;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ if (_tradeTaken)
+ {
+ return null;
+ }
+
+ var openingRange = _openingRangeHigh - _openingRangeLow;
+ var volatilityBuffer = openingRange * (_stdDevMultiplier - 1.0);
+ if (volatilityBuffer < 0)
+ {
+ volatilityBuffer = 0;
+ }
+
+ var longTrigger = _openingRangeHigh + volatilityBuffer;
+ var shortTrigger = _openingRangeLow - volatilityBuffer;
+
+ if (bar.Close > longTrigger)
+ {
+ _tradeTaken = true;
+ return CreateIntent(context.Symbol, OrderSide.Buy, openingRange, bar.Close);
+ }
+
+ if (bar.Close < shortTrigger)
+ {
+ _tradeTaken = true;
+ return CreateIntent(context.Symbol, OrderSide.Sell, openingRange, bar.Close);
+ }
+
+ return null;
+ }
+ catch (Exception ex)
+ {
+ if (_logger != null)
+ {
+ _logger.LogError("SimpleORBStrategy OnBar failed: {0}", ex.Message);
+ }
+
+ throw;
+ }
+ }
+
+ public StrategyIntent OnTick(TickData tick, StrategyContext context)
+ {
+ // Most strategies don't need tick-level logic
+ return null;
+ }
+
+ public Dictionary GetParameters()
+ {
+ var parameters = new Dictionary();
+ parameters.Add("opening_range_minutes", _openingRangeMinutes);
+ parameters.Add("std_dev_multiplier", _stdDevMultiplier);
+ return parameters;
+ }
+
+ public void SetParameters(Dictionary parameters)
+ {
+ // Parameters are constructor-bound for deterministic behavior in this wrapper.
+ // Method retained for interface compatibility.
+ }
+
+ private void ResetSession(DateTime sessionStart)
+ {
+ _currentSessionDate = sessionStart.Date;
+ _openingRangeStart = sessionStart;
+ _openingRangeEnd = sessionStart.AddMinutes(_openingRangeMinutes);
+ _openingRangeHigh = Double.MinValue;
+ _openingRangeLow = Double.MaxValue;
+ _openingRangeReady = false;
+ _tradeTaken = false;
+ }
+
+ private void UpdateOpeningRange(BarData bar)
+ {
+ if (bar.High > _openingRangeHigh)
+ {
+ _openingRangeHigh = bar.High;
+ }
+
+ if (bar.Low < _openingRangeLow)
+ {
+ _openingRangeLow = bar.Low;
+ }
+ }
+
+ private StrategyIntent CreateIntent(string symbol, OrderSide side, double openingRange, double lastPrice)
+ {
+ var metadata = new Dictionary();
+ metadata.Add("orb_high", _openingRangeHigh);
+ metadata.Add("orb_low", _openingRangeLow);
+ metadata.Add("orb_range", openingRange);
+ metadata.Add("trigger_price", lastPrice);
+ metadata.Add("multiplier", _stdDevMultiplier);
+
+ if (_logger != null)
+ {
+ _logger.LogInformation("SimpleORBStrategy generated {0} intent for {1}. OR High={2:F2}, OR Low={3:F2}, Last={4:F2}", side, symbol, _openingRangeHigh, _openingRangeLow, lastPrice);
+ }
+
+ return new StrategyIntent(
+ symbol,
+ side,
+ OrderType.Market,
+ null,
+ 8,
+ 16,
+ 0.75,
+ "ORB breakout signal",
+ metadata);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/deployment/backups/20260224_160009/manifest.txt b/deployment/backups/20260224_160009/manifest.txt
new file mode 100644
index 0000000..0797593
--- /dev/null
+++ b/deployment/backups/20260224_160009/manifest.txt
@@ -0,0 +1,6 @@
+Deployment manifest
+Timestamp: 20260224_160009
+Source Core DLL: C:\dev\nt8-sdk\deployment\..\src\NT8.Core\bin\Release\net48\NT8.Core.dll
+Source Adapters DLL: C:\dev\nt8-sdk\deployment\..\src\NT8.Adapters\bin\Release\net48\NT8.Adapters.dll
+Destination Custom Folder: C:\Users\billy\Documents\NinjaTrader 8\bin\Custom
+Destination Strategies Folder: C:\Users\billy\Documents\NinjaTrader 8\bin\Custom\Strategies
diff --git a/deployment/backups/20260224_160457/BaseNT8StrategyWrapper.cs b/deployment/backups/20260224_160457/BaseNT8StrategyWrapper.cs
new file mode 100644
index 0000000..5811382
--- /dev/null
+++ b/deployment/backups/20260224_160457/BaseNT8StrategyWrapper.cs
@@ -0,0 +1,229 @@
+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
+{
+ ///
+ /// Base wrapper class for NT8 strategies that integrate with the SDK
+ /// This is a template that would be extended in actual NT8 strategy files
+ ///
+ 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
+
+ ///
+ /// Stop loss in ticks
+ ///
+ public int StopTicks { get; set; }
+
+ ///
+ /// Profit target in ticks (optional)
+ ///
+ public int TargetTicks { get; set; }
+
+ ///
+ /// Risk amount per trade in dollars
+ ///
+ public double RiskAmount { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Constructor for BaseNT8StrategyWrapper
+ ///
+ 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
+
+ ///
+ /// Create the SDK strategy implementation
+ ///
+ protected abstract IStrategy CreateSdkStrategy();
+
+ #endregion
+
+ #region Public Methods
+
+ ///
+ /// Process a bar update (would be called from NT8's OnBarUpdate)
+ ///
+ 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
+
+ ///
+ /// Initialize SDK components
+ ///
+ 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);
+ }
+
+ ///
+ /// Create SDK configuration from parameters
+ ///
+ 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()
+ );
+
+ // Create strategy configuration
+ _strategyConfig = new StrategyConfig(
+ name: "NT8Strategy",
+ symbol: "Unknown",
+ parameters: new Dictionary(),
+ riskSettings: riskConfig,
+ sizingSettings: sizingConfig
+ );
+ }
+
+ ///
+ /// Execute strategy intent through NT8
+ ///
+ 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
+ }
+}
diff --git a/deployment/backups/20260224_160457/NT8.Adapters.dll b/deployment/backups/20260224_160457/NT8.Adapters.dll
new file mode 100644
index 0000000..0a12355
Binary files /dev/null and b/deployment/backups/20260224_160457/NT8.Adapters.dll differ
diff --git a/deployment/backups/20260224_160457/NT8.Core.dll b/deployment/backups/20260224_160457/NT8.Core.dll
new file mode 100644
index 0000000..ee14e46
Binary files /dev/null and b/deployment/backups/20260224_160457/NT8.Core.dll differ
diff --git a/deployment/backups/20260224_160457/SimpleORBNT8Wrapper.cs b/deployment/backups/20260224_160457/SimpleORBNT8Wrapper.cs
new file mode 100644
index 0000000..1c85459
--- /dev/null
+++ b/deployment/backups/20260224_160457/SimpleORBNT8Wrapper.cs
@@ -0,0 +1,280 @@
+using System;
+using System.Collections.Generic;
+using NT8.Core.Common.Interfaces;
+using NT8.Core.Common.Models;
+using NT8.Core.Logging;
+using NT8.Adapters.NinjaTrader;
+
+namespace NT8.Adapters.Wrappers
+{
+ ///
+ /// Simple ORB (Opening Range Breakout) strategy wrapper for NT8
+ /// This demonstrates how to implement a strategy that works with the SDK
+ ///
+ public class SimpleORBNT8Wrapper : BaseNT8StrategyWrapper
+ {
+ #region Strategy Parameters
+
+ ///
+ /// Opening range period in minutes
+ ///
+ public int OpeningRangeMinutes { get; set; }
+
+ ///
+ /// Number of standard deviations for breakout threshold
+ ///
+ public double StdDevMultiplier { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Constructor for SimpleORBNT8Wrapper
+ ///
+ public SimpleORBNT8Wrapper()
+ {
+ OpeningRangeMinutes = 30;
+ StdDevMultiplier = 1.0;
+ }
+
+ #endregion
+
+ #region Base Class Implementation
+
+ ///
+ /// Exposes adapter reference for integration test assertions.
+ ///
+ public NT8Adapter GetAdapterForTesting()
+ {
+ return _nt8Adapter;
+ }
+
+ ///
+ /// Create the SDK strategy implementation
+ ///
+ protected override IStrategy CreateSdkStrategy()
+ {
+ var openingRangeMinutes = OpeningRangeMinutes > 0 ? OpeningRangeMinutes : 30;
+ var stdDevMultiplier = StdDevMultiplier > 0.0 ? StdDevMultiplier : 1.0;
+ return new SimpleORBStrategy(openingRangeMinutes, stdDevMultiplier);
+ }
+
+ #endregion
+
+ #region Strategy Logic
+
+ ///
+ /// Simple ORB strategy implementation
+ ///
+ private class SimpleORBStrategy : IStrategy
+ {
+ private readonly int _openingRangeMinutes;
+ private readonly double _stdDevMultiplier;
+
+ private ILogger _logger;
+ private DateTime _currentSessionDate;
+ private DateTime _openingRangeStart;
+ private DateTime _openingRangeEnd;
+ private double _openingRangeHigh;
+ private double _openingRangeLow;
+ private bool _openingRangeReady;
+ private bool _tradeTaken;
+
+ public StrategyMetadata Metadata { get; private set; }
+
+ public SimpleORBStrategy(int openingRangeMinutes, double stdDevMultiplier)
+ {
+ if (openingRangeMinutes <= 0)
+ {
+ throw new ArgumentException("openingRangeMinutes");
+ }
+
+ if (stdDevMultiplier <= 0.0)
+ {
+ throw new ArgumentException("stdDevMultiplier");
+ }
+
+ _openingRangeMinutes = openingRangeMinutes;
+ _stdDevMultiplier = stdDevMultiplier;
+
+ _currentSessionDate = DateTime.MinValue;
+ _openingRangeStart = DateTime.MinValue;
+ _openingRangeEnd = DateTime.MinValue;
+ _openingRangeHigh = Double.MinValue;
+ _openingRangeLow = Double.MaxValue;
+ _openingRangeReady = false;
+ _tradeTaken = false;
+
+ Metadata = new StrategyMetadata(
+ name: "Simple ORB",
+ description: "Opening Range Breakout strategy",
+ version: "1.0",
+ author: "NT8 SDK Team",
+ symbols: new string[] { "ES", "NQ", "YM" },
+ requiredBars: 20
+ );
+ }
+
+ public void Initialize(StrategyConfig config, IMarketDataProvider dataProvider, ILogger logger)
+ {
+ if (logger == null)
+ {
+ throw new ArgumentNullException("logger");
+ }
+
+ _logger = logger;
+ _logger.LogInformation("SimpleORBStrategy initialized with OR period {0} minutes and multiplier {1:F2}", _openingRangeMinutes, _stdDevMultiplier);
+ }
+
+ public StrategyIntent OnBar(BarData bar, StrategyContext context)
+ {
+ if (bar == null)
+ {
+ throw new ArgumentNullException("bar");
+ }
+
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ try
+ {
+ if (_currentSessionDate != context.CurrentTime.Date)
+ {
+ ResetSession(context.Session.SessionStart);
+ }
+
+ if (bar.Time <= _openingRangeEnd)
+ {
+ UpdateOpeningRange(bar);
+ return null;
+ }
+
+ if (!_openingRangeReady)
+ {
+ if (_openingRangeHigh > _openingRangeLow)
+ {
+ _openingRangeReady = true;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ if (_tradeTaken)
+ {
+ return null;
+ }
+
+ var openingRange = _openingRangeHigh - _openingRangeLow;
+ var volatilityBuffer = openingRange * (_stdDevMultiplier - 1.0);
+ if (volatilityBuffer < 0)
+ {
+ volatilityBuffer = 0;
+ }
+
+ var longTrigger = _openingRangeHigh + volatilityBuffer;
+ var shortTrigger = _openingRangeLow - volatilityBuffer;
+
+ if (bar.Close > longTrigger)
+ {
+ _tradeTaken = true;
+ return CreateIntent(context.Symbol, OrderSide.Buy, openingRange, bar.Close);
+ }
+
+ if (bar.Close < shortTrigger)
+ {
+ _tradeTaken = true;
+ return CreateIntent(context.Symbol, OrderSide.Sell, openingRange, bar.Close);
+ }
+
+ return null;
+ }
+ catch (Exception ex)
+ {
+ if (_logger != null)
+ {
+ _logger.LogError("SimpleORBStrategy OnBar failed: {0}", ex.Message);
+ }
+
+ throw;
+ }
+ }
+
+ public StrategyIntent OnTick(TickData tick, StrategyContext context)
+ {
+ // Most strategies don't need tick-level logic
+ return null;
+ }
+
+ public Dictionary GetParameters()
+ {
+ var parameters = new Dictionary();
+ parameters.Add("opening_range_minutes", _openingRangeMinutes);
+ parameters.Add("std_dev_multiplier", _stdDevMultiplier);
+ return parameters;
+ }
+
+ public void SetParameters(Dictionary parameters)
+ {
+ // Parameters are constructor-bound for deterministic behavior in this wrapper.
+ // Method retained for interface compatibility.
+ }
+
+ private void ResetSession(DateTime sessionStart)
+ {
+ _currentSessionDate = sessionStart.Date;
+ _openingRangeStart = sessionStart;
+ _openingRangeEnd = sessionStart.AddMinutes(_openingRangeMinutes);
+ _openingRangeHigh = Double.MinValue;
+ _openingRangeLow = Double.MaxValue;
+ _openingRangeReady = false;
+ _tradeTaken = false;
+ }
+
+ private void UpdateOpeningRange(BarData bar)
+ {
+ if (bar.High > _openingRangeHigh)
+ {
+ _openingRangeHigh = bar.High;
+ }
+
+ if (bar.Low < _openingRangeLow)
+ {
+ _openingRangeLow = bar.Low;
+ }
+ }
+
+ private StrategyIntent CreateIntent(string symbol, OrderSide side, double openingRange, double lastPrice)
+ {
+ var metadata = new Dictionary();
+ metadata.Add("orb_high", _openingRangeHigh);
+ metadata.Add("orb_low", _openingRangeLow);
+ metadata.Add("orb_range", openingRange);
+ metadata.Add("trigger_price", lastPrice);
+ metadata.Add("multiplier", _stdDevMultiplier);
+
+ if (_logger != null)
+ {
+ _logger.LogInformation("SimpleORBStrategy generated {0} intent for {1}. OR High={2:F2}, OR Low={3:F2}, Last={4:F2}", side, symbol, _openingRangeHigh, _openingRangeLow, lastPrice);
+ }
+
+ return new StrategyIntent(
+ symbol,
+ side,
+ OrderType.Market,
+ null,
+ 8,
+ 16,
+ 0.75,
+ "ORB breakout signal",
+ metadata);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/deployment/backups/20260224_160457/manifest.txt b/deployment/backups/20260224_160457/manifest.txt
new file mode 100644
index 0000000..61acc31
--- /dev/null
+++ b/deployment/backups/20260224_160457/manifest.txt
@@ -0,0 +1,6 @@
+Deployment manifest
+Timestamp: 20260224_160457
+Source Core DLL: C:\dev\nt8-sdk\deployment\..\src\NT8.Core\bin\Release\net48\NT8.Core.dll
+Source Adapters DLL: C:\dev\nt8-sdk\deployment\..\src\NT8.Adapters\bin\Release\net48\NT8.Adapters.dll
+Destination Custom Folder: C:\Users\billy\Documents\NinjaTrader 8\bin\Custom
+Destination Strategies Folder: C:\Users\billy\Documents\NinjaTrader 8\bin\Custom\Strategies
diff --git a/deployment/backups/20260224_165037/BaseNT8StrategyWrapper.cs b/deployment/backups/20260224_165037/BaseNT8StrategyWrapper.cs
new file mode 100644
index 0000000..5811382
--- /dev/null
+++ b/deployment/backups/20260224_165037/BaseNT8StrategyWrapper.cs
@@ -0,0 +1,229 @@
+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
+{
+ ///
+ /// Base wrapper class for NT8 strategies that integrate with the SDK
+ /// This is a template that would be extended in actual NT8 strategy files
+ ///
+ 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
+
+ ///
+ /// Stop loss in ticks
+ ///
+ public int StopTicks { get; set; }
+
+ ///
+ /// Profit target in ticks (optional)
+ ///
+ public int TargetTicks { get; set; }
+
+ ///
+ /// Risk amount per trade in dollars
+ ///
+ public double RiskAmount { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Constructor for BaseNT8StrategyWrapper
+ ///
+ 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
+
+ ///
+ /// Create the SDK strategy implementation
+ ///
+ protected abstract IStrategy CreateSdkStrategy();
+
+ #endregion
+
+ #region Public Methods
+
+ ///
+ /// Process a bar update (would be called from NT8's OnBarUpdate)
+ ///
+ 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
+
+ ///
+ /// Initialize SDK components
+ ///
+ 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);
+ }
+
+ ///
+ /// Create SDK configuration from parameters
+ ///
+ 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()
+ );
+
+ // Create strategy configuration
+ _strategyConfig = new StrategyConfig(
+ name: "NT8Strategy",
+ symbol: "Unknown",
+ parameters: new Dictionary(),
+ riskSettings: riskConfig,
+ sizingSettings: sizingConfig
+ );
+ }
+
+ ///
+ /// Execute strategy intent through NT8
+ ///
+ 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
+ }
+}
diff --git a/deployment/backups/20260224_165037/NT8.Adapters.dll b/deployment/backups/20260224_165037/NT8.Adapters.dll
new file mode 100644
index 0000000..0a12355
Binary files /dev/null and b/deployment/backups/20260224_165037/NT8.Adapters.dll differ
diff --git a/deployment/backups/20260224_165037/NT8.Core.dll b/deployment/backups/20260224_165037/NT8.Core.dll
new file mode 100644
index 0000000..ee14e46
Binary files /dev/null and b/deployment/backups/20260224_165037/NT8.Core.dll differ
diff --git a/deployment/backups/20260224_165037/SimpleORBNT8Wrapper.cs b/deployment/backups/20260224_165037/SimpleORBNT8Wrapper.cs
new file mode 100644
index 0000000..1c85459
--- /dev/null
+++ b/deployment/backups/20260224_165037/SimpleORBNT8Wrapper.cs
@@ -0,0 +1,280 @@
+using System;
+using System.Collections.Generic;
+using NT8.Core.Common.Interfaces;
+using NT8.Core.Common.Models;
+using NT8.Core.Logging;
+using NT8.Adapters.NinjaTrader;
+
+namespace NT8.Adapters.Wrappers
+{
+ ///
+ /// Simple ORB (Opening Range Breakout) strategy wrapper for NT8
+ /// This demonstrates how to implement a strategy that works with the SDK
+ ///
+ public class SimpleORBNT8Wrapper : BaseNT8StrategyWrapper
+ {
+ #region Strategy Parameters
+
+ ///
+ /// Opening range period in minutes
+ ///
+ public int OpeningRangeMinutes { get; set; }
+
+ ///
+ /// Number of standard deviations for breakout threshold
+ ///
+ public double StdDevMultiplier { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Constructor for SimpleORBNT8Wrapper
+ ///
+ public SimpleORBNT8Wrapper()
+ {
+ OpeningRangeMinutes = 30;
+ StdDevMultiplier = 1.0;
+ }
+
+ #endregion
+
+ #region Base Class Implementation
+
+ ///
+ /// Exposes adapter reference for integration test assertions.
+ ///
+ public NT8Adapter GetAdapterForTesting()
+ {
+ return _nt8Adapter;
+ }
+
+ ///
+ /// Create the SDK strategy implementation
+ ///
+ protected override IStrategy CreateSdkStrategy()
+ {
+ var openingRangeMinutes = OpeningRangeMinutes > 0 ? OpeningRangeMinutes : 30;
+ var stdDevMultiplier = StdDevMultiplier > 0.0 ? StdDevMultiplier : 1.0;
+ return new SimpleORBStrategy(openingRangeMinutes, stdDevMultiplier);
+ }
+
+ #endregion
+
+ #region Strategy Logic
+
+ ///
+ /// Simple ORB strategy implementation
+ ///
+ private class SimpleORBStrategy : IStrategy
+ {
+ private readonly int _openingRangeMinutes;
+ private readonly double _stdDevMultiplier;
+
+ private ILogger _logger;
+ private DateTime _currentSessionDate;
+ private DateTime _openingRangeStart;
+ private DateTime _openingRangeEnd;
+ private double _openingRangeHigh;
+ private double _openingRangeLow;
+ private bool _openingRangeReady;
+ private bool _tradeTaken;
+
+ public StrategyMetadata Metadata { get; private set; }
+
+ public SimpleORBStrategy(int openingRangeMinutes, double stdDevMultiplier)
+ {
+ if (openingRangeMinutes <= 0)
+ {
+ throw new ArgumentException("openingRangeMinutes");
+ }
+
+ if (stdDevMultiplier <= 0.0)
+ {
+ throw new ArgumentException("stdDevMultiplier");
+ }
+
+ _openingRangeMinutes = openingRangeMinutes;
+ _stdDevMultiplier = stdDevMultiplier;
+
+ _currentSessionDate = DateTime.MinValue;
+ _openingRangeStart = DateTime.MinValue;
+ _openingRangeEnd = DateTime.MinValue;
+ _openingRangeHigh = Double.MinValue;
+ _openingRangeLow = Double.MaxValue;
+ _openingRangeReady = false;
+ _tradeTaken = false;
+
+ Metadata = new StrategyMetadata(
+ name: "Simple ORB",
+ description: "Opening Range Breakout strategy",
+ version: "1.0",
+ author: "NT8 SDK Team",
+ symbols: new string[] { "ES", "NQ", "YM" },
+ requiredBars: 20
+ );
+ }
+
+ public void Initialize(StrategyConfig config, IMarketDataProvider dataProvider, ILogger logger)
+ {
+ if (logger == null)
+ {
+ throw new ArgumentNullException("logger");
+ }
+
+ _logger = logger;
+ _logger.LogInformation("SimpleORBStrategy initialized with OR period {0} minutes and multiplier {1:F2}", _openingRangeMinutes, _stdDevMultiplier);
+ }
+
+ public StrategyIntent OnBar(BarData bar, StrategyContext context)
+ {
+ if (bar == null)
+ {
+ throw new ArgumentNullException("bar");
+ }
+
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ try
+ {
+ if (_currentSessionDate != context.CurrentTime.Date)
+ {
+ ResetSession(context.Session.SessionStart);
+ }
+
+ if (bar.Time <= _openingRangeEnd)
+ {
+ UpdateOpeningRange(bar);
+ return null;
+ }
+
+ if (!_openingRangeReady)
+ {
+ if (_openingRangeHigh > _openingRangeLow)
+ {
+ _openingRangeReady = true;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ if (_tradeTaken)
+ {
+ return null;
+ }
+
+ var openingRange = _openingRangeHigh - _openingRangeLow;
+ var volatilityBuffer = openingRange * (_stdDevMultiplier - 1.0);
+ if (volatilityBuffer < 0)
+ {
+ volatilityBuffer = 0;
+ }
+
+ var longTrigger = _openingRangeHigh + volatilityBuffer;
+ var shortTrigger = _openingRangeLow - volatilityBuffer;
+
+ if (bar.Close > longTrigger)
+ {
+ _tradeTaken = true;
+ return CreateIntent(context.Symbol, OrderSide.Buy, openingRange, bar.Close);
+ }
+
+ if (bar.Close < shortTrigger)
+ {
+ _tradeTaken = true;
+ return CreateIntent(context.Symbol, OrderSide.Sell, openingRange, bar.Close);
+ }
+
+ return null;
+ }
+ catch (Exception ex)
+ {
+ if (_logger != null)
+ {
+ _logger.LogError("SimpleORBStrategy OnBar failed: {0}", ex.Message);
+ }
+
+ throw;
+ }
+ }
+
+ public StrategyIntent OnTick(TickData tick, StrategyContext context)
+ {
+ // Most strategies don't need tick-level logic
+ return null;
+ }
+
+ public Dictionary GetParameters()
+ {
+ var parameters = new Dictionary();
+ parameters.Add("opening_range_minutes", _openingRangeMinutes);
+ parameters.Add("std_dev_multiplier", _stdDevMultiplier);
+ return parameters;
+ }
+
+ public void SetParameters(Dictionary parameters)
+ {
+ // Parameters are constructor-bound for deterministic behavior in this wrapper.
+ // Method retained for interface compatibility.
+ }
+
+ private void ResetSession(DateTime sessionStart)
+ {
+ _currentSessionDate = sessionStart.Date;
+ _openingRangeStart = sessionStart;
+ _openingRangeEnd = sessionStart.AddMinutes(_openingRangeMinutes);
+ _openingRangeHigh = Double.MinValue;
+ _openingRangeLow = Double.MaxValue;
+ _openingRangeReady = false;
+ _tradeTaken = false;
+ }
+
+ private void UpdateOpeningRange(BarData bar)
+ {
+ if (bar.High > _openingRangeHigh)
+ {
+ _openingRangeHigh = bar.High;
+ }
+
+ if (bar.Low < _openingRangeLow)
+ {
+ _openingRangeLow = bar.Low;
+ }
+ }
+
+ private StrategyIntent CreateIntent(string symbol, OrderSide side, double openingRange, double lastPrice)
+ {
+ var metadata = new Dictionary();
+ metadata.Add("orb_high", _openingRangeHigh);
+ metadata.Add("orb_low", _openingRangeLow);
+ metadata.Add("orb_range", openingRange);
+ metadata.Add("trigger_price", lastPrice);
+ metadata.Add("multiplier", _stdDevMultiplier);
+
+ if (_logger != null)
+ {
+ _logger.LogInformation("SimpleORBStrategy generated {0} intent for {1}. OR High={2:F2}, OR Low={3:F2}, Last={4:F2}", side, symbol, _openingRangeHigh, _openingRangeLow, lastPrice);
+ }
+
+ return new StrategyIntent(
+ symbol,
+ side,
+ OrderType.Market,
+ null,
+ 8,
+ 16,
+ 0.75,
+ "ORB breakout signal",
+ metadata);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/deployment/backups/20260224_165037/manifest.txt b/deployment/backups/20260224_165037/manifest.txt
new file mode 100644
index 0000000..f561edf
--- /dev/null
+++ b/deployment/backups/20260224_165037/manifest.txt
@@ -0,0 +1,6 @@
+Deployment manifest
+Timestamp: 20260224_165037
+Source Core DLL: C:\dev\nt8-sdk\deployment\..\src\NT8.Core\bin\Release\net48\NT8.Core.dll
+Source Adapters DLL: C:\dev\nt8-sdk\deployment\..\src\NT8.Adapters\bin\Release\net48\NT8.Adapters.dll
+Destination Custom Folder: C:\Users\billy\Documents\NinjaTrader 8\bin\Custom
+Destination Strategies Folder: C:\Users\billy\Documents\NinjaTrader 8\bin\Custom\Strategies
diff --git a/deployment/backups/20260224_165831/BaseNT8StrategyWrapper.cs b/deployment/backups/20260224_165831/BaseNT8StrategyWrapper.cs
new file mode 100644
index 0000000..5811382
--- /dev/null
+++ b/deployment/backups/20260224_165831/BaseNT8StrategyWrapper.cs
@@ -0,0 +1,229 @@
+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
+{
+ ///
+ /// Base wrapper class for NT8 strategies that integrate with the SDK
+ /// This is a template that would be extended in actual NT8 strategy files
+ ///
+ 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
+
+ ///
+ /// Stop loss in ticks
+ ///
+ public int StopTicks { get; set; }
+
+ ///
+ /// Profit target in ticks (optional)
+ ///
+ public int TargetTicks { get; set; }
+
+ ///
+ /// Risk amount per trade in dollars
+ ///
+ public double RiskAmount { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Constructor for BaseNT8StrategyWrapper
+ ///
+ 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
+
+ ///
+ /// Create the SDK strategy implementation
+ ///
+ protected abstract IStrategy CreateSdkStrategy();
+
+ #endregion
+
+ #region Public Methods
+
+ ///
+ /// Process a bar update (would be called from NT8's OnBarUpdate)
+ ///
+ 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
+
+ ///
+ /// Initialize SDK components
+ ///
+ 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);
+ }
+
+ ///
+ /// Create SDK configuration from parameters
+ ///
+ 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()
+ );
+
+ // Create strategy configuration
+ _strategyConfig = new StrategyConfig(
+ name: "NT8Strategy",
+ symbol: "Unknown",
+ parameters: new Dictionary(),
+ riskSettings: riskConfig,
+ sizingSettings: sizingConfig
+ );
+ }
+
+ ///
+ /// Execute strategy intent through NT8
+ ///
+ 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
+ }
+}
diff --git a/deployment/backups/20260224_165831/NT8.Adapters.dll b/deployment/backups/20260224_165831/NT8.Adapters.dll
new file mode 100644
index 0000000..0a12355
Binary files /dev/null and b/deployment/backups/20260224_165831/NT8.Adapters.dll differ
diff --git a/deployment/backups/20260224_165831/NT8.Core.dll b/deployment/backups/20260224_165831/NT8.Core.dll
new file mode 100644
index 0000000..b00aca1
Binary files /dev/null and b/deployment/backups/20260224_165831/NT8.Core.dll differ
diff --git a/deployment/backups/20260224_165831/SimpleORBNT8Wrapper.cs b/deployment/backups/20260224_165831/SimpleORBNT8Wrapper.cs
new file mode 100644
index 0000000..1c85459
--- /dev/null
+++ b/deployment/backups/20260224_165831/SimpleORBNT8Wrapper.cs
@@ -0,0 +1,280 @@
+using System;
+using System.Collections.Generic;
+using NT8.Core.Common.Interfaces;
+using NT8.Core.Common.Models;
+using NT8.Core.Logging;
+using NT8.Adapters.NinjaTrader;
+
+namespace NT8.Adapters.Wrappers
+{
+ ///
+ /// Simple ORB (Opening Range Breakout) strategy wrapper for NT8
+ /// This demonstrates how to implement a strategy that works with the SDK
+ ///
+ public class SimpleORBNT8Wrapper : BaseNT8StrategyWrapper
+ {
+ #region Strategy Parameters
+
+ ///
+ /// Opening range period in minutes
+ ///
+ public int OpeningRangeMinutes { get; set; }
+
+ ///
+ /// Number of standard deviations for breakout threshold
+ ///
+ public double StdDevMultiplier { get; set; }
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Constructor for SimpleORBNT8Wrapper
+ ///
+ public SimpleORBNT8Wrapper()
+ {
+ OpeningRangeMinutes = 30;
+ StdDevMultiplier = 1.0;
+ }
+
+ #endregion
+
+ #region Base Class Implementation
+
+ ///
+ /// Exposes adapter reference for integration test assertions.
+ ///
+ public NT8Adapter GetAdapterForTesting()
+ {
+ return _nt8Adapter;
+ }
+
+ ///
+ /// Create the SDK strategy implementation
+ ///
+ protected override IStrategy CreateSdkStrategy()
+ {
+ var openingRangeMinutes = OpeningRangeMinutes > 0 ? OpeningRangeMinutes : 30;
+ var stdDevMultiplier = StdDevMultiplier > 0.0 ? StdDevMultiplier : 1.0;
+ return new SimpleORBStrategy(openingRangeMinutes, stdDevMultiplier);
+ }
+
+ #endregion
+
+ #region Strategy Logic
+
+ ///
+ /// Simple ORB strategy implementation
+ ///
+ private class SimpleORBStrategy : IStrategy
+ {
+ private readonly int _openingRangeMinutes;
+ private readonly double _stdDevMultiplier;
+
+ private ILogger _logger;
+ private DateTime _currentSessionDate;
+ private DateTime _openingRangeStart;
+ private DateTime _openingRangeEnd;
+ private double _openingRangeHigh;
+ private double _openingRangeLow;
+ private bool _openingRangeReady;
+ private bool _tradeTaken;
+
+ public StrategyMetadata Metadata { get; private set; }
+
+ public SimpleORBStrategy(int openingRangeMinutes, double stdDevMultiplier)
+ {
+ if (openingRangeMinutes <= 0)
+ {
+ throw new ArgumentException("openingRangeMinutes");
+ }
+
+ if (stdDevMultiplier <= 0.0)
+ {
+ throw new ArgumentException("stdDevMultiplier");
+ }
+
+ _openingRangeMinutes = openingRangeMinutes;
+ _stdDevMultiplier = stdDevMultiplier;
+
+ _currentSessionDate = DateTime.MinValue;
+ _openingRangeStart = DateTime.MinValue;
+ _openingRangeEnd = DateTime.MinValue;
+ _openingRangeHigh = Double.MinValue;
+ _openingRangeLow = Double.MaxValue;
+ _openingRangeReady = false;
+ _tradeTaken = false;
+
+ Metadata = new StrategyMetadata(
+ name: "Simple ORB",
+ description: "Opening Range Breakout strategy",
+ version: "1.0",
+ author: "NT8 SDK Team",
+ symbols: new string[] { "ES", "NQ", "YM" },
+ requiredBars: 20
+ );
+ }
+
+ public void Initialize(StrategyConfig config, IMarketDataProvider dataProvider, ILogger logger)
+ {
+ if (logger == null)
+ {
+ throw new ArgumentNullException("logger");
+ }
+
+ _logger = logger;
+ _logger.LogInformation("SimpleORBStrategy initialized with OR period {0} minutes and multiplier {1:F2}", _openingRangeMinutes, _stdDevMultiplier);
+ }
+
+ public StrategyIntent OnBar(BarData bar, StrategyContext context)
+ {
+ if (bar == null)
+ {
+ throw new ArgumentNullException("bar");
+ }
+
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ try
+ {
+ if (_currentSessionDate != context.CurrentTime.Date)
+ {
+ ResetSession(context.Session.SessionStart);
+ }
+
+ if (bar.Time <= _openingRangeEnd)
+ {
+ UpdateOpeningRange(bar);
+ return null;
+ }
+
+ if (!_openingRangeReady)
+ {
+ if (_openingRangeHigh > _openingRangeLow)
+ {
+ _openingRangeReady = true;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ if (_tradeTaken)
+ {
+ return null;
+ }
+
+ var openingRange = _openingRangeHigh - _openingRangeLow;
+ var volatilityBuffer = openingRange * (_stdDevMultiplier - 1.0);
+ if (volatilityBuffer < 0)
+ {
+ volatilityBuffer = 0;
+ }
+
+ var longTrigger = _openingRangeHigh + volatilityBuffer;
+ var shortTrigger = _openingRangeLow - volatilityBuffer;
+
+ if (bar.Close > longTrigger)
+ {
+ _tradeTaken = true;
+ return CreateIntent(context.Symbol, OrderSide.Buy, openingRange, bar.Close);
+ }
+
+ if (bar.Close < shortTrigger)
+ {
+ _tradeTaken = true;
+ return CreateIntent(context.Symbol, OrderSide.Sell, openingRange, bar.Close);
+ }
+
+ return null;
+ }
+ catch (Exception ex)
+ {
+ if (_logger != null)
+ {
+ _logger.LogError("SimpleORBStrategy OnBar failed: {0}", ex.Message);
+ }
+
+ throw;
+ }
+ }
+
+ public StrategyIntent OnTick(TickData tick, StrategyContext context)
+ {
+ // Most strategies don't need tick-level logic
+ return null;
+ }
+
+ public Dictionary GetParameters()
+ {
+ var parameters = new Dictionary();
+ parameters.Add("opening_range_minutes", _openingRangeMinutes);
+ parameters.Add("std_dev_multiplier", _stdDevMultiplier);
+ return parameters;
+ }
+
+ public void SetParameters(Dictionary parameters)
+ {
+ // Parameters are constructor-bound for deterministic behavior in this wrapper.
+ // Method retained for interface compatibility.
+ }
+
+ private void ResetSession(DateTime sessionStart)
+ {
+ _currentSessionDate = sessionStart.Date;
+ _openingRangeStart = sessionStart;
+ _openingRangeEnd = sessionStart.AddMinutes(_openingRangeMinutes);
+ _openingRangeHigh = Double.MinValue;
+ _openingRangeLow = Double.MaxValue;
+ _openingRangeReady = false;
+ _tradeTaken = false;
+ }
+
+ private void UpdateOpeningRange(BarData bar)
+ {
+ if (bar.High > _openingRangeHigh)
+ {
+ _openingRangeHigh = bar.High;
+ }
+
+ if (bar.Low < _openingRangeLow)
+ {
+ _openingRangeLow = bar.Low;
+ }
+ }
+
+ private StrategyIntent CreateIntent(string symbol, OrderSide side, double openingRange, double lastPrice)
+ {
+ var metadata = new Dictionary();
+ metadata.Add("orb_high", _openingRangeHigh);
+ metadata.Add("orb_low", _openingRangeLow);
+ metadata.Add("orb_range", openingRange);
+ metadata.Add("trigger_price", lastPrice);
+ metadata.Add("multiplier", _stdDevMultiplier);
+
+ if (_logger != null)
+ {
+ _logger.LogInformation("SimpleORBStrategy generated {0} intent for {1}. OR High={2:F2}, OR Low={3:F2}, Last={4:F2}", side, symbol, _openingRangeHigh, _openingRangeLow, lastPrice);
+ }
+
+ return new StrategyIntent(
+ symbol,
+ side,
+ OrderType.Market,
+ null,
+ 8,
+ 16,
+ 0.75,
+ "ORB breakout signal",
+ metadata);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/deployment/backups/20260224_165831/manifest.txt b/deployment/backups/20260224_165831/manifest.txt
new file mode 100644
index 0000000..9e9d53a
--- /dev/null
+++ b/deployment/backups/20260224_165831/manifest.txt
@@ -0,0 +1,6 @@
+Deployment manifest
+Timestamp: 20260224_165831
+Source Core DLL: C:\dev\nt8-sdk\deployment\..\src\NT8.Core\bin\Release\net48\NT8.Core.dll
+Source Adapters DLL: C:\dev\nt8-sdk\deployment\..\src\NT8.Adapters\bin\Release\net48\NT8.Adapters.dll
+Destination Custom Folder: C:\Users\billy\Documents\NinjaTrader 8\bin\Custom
+Destination Strategies Folder: C:\Users\billy\Documents\NinjaTrader 8\bin\Custom\Strategies
diff --git a/deployment/deploy-to-nt8.bat b/deployment/deploy-to-nt8.bat
index b97d40a..6d2c8e0 100644
--- a/deployment/deploy-to-nt8.bat
+++ b/deployment/deploy-to-nt8.bat
@@ -12,7 +12,6 @@ set "CORE_BIN=%PROJECT_ROOT%\src\NT8.Core\bin\Release\net48"
set "ADAPTERS_BIN=%PROJECT_ROOT%\src\NT8.Adapters\bin\Release\net48"
set "WRAPPERS_SRC=%PROJECT_ROOT%\src\NT8.Adapters\Wrappers"
set "BACKUP_ROOT=%SCRIPT_DIR%backups"
-set "MANIFEST_FILE=%BACKUP_DIR%\manifest.txt"
echo ============================================================
echo NT8 SDK Deployment
@@ -47,7 +46,8 @@ if not exist "%NT8_STRATEGIES%" (
for /f %%i in ('powershell -NoProfile -Command "Get-Date -Format yyyyMMdd_HHmmss"') do set "STAMP=%%i"
set "BACKUP_DIR=%BACKUP_ROOT%\%STAMP%"
-mkdir "%BACKUP_DIR%" >nul 2>&1
+set "MANIFEST_FILE=%BACKUP_ROOT%\%STAMP%\manifest.txt"
+mkdir "%BACKUP_ROOT%\%STAMP%" >nul 2>&1
echo Backing up existing NT8 SDK files...
if exist "%NT8_CUSTOM%\NT8.Core.dll" copy /Y "%NT8_CUSTOM%\NT8.Core.dll" "%BACKUP_DIR%\NT8.Core.dll" >nul
@@ -88,6 +88,19 @@ if errorlevel 1 (
exit /b 1
)
+set "STRATEGIES_SRC=%PROJECT_ROOT%\src\NT8.Adapters\Strategies"
+copy /Y "%STRATEGIES_SRC%\NT8StrategyBase.cs" "%NT8_STRATEGIES%\NT8StrategyBase.cs" >nul
+if errorlevel 1 (
+ echo ERROR: Failed to copy NT8StrategyBase.cs
+ exit /b 1
+)
+
+copy /Y "%STRATEGIES_SRC%\SimpleORBNT8.cs" "%NT8_STRATEGIES%\SimpleORBNT8.cs" >nul
+if errorlevel 1 (
+ echo ERROR: Failed to copy SimpleORBNT8.cs
+ exit /b 1
+)
+
echo Verifying deployment files...
if not exist "%NT8_CUSTOM%\NT8.Core.dll" (
echo ERROR: Verification failed for NT8.Core.dll
diff --git a/src/NT8.Adapters/Strategies/NT8StrategyBase.cs b/src/NT8.Adapters/Strategies/NT8StrategyBase.cs
index 89b156b..b5ed2b3 100644
--- a/src/NT8.Adapters/Strategies/NT8StrategyBase.cs
+++ b/src/NT8.Adapters/Strategies/NT8StrategyBase.cs
@@ -11,7 +11,6 @@ using NinjaTrader.Gui.Tools;
using NinjaTrader.NinjaScript;
using NinjaTrader.NinjaScript.Indicators;
using NinjaTrader.NinjaScript.Strategies;
-using Microsoft.Extensions.Logging.Abstractions;
using NT8.Adapters.NinjaTrader;
using NT8.Core.Common.Interfaces;
using NT8.Core.Common.Models;
@@ -152,7 +151,7 @@ namespace NinjaTrader.NinjaScript.Strategies
catch (Exception ex)
{
Print(string.Format("[SDK ERROR] Initialization failed: {0}", ex.Message));
- Log(string.Format("[SDK ERROR] {0}", ex.ToString()), LogLevel.Error);
+ Log(string.Format("[SDK ERROR] {0}", ex.ToString()), NinjaTrader.Cbi.LogLevel.Error);
_sdkInitialized = false;
}
}
@@ -236,7 +235,7 @@ namespace NinjaTrader.NinjaScript.Strategies
_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);
+ Log(string.Format("[SDK ERROR] {0}", ex.ToString()), NinjaTrader.Cbi.LogLevel.Error);
}
}
@@ -321,7 +320,7 @@ namespace NinjaTrader.NinjaScript.Strategies
_riskManager = new BasicRiskManager(_logger);
_positionSizer = new BasicPositionSizer(_logger);
_circuitBreaker = new ExecutionCircuitBreaker(
- NullLogger.Instance,
+ _logger,
failureThreshold: 3,
timeout: TimeSpan.FromSeconds(30));
_executionAdapter = new NT8ExecutionAdapter();
diff --git a/src/NT8.Core/Execution/ExecutionCircuitBreaker.cs b/src/NT8.Core/Execution/ExecutionCircuitBreaker.cs
index 7f5b4e9..afa95ee 100644
--- a/src/NT8.Core/Execution/ExecutionCircuitBreaker.cs
+++ b/src/NT8.Core/Execution/ExecutionCircuitBreaker.cs
@@ -1,8 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.CompilerServices;
using Microsoft.Extensions.Logging;
+[assembly: InternalsVisibleTo("NT8.Core.Tests")]
+[assembly: InternalsVisibleTo("NT8.Integration.Tests")]
+
namespace NT8.Core.Execution
{
///
@@ -11,6 +15,7 @@ namespace NT8.Core.Execution
public class ExecutionCircuitBreaker
{
private readonly ILogger _logger;
+ private readonly NT8.Core.Logging.ILogger _sdkLogger;
private readonly object _lock = new object();
private CircuitBreakerStatus _status;
@@ -21,24 +26,49 @@ namespace NT8.Core.Execution
private readonly int _failureThreshold;
private readonly TimeSpan _retryTimeout;
- // Track execution times for latency monitoring
private readonly Queue _executionTimes;
private readonly int _latencyWindowSize;
- // Track order rejections
private readonly Queue _rejectionTimes;
private readonly int _rejectionWindowSize;
+ // Log helpers — route through whichever logger is available
+ private void LogDebug(string message) { if (_logger != null) _logger.LogDebug(message); else if (_sdkLogger != null) _sdkLogger.LogDebug(message); }
+ private void LogInfo(string message) { if (_logger != null) _logger.LogInformation(message); else if (_sdkLogger != null) _sdkLogger.LogInformation(message); }
+ private void LogWarn(string message) { if (_logger != null) _logger.LogWarning(message); else if (_sdkLogger != null) _sdkLogger.LogWarning(message); }
+ private void LogErr(string message) { if (_logger != null) _logger.LogError(message); else if (_sdkLogger != null) _sdkLogger.LogError(message); }
+
///
- /// Constructor for ExecutionCircuitBreaker
+ /// Constructor accepting NT8.Core.Logging.ILogger.
+ /// Use this overload from NinjaScript (.cs) files — no Microsoft.Extensions.Logging reference required.
///
- /// Logger instance
- /// Number of failures to trigger circuit breaker
- /// How long to stay open before half-open
- /// Time to wait between retries
- /// Size of latency tracking window
- /// Size of rejection tracking window
public ExecutionCircuitBreaker(
+ NT8.Core.Logging.ILogger sdkLogger,
+ int failureThreshold = 3,
+ TimeSpan? timeout = null,
+ TimeSpan? retryTimeout = null,
+ int latencyWindowSize = 100,
+ int rejectionWindowSize = 10)
+ {
+ _sdkLogger = sdkLogger;
+ _logger = null;
+ _status = CircuitBreakerStatus.Closed;
+ _failureCount = 0;
+ _lastFailureTime = DateTime.MinValue;
+ _timeout = timeout ?? TimeSpan.FromSeconds(30);
+ _retryTimeout = retryTimeout ?? TimeSpan.FromSeconds(5);
+ _failureThreshold = failureThreshold;
+ _latencyWindowSize = latencyWindowSize;
+ _rejectionWindowSize = rejectionWindowSize;
+ _executionTimes = new Queue();
+ _rejectionTimes = new Queue();
+ }
+
+ ///
+ /// Constructor accepting Microsoft.Extensions.Logging.ILogger.
+ /// Use this overload from DLL projects and unit tests.
+ ///
+ internal ExecutionCircuitBreaker(
ILogger logger,
int failureThreshold = 3,
TimeSpan? timeout = null,
@@ -50,6 +80,7 @@ namespace NT8.Core.Execution
throw new ArgumentNullException("logger");
_logger = logger;
+ _sdkLogger = null;
_status = CircuitBreakerStatus.Closed;
_failureCount = 0;
_lastFailureTime = DateTime.MinValue;
@@ -58,15 +89,11 @@ namespace NT8.Core.Execution
_failureThreshold = failureThreshold;
_latencyWindowSize = latencyWindowSize;
_rejectionWindowSize = rejectionWindowSize;
-
_executionTimes = new Queue();
_rejectionTimes = new Queue();
}
- ///
- /// Records execution time for monitoring
- ///
- /// Execution latency
+ /// Records execution time for latency monitoring.
public void RecordExecutionTime(TimeSpan latency)
{
try
@@ -74,31 +101,21 @@ namespace NT8.Core.Execution
lock (_lock)
{
_executionTimes.Enqueue(latency);
-
- // Keep only the last N measurements
while (_executionTimes.Count > _latencyWindowSize)
- {
_executionTimes.Dequeue();
- }
- // Check if we have excessive latency
if (_status == CircuitBreakerStatus.Closed && HasExcessiveLatency())
- {
TripCircuitBreaker("Excessive execution latency detected");
- }
}
}
catch (Exception ex)
{
- _logger.LogError("Failed to record execution time: {Message}", ex.Message);
+ LogErr(string.Format("Failed to record execution time: {0}", ex.Message));
throw;
}
}
- ///
- /// Records order rejection for monitoring
- ///
- /// Reason for rejection
+ /// Records an order rejection.
public void RecordOrderRejection(string reason)
{
if (string.IsNullOrEmpty(reason))
@@ -109,31 +126,21 @@ namespace NT8.Core.Execution
lock (_lock)
{
_rejectionTimes.Enqueue(DateTime.UtcNow);
-
- // Keep only the last N rejections
while (_rejectionTimes.Count > _rejectionWindowSize)
- {
_rejectionTimes.Dequeue();
- }
- // Check if we have excessive rejections
if (_status == CircuitBreakerStatus.Closed && HasExcessiveRejections())
- {
- TripCircuitBreaker(String.Format("Excessive order rejections: {0}", reason));
- }
+ TripCircuitBreaker(string.Format("Excessive order rejections: {0}", reason));
}
}
catch (Exception ex)
{
- _logger.LogError("Failed to record order rejection: {Message}", ex.Message);
+ LogErr(string.Format("Failed to record order rejection: {0}", ex.Message));
throw;
}
}
- ///
- /// Determines if an order should be allowed based on circuit breaker state
- ///
- /// True if order should be allowed, false otherwise
+ /// Returns true if an order should be allowed through.
public bool ShouldAllowOrder()
{
try
@@ -143,26 +150,20 @@ namespace NT8.Core.Execution
switch (_status)
{
case CircuitBreakerStatus.Closed:
- // Normal operation
return true;
case CircuitBreakerStatus.Open:
- // Check if we should transition to half-open
if (DateTime.UtcNow >= _nextRetryTime)
{
_status = CircuitBreakerStatus.HalfOpen;
- _logger.LogWarning("Circuit breaker transitioning to Half-Open state");
- return true; // Allow one test order
- }
- else
- {
- _logger.LogDebug("Circuit breaker is Open - blocking order");
- return false; // Block orders
+ LogWarn("Circuit breaker transitioning to Half-Open state");
+ return true;
}
+ LogDebug("Circuit breaker is Open - blocking order");
+ return false;
case CircuitBreakerStatus.HalfOpen:
- // In half-open, allow limited operations to test if system recovered
- _logger.LogDebug("Circuit breaker is Half-Open - allowing test order");
+ LogDebug("Circuit breaker is Half-Open - allowing test order");
return true;
default:
@@ -172,15 +173,12 @@ namespace NT8.Core.Execution
}
catch (Exception ex)
{
- _logger.LogError("Failed to check if order should be allowed: {Message}", ex.Message);
+ LogErr(string.Format("Failed to check ShouldAllowOrder: {0}", ex.Message));
throw;
}
}
- ///
- /// Gets the current state of the circuit breaker
- ///
- /// Current circuit breaker state
+ /// Returns the current circuit breaker state.
public CircuitBreakerState GetState()
{
try
@@ -191,20 +189,17 @@ namespace NT8.Core.Execution
_status != CircuitBreakerStatus.Closed,
_status,
GetStatusReason(),
- _failureCount
- );
+ _failureCount);
}
}
catch (Exception ex)
{
- _logger.LogError("Failed to get circuit breaker state: {Message}", ex.Message);
+ LogErr(string.Format("Failed to get state: {0}", ex.Message));
throw;
}
}
- ///
- /// Resets the circuit breaker to closed state
- ///
+ /// Resets the circuit breaker to Closed state.
public void Reset()
{
try
@@ -214,20 +209,17 @@ namespace NT8.Core.Execution
_status = CircuitBreakerStatus.Closed;
_failureCount = 0;
_lastFailureTime = DateTime.MinValue;
-
- _logger.LogInformation("Circuit breaker reset to Closed state");
+ LogInfo("Circuit breaker reset to Closed state");
}
}
catch (Exception ex)
{
- _logger.LogError("Failed to reset circuit breaker: {Message}", ex.Message);
+ LogErr(string.Format("Failed to reset circuit breaker: {0}", ex.Message));
throw;
}
}
- ///
- /// Called when an operation succeeds while in Half-Open state
- ///
+ /// Call after a successful order submission.
public void OnSuccess()
{
try
@@ -237,20 +229,18 @@ namespace NT8.Core.Execution
if (_status == CircuitBreakerStatus.HalfOpen)
{
Reset();
- _logger.LogInformation("Circuit breaker reset after successful test operation");
+ LogInfo("Circuit breaker reset after successful test operation");
}
}
}
catch (Exception ex)
{
- _logger.LogError("Failed to handle success in Half-Open state: {Message}", ex.Message);
+ LogErr(string.Format("Failed to handle OnSuccess: {0}", ex.Message));
throw;
}
}
- ///
- /// Called when an operation fails
- ///
+ /// Call after a failed order submission.
public void OnFailure()
{
try
@@ -260,7 +250,6 @@ namespace NT8.Core.Execution
_failureCount++;
_lastFailureTime = DateTime.UtcNow;
- // If we're in half-open and fail, go back to open
if (_status == CircuitBreakerStatus.HalfOpen ||
(_status == CircuitBreakerStatus.Closed && _failureCount >= _failureThreshold))
{
@@ -270,61 +259,35 @@ namespace NT8.Core.Execution
}
catch (Exception ex)
{
- _logger.LogError("Failed to handle failure: {Message}", ex.Message);
+ LogErr(string.Format("Failed to handle OnFailure: {0}", ex.Message));
throw;
}
}
- ///
- /// Trips the circuit breaker to open state
- ///
- /// Reason for tripping
private void TripCircuitBreaker(string reason)
{
_status = CircuitBreakerStatus.Open;
_nextRetryTime = DateTime.UtcNow.Add(_timeout);
-
- _logger.LogWarning("Circuit breaker TRIPPED: {Reason}. Will retry at {Time}",
- reason, _nextRetryTime);
+ LogWarn(string.Format("Circuit breaker TRIPPED: {0}. Will retry at {1}", reason, _nextRetryTime));
}
- ///
- /// Checks if we have excessive execution latency
- ///
- /// True if latency is excessive
private bool HasExcessiveLatency()
{
- if (_executionTimes.Count < 3) // Need minimum samples
+ if (_executionTimes.Count < 3)
return false;
-
- // Calculate average latency
var avgLatency = TimeSpan.FromMilliseconds(_executionTimes.Average(ts => ts.TotalMilliseconds));
-
- // If average latency is more than 5 seconds, consider it excessive
return avgLatency.TotalSeconds > 5.0;
}
- ///
- /// Checks if we have excessive order rejections
- ///
- /// True if rejections are excessive
private bool HasExcessiveRejections()
{
if (_rejectionTimes.Count < _rejectionWindowSize)
return false;
-
- // If all recent orders were rejected (100% rejection rate in window)
- var recentWindow = TimeSpan.FromMinutes(1); // Check last minute
+ var recentWindow = TimeSpan.FromMinutes(1);
var recentRejections = _rejectionTimes.Count(dt => DateTime.UtcNow - dt <= recentWindow);
-
- // If we have maximum possible rejections in the window, it's excessive
return recentRejections >= _rejectionWindowSize;
}
- ///
- /// Gets the reason for current status
- ///
- /// Reason string
private string GetStatusReason()
{
switch (_status)
@@ -332,8 +295,7 @@ namespace NT8.Core.Execution
case CircuitBreakerStatus.Closed:
return "Normal operation";
case CircuitBreakerStatus.Open:
- return String.Format("Tripped due to failures. Failures: {0}, Last: {1}",
- _failureCount, _lastFailureTime);
+ return string.Format("Tripped due to failures. Count: {0}, Last: {1}", _failureCount, _lastFailureTime);
case CircuitBreakerStatus.HalfOpen:
return "Testing recovery after timeout";
default:
@@ -341,10 +303,7 @@ namespace NT8.Core.Execution
}
}
- ///
- /// Gets average execution time for monitoring
- ///
- /// Average execution time
+ /// Returns average execution latency.
public TimeSpan GetAverageExecutionTime()
{
try
@@ -353,21 +312,17 @@ namespace NT8.Core.Execution
{
if (_executionTimes.Count == 0)
return TimeSpan.Zero;
-
return TimeSpan.FromMilliseconds(_executionTimes.Average(ts => ts.TotalMilliseconds));
}
}
catch (Exception ex)
{
- _logger.LogError("Failed to get average execution time: {Message}", ex.Message);
+ LogErr(string.Format("Failed to get average execution time: {0}", ex.Message));
throw;
}
}
- ///
- /// Gets rejection rate for monitoring
- ///
- /// Rejection rate as percentage
+ /// Returns rejection rate as a percentage.
public double GetRejectionRate()
{
try
@@ -376,19 +331,14 @@ namespace NT8.Core.Execution
{
if (_rejectionTimes.Count == 0)
return 0.0;
-
- // Calculate rejections in last minute
var oneMinuteAgo = DateTime.UtcNow.AddMinutes(-1);
var recentRejections = _rejectionTimes.Count(dt => dt >= oneMinuteAgo);
-
- // This is a simplified calculation - in practice you'd need to track
- // total attempts to calculate accurate rate
return (double)recentRejections / _rejectionWindowSize * 100.0;
}
}
catch (Exception ex)
{
- _logger.LogError("Failed to get rejection rate: {Message}", ex.Message);
+ LogErr(string.Format("Failed to get rejection rate: {0}", ex.Message));
throw;
}
}
diff --git a/src/NT8.Strategies/Examples/SimpleORBStrategy.cs b/src/NT8.Strategies/Examples/SimpleORBStrategy.cs
index 7df917f..b747218 100644
--- a/src/NT8.Strategies/Examples/SimpleORBStrategy.cs
+++ b/src/NT8.Strategies/Examples/SimpleORBStrategy.cs
@@ -19,6 +19,7 @@ namespace NT8.Strategies.Examples
private readonly double _stdDevMultiplier;
private ILogger _logger;
+ private StrategyConfig _config;
private ConfluenceScorer _scorer;
private GradeFilter _gradeFilter;
private RiskModeManager _riskModeManager;
@@ -98,6 +99,7 @@ namespace NT8.Strategies.Examples
try
{
_logger = logger;
+ _config = config;
_scorer = new ConfluenceScorer(_logger, 500);
_gradeFilter = new GradeFilter();
_riskModeManager = new RiskModeManager(_logger);
@@ -151,6 +153,10 @@ namespace NT8.Strategies.Examples
ResetSession(context.Session != null ? context.Session.SessionStart : context.CurrentTime.Date);
}
+ // Only trade during RTH
+ if (context.Session == null || !context.Session.IsRth)
+ return null;
+
if (bar.Time <= _openingRangeEnd)
{
UpdateOpeningRange(bar);
@@ -332,6 +338,13 @@ namespace NT8.Strategies.Examples
private StrategyIntent CreateIntent(string symbol, OrderSide side, double openingRange, double lastPrice)
{
+ var stopTicks = _config != null && _config.Parameters.ContainsKey("StopTicks")
+ ? (int)_config.Parameters["StopTicks"]
+ : 8;
+ var targetTicks = _config != null && _config.Parameters.ContainsKey("TargetTicks")
+ ? (int)_config.Parameters["TargetTicks"]
+ : 16;
+
var metadata = new Dictionary();
metadata.Add("orb_high", _openingRangeHigh);
metadata.Add("orb_low", _openingRangeLow);
@@ -346,8 +359,8 @@ namespace NT8.Strategies.Examples
side,
OrderType.Market,
null,
- 8,
- 16,
+ stopTicks,
+ targetTicks,
0.75,
"ORB breakout signal",
metadata);