153 lines
5.1 KiB
Markdown
153 lines
5.1 KiB
Markdown
# NT8 Strategy Dropdown Fix Specification
|
|
|
|
**For:** Kilocode AI Agent
|
|
**Priority:** URGENT
|
|
**Mode:** Code Mode
|
|
**Estimated Time:** 20-30 minutes
|
|
**Files to Edit:** 1 file (SimpleORBNT8.cs)
|
|
|
|
---
|
|
|
|
## 🎯 Objective
|
|
|
|
Fix SimpleORBNT8 not appearing in NT8 strategy dropdown. The strategy compiles
|
|
but causes a runtime error when NT8 tries to load it for the dropdown list.
|
|
|
|
---
|
|
|
|
## 🔍 Root Cause
|
|
|
|
`ConfigureStrategyParameters()` is called during `State.DataLoaded` and accesses
|
|
`Instrument.MasterInstrument.PointValue` and `Instrument.MasterInstrument.TickSize`.
|
|
|
|
These properties are only safely available when the strategy is applied to a chart
|
|
with a known instrument. When NT8 loads the strategy list for the dropdown,
|
|
`Instrument` is null, causing a NullReferenceException that removes the strategy
|
|
from the available list silently.
|
|
|
|
Per NT8 forum: "If there is an error in OnStateChange() when you go to
|
|
New > Strategy, the OnStateChange() is called and a run-time type error
|
|
can occur which removes the strategy from the available list as a preventative measure."
|
|
|
|
---
|
|
|
|
## 🔧 Fix: SimpleORBNT8.cs - Guard Instrument access
|
|
|
|
### File
|
|
`src/NT8.Adapters/Strategies/SimpleORBNT8.cs`
|
|
|
|
### Change: Add null guard in ConfigureStrategyParameters()
|
|
|
|
**Find:**
|
|
```csharp
|
|
protected override void ConfigureStrategyParameters()
|
|
{
|
|
_strategyConfig.RiskSettings.DailyLossLimit = DailyLossLimit;
|
|
_strategyConfig.RiskSettings.MaxTradeRisk = MaxTradeRisk;
|
|
_strategyConfig.RiskSettings.MaxOpenPositions = MaxOpenPositions;
|
|
|
|
var pointValue = Instrument.MasterInstrument.PointValue;
|
|
var tickSize = Instrument.MasterInstrument.TickSize;
|
|
var dollarRisk = StopTicks * tickSize * pointValue;
|
|
|
|
if (dollarRisk > _strategyConfig.RiskSettings.MaxTradeRisk)
|
|
_strategyConfig.RiskSettings.MaxTradeRisk = dollarRisk;
|
|
|
|
_strategyConfig.SizingSettings.RiskPerTrade = RiskPerTrade;
|
|
_strategyConfig.SizingSettings.MinContracts = MinContracts;
|
|
_strategyConfig.SizingSettings.MaxContracts = MaxContracts;
|
|
|
|
_strategyConfig.Parameters["StopTicks"] = StopTicks;
|
|
_strategyConfig.Parameters["TargetTicks"] = TargetTicks;
|
|
_strategyConfig.Parameters["OpeningRangeMinutes"] = OpeningRangeMinutes;
|
|
|
|
if (_logger != null)
|
|
{
|
|
_logger.LogInformation(
|
|
"Simple ORB configured: OR={0}min, Stop={1}ticks, Target={2}ticks",
|
|
OpeningRangeMinutes,
|
|
StopTicks,
|
|
TargetTicks);
|
|
}
|
|
}
|
|
```
|
|
|
|
**Replace with:**
|
|
```csharp
|
|
protected override void ConfigureStrategyParameters()
|
|
{
|
|
_strategyConfig.RiskSettings.DailyLossLimit = DailyLossLimit;
|
|
_strategyConfig.RiskSettings.MaxTradeRisk = MaxTradeRisk;
|
|
_strategyConfig.RiskSettings.MaxOpenPositions = MaxOpenPositions;
|
|
|
|
// Guard: Instrument may be null during strategy list loading
|
|
if (Instrument != null && Instrument.MasterInstrument != null)
|
|
{
|
|
var pointValue = Instrument.MasterInstrument.PointValue;
|
|
var tickSize = Instrument.MasterInstrument.TickSize;
|
|
var dollarRisk = StopTicks * tickSize * pointValue;
|
|
|
|
if (dollarRisk > _strategyConfig.RiskSettings.MaxTradeRisk)
|
|
_strategyConfig.RiskSettings.MaxTradeRisk = dollarRisk;
|
|
}
|
|
|
|
_strategyConfig.SizingSettings.RiskPerTrade = RiskPerTrade;
|
|
_strategyConfig.SizingSettings.MinContracts = MinContracts;
|
|
_strategyConfig.SizingSettings.MaxContracts = MaxContracts;
|
|
|
|
_strategyConfig.Parameters["StopTicks"] = StopTicks;
|
|
_strategyConfig.Parameters["TargetTicks"] = TargetTicks;
|
|
_strategyConfig.Parameters["OpeningRangeMinutes"] = OpeningRangeMinutes;
|
|
|
|
if (_logger != null)
|
|
{
|
|
_logger.LogInformation(
|
|
"Simple ORB configured: OR={0}min, Stop={1}ticks, Target={2}ticks",
|
|
OpeningRangeMinutes,
|
|
StopTicks,
|
|
TargetTicks);
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## ✅ Verification
|
|
|
|
```bash
|
|
# Build must succeed
|
|
dotnet build src\NT8.Adapters\NT8.Adapters.csproj --configuration Release
|
|
|
|
# All tests must still pass
|
|
dotnet test NT8-SDK.sln --configuration Release --no-build
|
|
```
|
|
|
|
**After deploy and recompile in NT8:**
|
|
- [ ] Zero compile errors
|
|
- [ ] "Simple ORB NT8" appears in strategy dropdown
|
|
- [ ] "Minimal Test" appears in strategy dropdown
|
|
|
|
---
|
|
|
|
## 🚨 Constraints
|
|
|
|
- Surgical edit ONLY - one method, add null guard
|
|
- C# 5.0 syntax - no modern features
|
|
- Do NOT change any other logic
|
|
- All 319 tests must still pass
|
|
|
|
---
|
|
|
|
## 📋 Git Commit
|
|
|
|
```bash
|
|
git add src/NT8.Adapters/Strategies/SimpleORBNT8.cs
|
|
git commit -m "fix: Guard Instrument null access in ConfigureStrategyParameters
|
|
|
|
Instrument.MasterInstrument is null when NT8 loads strategy list
|
|
for dropdown. Added null guard to prevent runtime exception that
|
|
silently removes strategy from available list."
|
|
```
|
|
|
|
**READY FOR KILOCODE - CODE MODE** ✅
|