Pre-cleanup baseline snapshot
Some checks failed
Build and Test / build (push) Has been cancelled

This commit is contained in:
2026-04-05 16:50:18 -04:00
parent d856f3949d
commit 9a28a49292
12 changed files with 695 additions and 30 deletions

View File

@@ -1,9 +1,66 @@
# Coding Patterns — NT8 SDK Required Patterns # Coding Patterns — NT8 SDK Required Patterns
**Last Updated:** 2026-03-27
All code in the NT8 SDK MUST follow these patterns without exception. All code in the NT8 SDK MUST follow these patterns without exception.
--- ---
## 0. C# 5.0 Hard Constraints (NinjaScript Compiler)
```csharp
// ❌ PROHIBITED — compiler will fail silently or error
$"Hello {name}" // no string interpolation
obj?.Method() // no null-conditional
public int Prop => _value; // no expression body
nameof(SomeClass) // no nameof
await SomeAsync() // no async/await
// ✅ REQUIRED
string.Format("Hello {0}", name)
obj != null ? obj.Method() : null
public int Prop { get { return _value; } }
"SomeClass" // string literal
// synchronous only
```
---
## 0b. NT8-Specific Critical Rules
```csharp
// SetStopLoss/SetProfitTarget MUST come BEFORE EnterLong/EnterShort
// Calling them after is silently ignored in backtest
SetStopLoss(signalName, CalculationMode.Ticks, stopTicks, false); // FIRST
SetProfitTarget(signalName, CalculationMode.Ticks, targetTicks); // SECOND
EnterShort(qty, signalName); // THIRD
// OnBarUpdate must guard secondary series
protected override void OnBarUpdate()
{
if (BarsInProgress != 0) return; // CRITICAL: ignore daily bar series updates
// ...
}
// State guard in ProcessStrategyIntent
// Allows Historical (backtest), blocks Realtime replay burst:
if (State == State.Realtime && !_realtimeBarSeen)
return;
```
---
## Sizing Formula
```
contracts = floor(RiskPerTrade / (StopTicks × TickValue))
NQ tick value = $5.00
$100 / (8 × $5) = 2 contracts
$200 / (8 × $5) = 5 contracts (capped at MaxContracts)
Always verify: RiskPerTrade ≤ MaxTradeRisk
```
---
## 1. Thread Safety — Lock Everything Shared ## 1. Thread Safety — Lock Everything Shared
Every class with shared state must have a lock object: Every class with shared state must have a lock object:

View File

@@ -1,7 +1,108 @@
# NT8 Institutional SDK - Development Workflow # NT8-SDK — Kilocode Development Workflow
**Last Updated:** 2026-03-27
## Overview This is the authoritative workflow for all development work on NT8-SDK using Kilocode.
This document outlines the development workflow for the NT8 Institutional SDK, following the Archon workflow principles even in the absence of the Archon MCP server.
---
## Division of Labor
| Role | Responsibility |
|---|---|
| **Claude** | Architecture, diagnosis, Kilocode prompt authoring, sequencing |
| **Kilocode** | ALL code implementation — zero exceptions |
| **Mo** | Strategy direction, backtest execution, log collection, go/no-go |
---
## Per-Task Workflow
1. **Claude writes Kilocode prompt** — exact Find/Replace, both file paths, build command, validation checklist
2. **Mo runs Kilocode** — pastes prompt, Kilocode executes
3. **Kilocode reports** — build output + files changed
4. **Mo brings results to Claude** — Kilocode report + session log + CSV
5. **Claude diagnoses** — confirms or issues follow-up prompt
6. **Mo commits:** `git add``git commit``git push`
7. **Update SPRINT_BOARD** — task to Done or Blocked
---
## Kilocode Prompt Template
```
TASK: [one-line description]
CONTEXT:
[1-3 sentences explaining why]
FILES TO MODIFY:
1. C:\dev\nt8-sdk\src\... [repo path]
2. C:\Users\billy\...\Strategies\... [NT8 path — same change]
CHANGE 1 — [description]:
File: [path]
Find:
[exact existing code]
Replace with:
[new code]
BUILD & DEPLOY:
1. dotnet build NT8-SDK.sln --configuration Release
2. deployment\deploy-to-nt8.bat
3. NT8: Tools → Edit NinjaScript → open NT8StrategyBase.cs → save
VALIDATION:
- Run Strategy Analyzer: NQ JUN26, Jan 1 2026 → Mar 27 2026
- Look for in session log: [specific confirmation lines]
```
---
## Guardrails — Kilocode MUST NEVER
1. Modify files outside the task spec
2. Use C# 6+ syntax
3. Remove existing comments or XML documentation
4. Change interface signatures
5. Deploy without building first
6. Edit NT8 path without also updating repo path
7. Guess NT8 API signatures
8. Introduce async/await
---
## Log Analysis Quick Reference
**Healthy dual-leg trade in session log:**
```
SIGNAL Sell | Grade=A | Score=0.820
SUBMIT Scaler=1 Runner=1 Stop=8 Target=20
FILL Short 1 @ XXXXX <- scaler fill
PNL_UPDATE Position=Short Qty=1
FILL Short 1 @ XXXXX <- runner fill
PNL_UPDATE Position=Short Qty=2 <- CRITICAL: Qty=2 = runner entered
```
**Warning signs:**
- SUBMIT then only 1 FILL → runner blocked (check EntriesPerDirection + MaxOpenPositions)
- Multiple SIGNALs in milliseconds → replay burst (_realtimeBarSeen not working)
- SIGNAL then nothing → ProcessStrategyIntent guard blocking backtest
---
## Commit Message Format
```
feat: description <- new feature
fix: description <- bug fix
refactor: description <- no behavior change
test: description <- tests only
docs: description <- documentation only
```
---
## Original Archon Workflow (2025, archived below)
## Archon Workflow Principles ## Archon Workflow Principles

