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
This commit is contained in:
280
deployment/backups/20260224_165037/SimpleORBNT8Wrapper.cs
Normal file
280
deployment/backups/20260224_165037/SimpleORBNT8Wrapper.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple ORB (Opening Range Breakout) strategy wrapper for NT8
|
||||
/// This demonstrates how to implement a strategy that works with the SDK
|
||||
/// </summary>
|
||||
public class SimpleORBNT8Wrapper : BaseNT8StrategyWrapper
|
||||
{
|
||||
#region Strategy Parameters
|
||||
|
||||
/// <summary>
|
||||
/// Opening range period in minutes
|
||||
/// </summary>
|
||||
public int OpeningRangeMinutes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of standard deviations for breakout threshold
|
||||
/// </summary>
|
||||
public double StdDevMultiplier { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for SimpleORBNT8Wrapper
|
||||
/// </summary>
|
||||
public SimpleORBNT8Wrapper()
|
||||
{
|
||||
OpeningRangeMinutes = 30;
|
||||
StdDevMultiplier = 1.0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Base Class Implementation
|
||||
|
||||
/// <summary>
|
||||
/// Exposes adapter reference for integration test assertions.
|
||||
/// </summary>
|
||||
public NT8Adapter GetAdapterForTesting()
|
||||
{
|
||||
return _nt8Adapter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the SDK strategy implementation
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// Simple ORB strategy implementation
|
||||
/// </summary>
|
||||
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<string, object> GetParameters()
|
||||
{
|
||||
var parameters = new Dictionary<string, object>();
|
||||
parameters.Add("opening_range_minutes", _openingRangeMinutes);
|
||||
parameters.Add("std_dev_multiplier", _stdDevMultiplier);
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public void SetParameters(Dictionary<string, object> 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<string, object>();
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user