Production hardening: kill switch, circuit breaker, trailing stops, log level, holiday calendar
Some checks failed
Build and Test / build (push) Has been cancelled
Some checks failed
Build and Test / build (push) Has been cancelled
This commit is contained in:
152
DROPDOWN_FIX_SPECIFICATION.md
Normal file
152
DROPDOWN_FIX_SPECIFICATION.md
Normal file
@@ -0,0 +1,152 @@
|
||||
# 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** ✅
|
||||
Reference in New Issue
Block a user