View File

@@ -1,7 +1,74 @@
# Project Context — NT8 SDK (Production Hardening Phase) # Project Context — NT8 SDK (Sprint 2: SIM Validation)
**Last Updated:** 2026-03-27
You are working on the **NT8 SDK** — an institutional-grade algorithmic trading framework for NinjaTrader 8. You are working on the **NT8 SDK** — an institutional-grade algorithmic futures trading system for NinjaTrader 8.
This is production trading software. Bugs cause real financial losses. This is **production trading software**. Bugs cause real financial losses. Never take shortcuts.
---
## Critical Rules for Kilocode
1. **Only modify files listed in the task spec.** Never touch adjacent code.
2. **C# 5.0 only.** No `$""`, no `?.`, no `=>` bodies, no `nameof()`, no async/await.
3. **Never remove XML documentation or comments.**
4. **Never change interface signatures** — IStrategy, IRiskManager, IPositionSizer, INT8ExecutionBridge are frozen.
5. **Always build before deploying:** `dotnet build NT8-SDK.sln --configuration Release`
6. **Always deploy to BOTH paths** after every code change:
- Repo: `C:\dev\nt8-sdk\src\NT8.Adapters\Strategies\`
- NT8: `C:\Users\billy\Documents\NinjaTrader 8\bin\Custom\Strategies\`
7. **Never guess NT8 API signatures.** Verify at `https://developer.ninjatrader.com/docs/desktop`.
---
## Current State (2026-03-27)
**What works end-to-end:**
- SimpleORBStrategy with 10-factor confluence scoring
- NT8StrategyBase with session management, kill switch, connection recovery
- Dual-leg scaler + runner architecture (EntriesPerDirection=2 restored)
- PortfolioRiskManager singleton (kill switch, daily loss, contract cap)
- File logging (session log + settings export)
- Historical replay guard (_realtimeBarSeen)
- Execution confirmed in SIM on 2026-03-27
**Pending validation:**
- Runner leg dual-fill (Qty=2) — run backtest to confirm
- Breakeven + trail in live multi-bar scenario
---
## Architecture
```
SimpleORBNT8.cs NT8 entry point
NT8StrategyBase.cs Abstract base: bar routing, kill switch, breakeven, runner trail
SimpleORBStrategy.cs Signal: ORB detection, 10-factor confluence, _tradeTaken lock
NT8OrderAdapter.cs INT8ExecutionBridge: EnterLong/EnterShort/SetStopLoss
PortfolioRiskManager.cs Singleton: cross-strategy risk
NinjaTrader 8
```
## Key Files
| File | Path |
|---|---|
| NT8StrategyBase.cs | `src\NT8.Adapters\Strategies\` |
| SimpleORBNT8.cs | `src\NT8.Adapters\Strategies\` |
| SimpleORBStrategy.cs | `src\NT8.Strategies\Examples\` |
| NT8OrderAdapter.cs | `src\NT8.Adapters\NinjaTrader\` |
| PortfolioRiskManager.cs | `src\NT8.Core\Risk\` |
| deploy-to-nt8.bat | `deployment\` |
## Active Sprint Tasks
See `SPRINT_BOARD.md` (at `docs\architecture\phase1_sprint_plan.md`) for full task list.
Immediate next action: Run Strategy Analyzer backtest (NQ JUN26, Jan 1 2026 → Mar 27 2026) and confirm `PNL_UPDATE Position=Short Qty=2` in session log to validate runner leg.
--- ---

View File

@@ -1,4 +1,69 @@
# Designed vs. Implemented Features - Gap Analysis # NT8-SDK — Gap Analysis & Roadmap
**Version:** 3.0 | **Date:** 2026-03-27 | Supersedes all previous gap analysis documents.
---
## Open Gaps
| ID | Description | Priority | Sprint |
|---|---|---|---|
| GAP-001 | Runner leg backtest validation (Qty=2 check). EntriesPerDirection=2 restored but not backtested. | CRITICAL | S2-05 |
| GAP-002 | orbRangeTicks not wired in DailyBarContext (hardcoded 0.0 in SimpleORBNT8.OnBarUpdate) | LOW | Sprint 3 |
| GAP-003 | Risk parameter consistency: RiskPerTrade can exceed MaxTradeRisk silently. No assertion. | HIGH | S2-06 |
| GAP-004 | GetRiskStatus() returns hardcoded limit rather than registered strategy config value | LOW | Sprint 3 |
| GAP-005 | No Gitea CI pipeline. Build and test are manual. | MEDIUM | Sprint 3 |
| GAP-006 | No n8n webhook alerts for fills, risk events, connection loss | MEDIUM | Sprint 3 |
| GAP-007 | No walk-forward / out-of-sample validation. All backtests are in-sample. | HIGH | S2-08 |
| GAP-008 | Short-side profitable only in crash regimes. No regime filter. | MEDIUM | Sprint 3 |
| GAP-009 | No tick replay backtest. OnBarClose simulation compresses trade duration. | LOW | Sprint 3 |
---
## Sprint Roadmap
### Sprint 2 (ACTIVE) — SIM Validation
Goal: 2+ weeks unattended SIM with dual-leg execution confirmed.
Key pending: GAP-001 (runner validation), GAP-003 (risk consistency), GAP-007 (walk-forward).
### Sprint 3 — Production Hardening
Goal: 30-day SIM clean. CI and alerts wired.
Key work: GAP-004 through GAP-009, VWAPMeanReversion skeleton.
### Sprint 4 — Live Capital
Gate: 30-day SIM PF > 2.0, max DD < $500.
Key work: Go live 1 NQ contract, OvernightGap strategies, ops runbook.
### Sprint 5 — ML Inference
Prerequisite: 60 days live data.
Key work: FastAPI /predict, MLSignalFactorCalculator as 11th factor.
---
## Strategy Backlog
| ID | Strategy | Priority | Notes |
|---|---|---|---|
| STRAT_079 | Liquidity Sweep Reversal | Medium | Potential short-trade improvement |
| STRAT_154 | Overnight Gap Continuation | High | Leverages existing SessionManager |
| STRAT_214 | Overnight Gap Reversion | High | Counter to STRAT_154 |
| LondonORB | London ORB (3:00 AM ET) | Medium | Separate LondonORBNT8 strategy file |
| VWAP-MR | VWAP Mean Reversion | High | Sprint 3 build target |
---
## Backtest Performance Reference
| Date | Period | Trades | Win% | PF | Net | Config |
|---|---|---|---|---|---|---|
| 2026-03-27 | JanMar 2026 | 20 | 75% | **7.00** | $1,200 | trail=20 ✅ Production config |
| 2026-03-27 | JanMar 2026 | 40 | 75% | 3.69 | $1,075 | trail=12 |
| 2026-03-27 | Mar 2025Mar 2026 | 148 | 51% | 3.15 | $71,303 | 9 cts experimental |
Note: 148-trade run used RiskPerTrade=$500 + EntriesPerDirection=1 (runner blocked). Not a production reference.
---
# ARCHIVED BELOW — Original Gap Analysis (2026-02-17, superseded)
**Date:** February 17, 2026 **Date:** February 17, 2026
**Status:** Post Phase A-B-C NT8 Integration **Status:** Post Phase A-B-C NT8 Integration

View File

@@ -1,9 +1,134 @@
# NT8 SDK Project - Comprehensive Recap & Handover # NT8-SDK Project Context & Current State
**Version:** 3.0 | **Date:** 2026-03-27 | **Status:** Sprint 2 Active — SIM Validation
**Document Version:** 2.0 > This file supersedes the previous PROJECT_HANDOVER.md and is the live source of truth.
**Date:** February 16, 2026 > See also: `SPRINT_BOARD.md`, `GAP_ANALYSIS_AND_ROADMAP.md`, `CODING_PATTERNS.md`, `KILOCODE_WORKFLOW.md`
**Current Phase:** Phase 5 Complete > Full formatted handover: `NT8_SDK_Handover_Package.docx`
**Project Completion:** ~85%
---
## 1. What This Is
NT8-SDK is an institutional-grade algorithmic futures trading system built on NinjaTrader 8. It is not a research prototype — it is production trading software where bugs equal real financial losses.
The system trades NQ (Nasdaq 100 E-mini futures) using a 30-minute Opening Range Breakout strategy (SimpleORB) with a 10-factor confluence scoring engine that grades each signal A+ through F before allowing execution. A scaler/runner dual-leg architecture captures quick targets on the scaler while the runner trails for extended moves.
**Division of labor:** Claude handles architecture, diagnosis, and Kilocode prompt design. Kilocode executes ALL code changes. Mo owns strategy direction and go/no-go decisions.
---
## 2. Technology Stack
| Layer | Technology | Constraint |
|---|---|---|
| Language | C# 5.0 | Hard — NinjaScript compiler limit |
| Framework | .NET Framework 4.8 | Hard — NT8 requirement |
| Platform | NinjaTrader 8 | Hard — execution environment |
| Local repo | `C:\dev\nt8-sdk` | Windows path |
| NT8 deploy | `C:\Users\billy\Documents\NinjaTrader 8\bin\Custom\Strategies\` | Must match source |
| Deploy script | `deployment\deploy-to-nt8.bat` | Creates timestamped backups |
| VCS | Gitea (self-hosted) | `https://git.thehussains.org/mo/nt8-sdk` |
| AI coding | Kilocode | Executes ALL code changes |
| Automation | n8n (self-hosted) | Deferred to Sprint 4 |
| ML inference | Ollama (local) | Deferred to Sprint 5 |
**Critical C# constraint:** No `$""`, no `?.`, no `=>`, no async/await. Use `string.Format()`, explicit null checks, full method bodies.
---
## 3. Architecture (Top to Bottom)
```
SimpleORBNT8.cs NT8 entry point — sets defaults, adds daily bar series, builds DailyBarContext
NT8StrategyBase.cs Abstract base — bar routing, session management, kill switch, breakeven, runner
SimpleORBStrategy.cs Core signal — ORB detection, 10-factor confluence, _tradeTaken session lock
NT8OrderAdapter.cs INT8ExecutionBridge — calls EnterLong/EnterShort/SetStopLoss
PortfolioRiskManager.cs Singleton — cross-strategy daily loss + contract cap
NinjaTrader 8 Execution, fills, order management
```
---
## 4. Current Production Parameters (SIM: SimSimple ORB)
| Parameter | Value | Notes |
|---|---|---|
| Instrument | NQ JUN26 | Primary instrument |
| Bar type | 13-Range bars | |
| BarsRequiredToTrade | 50 | Warm-up guard |
| DailyLossLimit | $1,000 | |
| MaxTradeRisk | $200 | |
| RiskPerTrade | $100 | 2 contracts at current NQ prices |
| MinContracts | 1 | |
| MaxContracts | 3 | |
| MaxOpenPositions | 2 | Scaler + runner |
| EntriesPerDirection | 2 | Scaler slot 1, runner slot 2 |
| MinTradeGrade | 5 (A) | 4 (B) for broad SIM testing |
| EnableShortTrades | False | Long-only until short backtest done |
| BreakevenTriggerTicks | 20 | Tuned from 12 |
| RunnerTrailTicks | 20 | Tuned from 12 |
| OpeningRangeMinutes | 30 | 9:3010:00 ET |
| StopTicks | 8 | $40 per contract NQ |
| TargetTicks | 16 (dynamic) | Scales with ORB/ATR ratio |
---
## 5. Two-Path Deployment Rule
Every code change MUST be applied to both:
1. `C:\dev\nt8-sdk\src\NT8.Adapters\Strategies\` (repo source)
2. `C:\Users\billy\Documents\NinjaTrader 8\bin\Custom\Strategies\` (NT8 runtime)
After deployment, NT8 must recompile: Tools → Edit NinjaScript → open `NT8StrategyBase.cs` → save.
---
## 6. Key Learnings (Hard-Won)
1. **`State.Historical` guard** — `if (State == State.Realtime && !_realtimeBarSeen) return;` in `ProcessStrategyIntent` allows backtest (Historical), blocks replay burst in live.
2. **`_realtimeBarSeen` flag** — reset to `false` in `State.Realtime`, set `true` on first bar. Skips catch-up bar on live load to prevent replay burst.
3. **`EntriesPerDirection = 2`** — required for scaler + runner. Setting to 1 silently blocks the runner with no error.
4. **`SetStopLoss`/`SetProfitTarget` before `EnterLong`/`EnterShort`** — calling after entry is silently ignored in backtest.
5. **`Calculate.OnBarClose` backtest** — trades appear to close in under 1 second in logs. NT8 simulation artifact, not a bug. Live trades hold 220 minutes.
6. **NR7 warm-up** — requires 7 daily bars. Warm-up messages (0/7 bars) are correct behavior.
7. **NT8 never auto-recompiles** — always force recompile after file changes via NinjaScript Editor.
8. **Dual-path deployment mandatory** — stale deployed files cause phantom bugs where code looks right but behaves wrong.
9. **`PortfolioRiskManager` is a singleton** — fully implemented, no changes required. Kill switch, daily loss, contract cap all working.
10. **Sizing formula**`floor(RiskPerTrade / (StopTicks × $5.00))`. NQ: `$100 / (8 × $5) = 2 contracts`. Always verify `RiskPerTrade <= MaxTradeRisk`.
---
## 7. Validated Backtest Results
| Date | Period | Trades | Win% | PF | Net | Config |
|---|---|---|---|---|---|---|
| 2026-03-27 | JanMar 2026 | 20 | 75% | **7.00** | $1,200 | 1 ct, trail=20 ✅ Best |
| 2026-03-27 | JanMar 2026 | 40 | 75% | 3.69 | $1,075 | 1 ct, trail=12 |
| 2026-03-27 | Mar 2025Mar 2026 | 148 | 51% | 3.15 | $71,303 | 9 cts (experimental) |
The 9-contract run used `RiskPerTrade=$500` — not a production configuration. Runner leg was also blocked (`EntriesPerDirection=1`) for that run. Re-run required after Sprint 2 fixes.
---
## 8. Immediate Next Actions Before Market Open
1. Run Strategy Analyzer (NQ JUN26, Jan 1 2026 → Mar 27 2026) and confirm `PNL_UPDATE Position=Short Qty=2` in session log — validates runner leg
2. Verify SIM account settings: `RiskPerTrade=$100`, `BreakevenTriggerTicks=20`, `RunnerTrailTicks=20`
3. Only re-enable BX68915-15 after runner validation passes — long-only, `MaxContracts=2`, `DailyLossLimit=$500`
--- ---

View File

@@ -1,3 +1,16 @@
# NT8-SDK — Institutional Algorithmic Futures Trading System
**See `NT8_SDK_Handover_Package.docx` for the complete milestone handover document.**
Quick reference docs in repo root:
- `PROJECT_CONTEXT.md` — current state, parameters, key learnings
- `SPRINT_BOARD.md` — active sprint tasks
- `GAP_ANALYSIS_AND_ROADMAP.md` — open gaps and sprint plan
- `CODING_PATTERNS.md` — C# 5.0 rules, NT8 quirks
- `KILOCODE_WORKFLOW.md` — Kilocode prompt template and guardrails
---
# NT8 Institutional Trading SDK # NT8 Institutional Trading SDK
**Version:** 0.2.0 **Version:** 0.2.0

View File

@@ -173,7 +173,7 @@ else {
} }
if (-not $SkipVerification) { if (-not $SkipVerification) {
Write-Step "6/6" "Verifying deployment" Write-Step "6/7" "Verifying deployment"
$ok = $true $ok = $true
if (-not (Test-Path "$nt8Custom\NT8.Core.dll")) { if (-not (Test-Path "$nt8Custom\NT8.Core.dll")) {
@@ -195,13 +195,43 @@ if (-not $SkipVerification) {
Write-Success "Deployment verification passed" Write-Success "Deployment verification passed"
} }
else { else {
Write-Step "6/6" "Skipping verification" Write-Step "6/7" "Skipping verification"
}
# Step 7: Delete the compiled NinjaScript assembly so NT8 is forced to do a
# full recompile from source on next startup. Without this, NT8 may load a
# stale cached assembly and silently ignore updated .cs files.
Write-Step "7/7" "Invalidating NinjaScript compiled assembly"
$compiledDll = Join-Path $nt8Custom "NinjaTrader.Custom.dll"
$compiledPdb = Join-Path $nt8Custom "NinjaTrader.Custom.pdb"
$compiledXml = Join-Path $nt8Custom "NinjaTrader.Custom.xml"
$invalidated = 0
foreach ($artifact in @($compiledDll, $compiledPdb)) {
if (Test-Path $artifact) {
Remove-Item $artifact -Force
Write-Success ("Deleted {0}" -f (Split-Path $artifact -Leaf))
$invalidated++
}
}
if ($invalidated -gt 0) {
Write-Host " NT8 will perform a full recompile on next startup." -ForegroundColor Green
Write-Host " The .xml file is documentation only and was left in place." -ForegroundColor Gray
} else {
Write-Warn "No compiled assembly found to delete (NT8 may not have been run yet)"
} }
$duration = (Get-Date) - $startTime $duration = (Get-Date) - $startTime
Write-Header "Deployment Complete" Write-Header "Deployment Complete"
Write-Host ("Duration: {0:F1} seconds" -f $duration.TotalSeconds) Write-Host ("Duration: {0:F1} seconds" -f $duration.TotalSeconds)
Write-Host "Next: Open NinjaTrader 8 -> NinjaScript Editor -> Compile All" Write-Host ""
Write-Host "NEXT STEPS:" -ForegroundColor Cyan
Write-Host " 1. Start NinjaTrader 8 (full recompile will happen automatically)" -ForegroundColor White
Write-Host " 2. Wait for compilation to complete in the Output window" -ForegroundColor White
Write-Host " 3. Remove and re-add the strategy to the chart" -ForegroundColor White
Write-Host " 4. Verify defaults: BreakevenTriggerTicks=20 RunnerTrailTicks=20 MaxContracts=3" -ForegroundColor White
Write-Host " 5. Confirm NT8 Output shows: StartBehavior=AdoptAccountPosition EntriesPerDirection=2" -ForegroundColor White
exit 0 exit 0

View File

@@ -147,10 +147,32 @@ echo.
echo Deployment complete. echo Deployment complete.
echo Backup location: %BACKUP_DIR% echo Backup location: %BACKUP_DIR%
echo Manifest file : %MANIFEST_FILE% echo Manifest file : %MANIFEST_FILE%
echo. echo.
echo Next steps: echo Invalidating NinjaScript compiled assembly...
echo 1. Open NinjaTrader 8. set "COMPILED_DLL=%NT8_CUSTOM%\NinjaTrader.Custom.dll"
echo 2. Open NinjaScript Editor and press F5 (Compile). set "COMPILED_PDB=%NT8_CUSTOM%\NinjaTrader.Custom.pdb"
echo 3. Verify strategies appear in the Strategies list.
if exist "%COMPILED_DLL%" (
del /F /Q "%COMPILED_DLL%"
echo [OK] Deleted NinjaTrader.Custom.dll
) else (
echo [WARN] NinjaTrader.Custom.dll not found - NT8 may not have been run yet
)
if exist "%COMPILED_PDB%" (
del /F /Q "%COMPILED_PDB%"
echo [OK] Deleted NinjaTrader.Custom.pdb
)
echo.
echo ============================================================
echo NEXT STEPS:
echo 1. Start NinjaTrader 8 (full recompile happens automatically)
echo 2. Wait for compilation to finish in the Output window
echo 3. Remove and re-add the strategy to the chart
echo 4. Verify defaults: BreakevenTriggerTicks=20 RunnerTrailTicks=20 MaxContracts=3
echo 5. NT8 Output must show: StartBehavior=AdoptAccountPosition EntriesPerDirection=2
echo ============================================================
exit /b 0 exit /b 0

View File

@@ -1,7 +1,99 @@
# NT8 Institutional SDK - Phase 1 Sprint Plan # NT8-SDK — Sprint Board
**Last Updated:** 2026-03-27 | **Active Sprint:** Sprint 2
## Overview ---
This document outlines the sprint plan for Phase 1 development of the NT8 Institutional SDK. Phase 1 builds upon the completed Phase 0 foundation to deliver a more complete trading system with Order Management System (OMS), NinjaTrader 8 integration, enhanced risk controls, and market data handling.
## Sprint 2 — SIM Validation (ACTIVE)
**Goal:** Strategy runs unattended 2+ weeks in SIM with correct dual-leg execution.
**Gate:** Zero unhandled exceptions, both scaler and runner filling (Qty=2 in log), daily loss limit never accidentally triggered.
| # | Task | Status | Notes |
|---|---|---|---|
| S2-01 | Restore `EntriesPerDirection=2` | ✅ Done | Deployed 2026-03-27 |
| S2-02 | `MaxOpenPositions=2` in SimpleORBNT8 | ✅ Done | Deployed 2026-03-27 |
| S2-03 | `_realtimeBarSeen` replay guard | ✅ Done | Blocks live replay burst, allows backtest |
| S2-04 | `State.Historical` guard in ProcessStrategyIntent | ✅ Done | Restores backtest execution |
| S2-05 | Validate runner leg — Qty=2 in session log | ⬜ Pending | Run backtest after S2-01 |
| S2-06 | Risk parameter consistency validation | ⬜ Pending | Assert RiskPerTrade ≤ MaxTradeRisk |
| S2-07 | SIM unattended run 2+ weeks | ▶ In progress | Started 2026-03-27 |
| S2-08 | Walk-forward backtest split | ⬜ Pending | MarSep 2025 train / OctMar 2026 test |
| S2-09 | BX68915-15 prop firm re-enable | 🔴 Blocked | Gate: S2-05 + S2-07 pass |
---
## Sprint 3 — Production Hardening
**Goal:** 30-day SIM run clean. CI and alerts live.
| # | Task | Status | Notes |
|---|---|---|---|
| S3-01 | Gitea CI — build + test on push | ⬜ Pending | `.gitea/workflows/build.yml` |
| S3-02 | n8n webhook — fills + risk events | ⬜ Pending | HTTP POST from NT8StrategyBase |
| S3-03 | Fix `GetRiskStatus()` hardcoded limit | ⬜ Pending | Read from registered strategy config |
| S3-04 | `orbRangeTicks` wiring in DailyBarContext | ⬜ Pending | Low priority |
| S3-05 | Short-side regime filter | ⬜ Pending | 20-day MA or VIX-based gate |
| S3-06 | Tick replay validation | ⬜ Pending | 30-day window |
| S3-07 | VWAPMeanReversion strategy skeleton | ⬜ Pending | New IStrategy implementation |
---
## Sprint 4 — Live Capital
**Gate:** 30-day SIM pass rate > 70%, PF > 2.0, max drawdown < $500
| # | Task | Status |
|---|---|---|
| S4-01 | Go live 1 NQ contract | ⬜ Pending gate |
| S4-02 | OvernightGapContinuation strategy | ⬜ Pending |
| S4-03 | OvernightGapReversion strategy | ⬜ Pending |
| S4-04 | Ops runbook and emergency procedures | ⬜ Pending |
| S4-05 | Connection loss recovery testing | ⬜ Pending |
| S4-06 | CME holiday filter | ⬜ Pending |
---
## Sprint 5 — ML Inference
**Prerequisite:** 60 days of live trading data.
| # | Task |
|---|---|
| S5-01 | FastAPI /predict endpoint on Ollama workstation |
| S5-02 | HTTP client in SimpleORBStrategy |
| S5-03 | MLSignalFactorCalculator as IFactorCalculator |
| S5-04 | Feature engineering from live trade history |
| S5-05 | A/B test: with vs without ML factor |
---
## Completed (Historical)
| Task | Sprint | Completed |
|---|---|---|
| Execute trades in NT8 SIM (execution bridge wired) | Sprint 1 | 2026-03-27 |
| Historical replay burst fix | Sprint 1 | 2026-03-27 |
| NR7 warm-up guard | Phase 4 | 2026-02 |
| 10-factor confluence scoring engine | Phase 4 | 2026-02 |
| PortfolioRiskManager singleton | Phase 4 | 2026-02 |
| Analytics layer (240+ tests) | Phase 5 | 2026-02-16 |
| Breakeven + runner trail logic | Sprint 1 | 2026-03 |
| Connection loss detection | Sprint 1 | 2026-03 |
| File logging + settings export | Sprint 1 | 2026-03 |
---
## Backtest Results History
| Date | Period | Trades | Win% | PF | Net | Config |
|---|---|---|---|---|---|---|
| 2026-03-27 | JanMar 2026 | 20 | 75% | 7.00 | $1,200 | trail=20, grade=B ✅ Use this |
| 2026-03-27 | JanMar 2026 | 40 | 75% | 3.69 | $1,075 | trail=12, grade=B |
| 2026-03-27 | Mar 2025Mar 2026 | 148 | 51% | 3.15 | $71,303 | 9 cts experimental |
**Note:** The 148-trade run used `RiskPerTrade=$500` producing 9 contracts AND had `EntriesPerDirection=1` blocking the runner. Not a production reference. Re-run required post Sprint 2.
---
# ARCHIVED BELOW — Phase 1 Sprint Plan (2025-09-15, superseded)
## Overview (ARCHIVED)
This document originally outlined Phase 1 sprint planning from September 2025.
## Sprint Goals ## Sprint Goals
1. Implement Order Management System (OMS) with smart order routing 1. Implement Order Management System (OMS) with smart order routing

View File

@@ -182,6 +182,16 @@ namespace NinjaTrader.NinjaScript.Strategies
ExitShort("EmergencyFlatten"); ExitShort("EmergencyFlatten");
} }
/// <summary>
/// Returns true if the concrete strategy has ForceSessionReset enabled.
/// Override in subclass to expose the NinjaScript parameter value.
/// Default returns false so base class never forces a reset unless overridden.
/// </summary>
protected virtual bool GetForceSessionReset()
{
return false;
}
/// <summary> /// <summary>
/// Create the SDK strategy instance. /// Create the SDK strategy instance.
/// </summary> /// </summary>
@@ -207,7 +217,7 @@ namespace NinjaTrader.NinjaScript.Strategies
MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix; MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
OrderFillResolution = OrderFillResolution.Standard; OrderFillResolution = OrderFillResolution.Standard;
Slippage = 0; Slippage = 0;
StartBehavior = StartBehavior.WaitUntilFlat; StartBehavior = StartBehavior.AdoptAccountPosition;
TimeInForce = TimeInForce.Gtc; TimeInForce = TimeInForce.Gtc;
TraceOrders = false; TraceOrders = false;
RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose; RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
@@ -220,7 +230,7 @@ namespace NinjaTrader.NinjaScript.Strategies
MaxOpenPositions = 3; MaxOpenPositions = 3;
RiskPerTrade = 100.0; RiskPerTrade = 100.0;
MinContracts = 1; MinContracts = 1;
MaxContracts = 10; MaxContracts = 3;
EnableKillSwitch = false; EnableKillSwitch = false;
EnableVerboseLogging = false; EnableVerboseLogging = false;
MinTradeGrade = 4; MinTradeGrade = 4;
@@ -229,10 +239,10 @@ namespace NinjaTrader.NinjaScript.Strategies
EnableLongTrades = true; EnableLongTrades = true;
EnableShortTrades = true; EnableShortTrades = true;
EnableAutoBreakeven = true; EnableAutoBreakeven = true;
BreakevenTriggerTicks = 12; BreakevenTriggerTicks = 20;
BreakevenOffsetTicks = 1; BreakevenOffsetTicks = 1;
EnableRunner = true; EnableRunner = true;
RunnerTrailTicks = 12; RunnerTrailTicks = 20;
_killSwitchTriggered = false; _killSwitchTriggered = false;
_connectionLost = false; _connectionLost = false;
} }
@@ -242,6 +252,14 @@ namespace NinjaTrader.NinjaScript.Strategies
{ {
try try
{ {
// DIAGNOSTIC: Print actual runtime property values to confirm
// what NT8 loaded vs what SetDefaults specified.
Print(string.Format("[SDK-DIAG] SetDefaults check: BE={0} Trail={1} MaxC={2} SB={3} EPD={4}",
BreakevenTriggerTicks,
RunnerTrailTicks,
MaxContracts,
StartBehavior,
EntriesPerDirection));
InitFileLog(); InitFileLog();
InitializeSdkComponents(); InitializeSdkComponents();
_sdkInitialized = true; _sdkInitialized = true;
@@ -260,6 +278,18 @@ namespace NinjaTrader.NinjaScript.Strategies
else if (State == State.Realtime) else if (State == State.Realtime)
{ {
_realtimeBarSeen = false; _realtimeBarSeen = false;
// If ForceSessionReset is enabled, push a reset signal into the SDK strategy
// so _tradeTaken is cleared before any live bar is processed.
// This recovers from replay-burst scenarios where historical bars set _tradeTaken.
if (_sdkStrategy != null && GetForceSessionReset())
{
var resetParams = new Dictionary<string, object>();
resetParams.Add("force_session_reset", true);
_sdkStrategy.SetParameters(resetParams);
Print(string.Format("[SDK] ForceSessionReset: _tradeTaken cleared on live start at {0}", DateTime.Now.ToString("HH:mm:ss")));
}
WriteSettingsFile(); WriteSettingsFile();
} }
else if (State == State.Terminated) else if (State == State.Terminated)
@@ -748,9 +778,24 @@ namespace NinjaTrader.NinjaScript.Strategies
private BarData ConvertCurrentBar() private BarData ConvertCurrentBar()
{ {
DateTime barTimeEt;
try
{
var centralZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
var easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime utcTime = TimeZoneInfo.ConvertTimeToUtc(
DateTime.SpecifyKind(Time[0], DateTimeKind.Unspecified),
centralZone);
barTimeEt = TimeZoneInfo.ConvertTimeFromUtc(utcTime, easternZone);
}
catch
{
barTimeEt = Time[0];
}
return NT8DataConverter.ConvertBar( return NT8DataConverter.ConvertBar(
Instrument.MasterInstrument.Name, Instrument.MasterInstrument.Name,
Time[0], barTimeEt,
Open[0], Open[0],
High[0], High[0],
Low[0], Low[0],

View File

@@ -40,6 +40,10 @@ namespace NinjaTrader.NinjaScript.Strategies
[Range(1, 50)] [Range(1, 50)]
public int StopTicks { get; set; } public int StopTicks { get; set; }
[NinjaScriptProperty]
[Display(Name = "Force Session Reset On Start", GroupName = "ORB Strategy", Order = 10)]
public bool ForceSessionReset { get; set; }
[NinjaScriptProperty] [NinjaScriptProperty]
[Display(Name = "Profit Target Ticks", GroupName = "ORB Risk", Order = 2)] [Display(Name = "Profit Target Ticks", GroupName = "ORB Risk", Order = 2)]
[Range(1, 100)] [Range(1, 100)]
@@ -73,10 +77,12 @@ namespace NinjaTrader.NinjaScript.Strategies
// Long-only: short trades permanently disabled pending backtest confirmation // Long-only: short trades permanently disabled pending backtest confirmation
EnableShortTrades = false; EnableShortTrades = false;
EnableAutoBreakeven = true; EnableAutoBreakeven = true;
BreakevenTriggerTicks = 12; BreakevenTriggerTicks = 20;
BreakevenOffsetTicks = 1; BreakevenOffsetTicks = 1;
EnableRunner = true; EnableRunner = true;
RunnerTrailTicks = 12; RunnerTrailTicks = 20;
ForceSessionReset = false;
StartBehavior = StartBehavior.AdoptAccountPosition;
} }
else if (State == State.Configure) else if (State == State.Configure)
{ {
@@ -105,6 +111,11 @@ namespace NinjaTrader.NinjaScript.Strategies
} }
} }
protected override bool GetForceSessionReset()
{
return ForceSessionReset;
}
protected override IStrategy CreateSdkStrategy() protected override IStrategy CreateSdkStrategy()
{ {
return new SdkSimpleORB(OpeningRangeMinutes, StdDevMultiplier); return new SdkSimpleORB(OpeningRangeMinutes, StdDevMultiplier);

View File

@@ -203,7 +203,15 @@ namespace NT8.Strategies.Examples
} }
if (_tradeTaken) if (_tradeTaken)
{
if (_logger != null)
_logger.LogDebug(
"SimpleORBStrategy skip: trade already taken for session {0:yyyy-MM-dd}; bar={1:yyyy-MM-dd HH:mm}; symbol={2}",
_currentSessionDate,
bar.Time,
context.Symbol);
return null; return null;
}
var openingRange = _openingRangeHigh - _openingRangeLow; var openingRange = _openingRangeHigh - _openingRangeLow;
var volatilityBuffer = openingRange * (_stdDevMultiplier - 1.0); var volatilityBuffer = openingRange * (_stdDevMultiplier - 1.0);
@@ -286,6 +294,15 @@ namespace NT8.Strategies.Examples
_tradeTaken = true; _tradeTaken = true;
if (_logger != null)
_logger.LogDebug(
"SimpleORBStrategy flag set: tradeTaken={0} session={1:yyyy-MM-dd}; bar={2:yyyy-MM-dd HH:mm}; side={3}; symbol={4}",
_tradeTaken,
_currentSessionDate,
bar.Time,
candidate.Side,
candidate.Symbol);
if (_logger != null && score.Factors != null) if (_logger != null && score.Factors != null)
{ {
System.Text.StringBuilder sb = new System.Text.StringBuilder(); System.Text.StringBuilder sb = new System.Text.StringBuilder();
@@ -347,7 +364,27 @@ namespace NT8.Strategies.Examples
/// <param name="parameters">Parameter map.</param> /// <param name="parameters">Parameter map.</param>
public void SetParameters(Dictionary<string, object> parameters) public void SetParameters(Dictionary<string, object> parameters)
{ {
// Constructor-bound parameters intentionally remain immutable for deterministic behavior. if (parameters == null)
return;
// force_session_reset: clear _tradeTaken and ORB state so a fresh live session
// can trade even if historical replay set _tradeTaken before going realtime.
if (parameters.ContainsKey("force_session_reset"))
{
var val = parameters["force_session_reset"];
if (val is bool && (bool)val)
{
lock (_lock)
{
_tradeTaken = false;
_openingRangeReady = false;
_openingRangeHigh = Double.MinValue;
_openingRangeLow = Double.MaxValue;
if (_logger != null)
_logger.LogInformation("ForceSessionReset: _tradeTaken cleared, ORB state reset for live session");
}
}
}
} }
private void EnsureInitialized() private void EnsureInitialized()