Production hardening: kill switch, circuit breaker, trailing stops, log level, holiday calendar
Some checks failed
Build and Test / build (push) Has been cancelled

This commit is contained in:
2026-02-24 15:00:41 -05:00
parent 0e36fe5d23
commit a87152effb
50 changed files with 12849 additions and 752 deletions

View File

@@ -0,0 +1,207 @@
<#
.SYNOPSIS
Automates deployment of NT8 SDK to NinjaTrader 8.
.DESCRIPTION
Builds, tests, copies DLLs/strategy source files, and verifies deployment.
#>
param(
[switch]$BuildFirst = $true,
[switch]$RunTests = $true,
[switch]$CopyStrategies = $true,
[switch]$SkipVerification = $false,
[string]$Configuration = "Release"
)
$ErrorActionPreference = "Stop"
$sdkRoot = "C:\dev\nt8-sdk"
$nt8Custom = "$env:USERPROFILE\Documents\NinjaTrader 8\bin\Custom"
$nt8Strategies = "$nt8Custom\Strategies"
$coreDllPath = "$sdkRoot\src\NT8.Core\bin\$Configuration\net48"
$adaptersDllPath = "$sdkRoot\src\NT8.Adapters\bin\$Configuration\net48"
$strategiesPath = "$sdkRoot\src\NT8.Adapters\Strategies"
function Write-Header {
param([string]$Message)
Write-Host ""
Write-Host ("=" * 70) -ForegroundColor Cyan
Write-Host $Message -ForegroundColor Cyan
Write-Host ("=" * 70) -ForegroundColor Cyan
}
function Write-Step {
param([string]$Step, [string]$Message)
Write-Host "`n[$Step] $Message" -ForegroundColor Yellow
}
function Write-Success {
param([string]$Message)
Write-Host " [OK] $Message" -ForegroundColor Green
}
function Write-Warn {
param([string]$Message)
Write-Host " [WARN] $Message" -ForegroundColor Yellow
}
if (-not (Test-Path $sdkRoot)) {
throw "SDK root not found: $sdkRoot"
}
if (-not (Test-Path $nt8Custom)) {
throw "NinjaTrader 8 Custom directory not found: $nt8Custom"
}
$strategyFiles = @(
"NT8StrategyBase.cs",
"SimpleORBNT8.cs",
"MinimalTestStrategy.cs"
)
Write-Header "NT8 SDK Deployment Script"
Write-Host "Configuration: $Configuration"
Write-Host "SDK Root: $sdkRoot"
Write-Host "NT8 Custom: $nt8Custom"
$startTime = Get-Date
if ($BuildFirst) {
Write-Step "1/6" "Building SDK"
Push-Location $sdkRoot
try {
& dotnet clean --configuration $Configuration --verbosity quiet
if ($LASTEXITCODE -ne 0) { throw "Clean failed" }
& dotnet build --configuration $Configuration --verbosity quiet
if ($LASTEXITCODE -ne 0) { throw "Build failed" }
Write-Success "Build succeeded"
}
finally {
Pop-Location
}
}
else {
Write-Step "1/6" "Skipping build"
}
if ($RunTests) {
Write-Step "2/6" "Running tests"
Push-Location $sdkRoot
try {
& dotnet test --configuration $Configuration --no-build --verbosity quiet
if ($LASTEXITCODE -ne 0) { throw "Tests failed" }
Write-Success "Tests passed"
}
finally {
Pop-Location
}
}
else {
Write-Step "2/6" "Skipping tests"
}
Write-Step "3/6" "Copying SDK DLLs"
if (Test-Path "$coreDllPath\NT8.Core.dll") {
Copy-Item "$coreDllPath\NT8.Core.dll" $nt8Custom -Force
Write-Success "Copied NT8.Core.dll"
}
else {
throw "NT8.Core.dll not found at $coreDllPath"
}
if (Test-Path "$adaptersDllPath\NT8.Adapters.dll") {
Copy-Item "$adaptersDllPath\NT8.Adapters.dll" $nt8Custom -Force
Write-Success "Copied NT8.Adapters.dll"
}
else {
Write-Warn "NT8.Adapters.dll not found (may be expected)"
}
Write-Step "4/6" "Copying dependencies"
$dependencies = @(
"Microsoft.Extensions.*.dll",
"System.Memory.dll",
"System.Buffers.dll",
"System.Runtime.CompilerServices.Unsafe.dll"
)
$depCopied = 0
foreach ($pattern in $dependencies) {
$files = Get-ChildItem "$coreDllPath\$pattern" -ErrorAction SilentlyContinue
foreach ($f in $files) {
Copy-Item $f.FullName $nt8Custom -Force
$depCopied++
}
}
if ($depCopied -gt 0) {
Write-Success ("Copied {0} dependencies" -f $depCopied)
}
else {
Write-Warn "No dependency files copied"
}
if ($CopyStrategies) {
Write-Step "5/6" "Copying strategy files"
if (-not (Test-Path $nt8Strategies)) {
New-Item -ItemType Directory -Path $nt8Strategies -Force | Out-Null
}
$copied = 0
foreach ($file in $strategyFiles) {
$sourcePath = Join-Path $strategiesPath $file
if (Test-Path $sourcePath) {
Copy-Item $sourcePath $nt8Strategies -Force
Write-Success ("Copied {0}" -f $file)
$copied++
}
else {
Write-Warn ("Missing {0}" -f $file)
}
}
if ($copied -eq 0) {
throw "No strategy files copied"
}
}
else {
Write-Step "5/6" "Skipping strategy copy"
}
if (-not $SkipVerification) {
Write-Step "6/6" "Verifying deployment"
$ok = $true
if (-not (Test-Path "$nt8Custom\NT8.Core.dll")) {
$ok = $false
Write-Warn "NT8.Core.dll missing after copy"
}
foreach ($file in $strategyFiles) {
if (-not (Test-Path (Join-Path $nt8Strategies $file))) {
$ok = $false
Write-Warn ("{0} missing after copy" -f $file)
}
}
if (-not $ok) {
throw "Deployment verification failed"
}
Write-Success "Deployment verification passed"
}
else {
Write-Step "6/6" "Skipping verification"
}
$duration = (Get-Date) - $startTime
Write-Header "Deployment Complete"
Write-Host ("Duration: {0:F1} seconds" -f $duration.TotalSeconds)
Write-Host "Next: Open NinjaTrader 8 -> NinjaScript Editor -> Compile All"
exit 0

View File

@@ -0,0 +1,99 @@
# NT8 SDK Installation Instructions
## Overview
This guide documents manual and scripted deployment of the NT8 SDK into NinjaTrader 8.
## Prerequisites
1. Windows machine with NinjaTrader 8 installed.
2. NinjaTrader 8 has been launched at least one time so the Custom folder exists.
3. .NET SDK available for building release binaries.
4. Repository checked out locally.
## Expected Paths
- Project root: `c:\dev\nt8-sdk`
- Deployment script: `c:\dev\nt8-sdk\deployment\deploy-to-nt8.bat`
- NinjaTrader custom folder: `%USERPROFILE%\Documents\NinjaTrader 8\bin\Custom`
## Build Release Artifacts
Run this from repository root:
```bat
cd c:\dev\nt8-sdk && dotnet build NT8-SDK.sln --configuration Release
```
Expected outputs:
- `src\NT8.Core\bin\Release\net48\NT8.Core.dll`
- `src\NT8.Adapters\bin\Release\net48\NT8.Adapters.dll`
## Deploy Using Script (Recommended)
Run:
```bat
cd c:\dev\nt8-sdk\deployment && deploy-to-nt8.bat
```
What the script does:
1. Validates NinjaTrader custom folder exists.
2. Validates release binaries exist.
3. Creates backup folder under `deployment\backups\<timestamp>`.
4. Backs up existing deployed SDK files.
5. Copies DLLs into NinjaTrader Custom folder.
6. Copies wrapper strategy source files into `Custom\Strategies`.
7. Verifies expected deployed files exist after copy.
8. Writes `manifest.txt` into the backup folder with source/destination details.
## Verify Deployment in NinjaTrader 8
1. Open NinjaTrader 8.
2. Open NinjaScript Editor.
3. Press `F5` to compile.
4. Confirm no compile errors.
5. Open Strategies window and verify wrappers are listed:
- `BaseNT8StrategyWrapper`
- `SimpleORBNT8Wrapper`
## Rollback Procedure
If deployment must be reverted:
1. Locate the latest backup in `deployment\backups`.
2. Review `manifest.txt` in that backup folder to confirm file set and paths.
2. Copy files back into:
- `%USERPROFILE%\Documents\NinjaTrader 8\bin\Custom`
- `%USERPROFILE%\Documents\NinjaTrader 8\bin\Custom\Strategies`
3. Recompile in NinjaTrader (`F5`).
## Troubleshooting
### "NinjaTrader Custom folder not found"
- Launch NinjaTrader once.
- Confirm `%USERPROFILE%\Documents\NinjaTrader 8\bin\Custom` exists.
### "Core DLL not found" or "Adapters DLL not found"
- Re-run release build:
```bat
cd c:\dev\nt8-sdk && dotnet build NT8-SDK.sln --configuration Release
```
### NinjaScript compile errors after deploy
- Confirm target framework remains .NET Framework 4.8.
- Confirm C# 5.0-compatible syntax in wrappers.
- Restore from backup and redeploy after fixes.
## Operational Notes
- Deploy only when NinjaTrader strategy execution is stopped.
- Keep timestamped backups for audit and rollback.
- Keep `manifest.txt` with each backup for deployment traceability.
- Re-run deployment after every release build update.

View File

@@ -0,0 +1,75 @@
<#
.SYNOPSIS
Verifies NT8 SDK deployment without rebuilding.
#>
param(
[switch]$Detailed
)
$nt8Custom = "$env:USERPROFILE\Documents\NinjaTrader 8\bin\Custom"
$nt8Strategies = "$nt8Custom\Strategies"
$requiredDlls = @("NT8.Core.dll")
$optionalDlls = @("NT8.Adapters.dll")
$strategyFiles = @("NT8StrategyBase.cs", "SimpleORBNT8.cs", "MinimalTestStrategy.cs")
Write-Host "NT8 SDK Deployment Verification" -ForegroundColor Cyan
Write-Host ("=" * 50)
$allGood = $true
Write-Host "\nChecking Custom directory..." -ForegroundColor Yellow
foreach ($dll in $requiredDlls) {
$path = Join-Path $nt8Custom $dll
if (Test-Path $path) {
Write-Host " [OK] $dll" -ForegroundColor Green
if ($Detailed) {
$info = Get-Item $path
Write-Host (" Size: {0} KB" -f [math]::Round($info.Length / 1KB, 2)) -ForegroundColor Gray
Write-Host (" Modified: {0}" -f $info.LastWriteTime) -ForegroundColor Gray
}
}
else {
Write-Host " [MISSING] $dll" -ForegroundColor Red
$allGood = $false
}
}
foreach ($dll in $optionalDlls) {
$path = Join-Path $nt8Custom $dll
if (Test-Path $path) {
Write-Host " [OK] $dll (optional)" -ForegroundColor Green
}
else {
Write-Host " [SKIP] $dll (optional)" -ForegroundColor Gray
}
}
Write-Host "\nChecking Strategies directory..." -ForegroundColor Yellow
foreach ($file in $strategyFiles) {
$path = Join-Path $nt8Strategies $file
if (Test-Path $path) {
Write-Host " [OK] $file" -ForegroundColor Green
if ($Detailed) {
$info = Get-Item $path
Write-Host (" Size: {0} KB" -f [math]::Round($info.Length / 1KB, 2)) -ForegroundColor Gray
Write-Host (" Modified: {0}" -f $info.LastWriteTime) -ForegroundColor Gray
}
}
else {
Write-Host " [MISSING] $file" -ForegroundColor Red
$allGood = $false
}
}
Write-Host ""
if ($allGood) {
Write-Host "[OK] Deployment verified - all required files present" -ForegroundColor Green
exit 0
}
Write-Host "[FAIL] Deployment incomplete - missing required files" -ForegroundColor Red
Write-Host "Run: .\deployment\Deploy-To-NT8.ps1" -ForegroundColor Yellow
exit 1

View File

@@ -0,0 +1,123 @@
@echo off
setlocal
REM NT8 SDK Deployment Script
REM Copies release binaries and NT8 wrapper scripts into NinjaTrader 8 Custom folders.
set "SCRIPT_DIR=%~dp0"
set "PROJECT_ROOT=%SCRIPT_DIR%.."
set "NT8_CUSTOM=%USERPROFILE%\Documents\NinjaTrader 8\bin\Custom"
set "NT8_STRATEGIES=%NT8_CUSTOM%\Strategies"
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
echo Project Root: %PROJECT_ROOT%
echo NT8 Custom : %NT8_CUSTOM%
echo ============================================================
if not exist "%NT8_CUSTOM%" (
echo ERROR: NinjaTrader Custom folder not found.
echo Expected path: %NT8_CUSTOM%
echo Ensure NinjaTrader 8 is installed and started once.
exit /b 1
)
if not exist "%CORE_BIN%\NT8.Core.dll" (
echo ERROR: Core DLL not found: %CORE_BIN%\NT8.Core.dll
echo Build release artifacts first:
echo dotnet build NT8-SDK.sln --configuration Release
exit /b 1
)
if not exist "%ADAPTERS_BIN%\NT8.Adapters.dll" (
echo ERROR: Adapters DLL not found: %ADAPTERS_BIN%\NT8.Adapters.dll
echo Build release artifacts first:
echo dotnet build NT8-SDK.sln --configuration Release
exit /b 1
)
if not exist "%NT8_STRATEGIES%" (
mkdir "%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
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
if exist "%NT8_CUSTOM%\NT8.Adapters.dll" copy /Y "%NT8_CUSTOM%\NT8.Adapters.dll" "%BACKUP_DIR%\NT8.Adapters.dll" >nul
if exist "%NT8_STRATEGIES%\BaseNT8StrategyWrapper.cs" copy /Y "%NT8_STRATEGIES%\BaseNT8StrategyWrapper.cs" "%BACKUP_DIR%\BaseNT8StrategyWrapper.cs" >nul
if exist "%NT8_STRATEGIES%\SimpleORBNT8Wrapper.cs" copy /Y "%NT8_STRATEGIES%\SimpleORBNT8Wrapper.cs" "%BACKUP_DIR%\SimpleORBNT8Wrapper.cs" >nul
echo Deployment manifest > "%MANIFEST_FILE%"
echo Timestamp: %STAMP%>> "%MANIFEST_FILE%"
echo Source Core DLL: %CORE_BIN%\NT8.Core.dll>> "%MANIFEST_FILE%"
echo Source Adapters DLL: %ADAPTERS_BIN%\NT8.Adapters.dll>> "%MANIFEST_FILE%"
echo Destination Custom Folder: %NT8_CUSTOM%>> "%MANIFEST_FILE%"
echo Destination Strategies Folder: %NT8_STRATEGIES%>> "%MANIFEST_FILE%"
echo Deploying DLLs...
copy /Y "%CORE_BIN%\NT8.Core.dll" "%NT8_CUSTOM%\NT8.Core.dll" >nul
if errorlevel 1 (
echo ERROR: Failed to copy NT8.Core.dll
exit /b 1
)
copy /Y "%ADAPTERS_BIN%\NT8.Adapters.dll" "%NT8_CUSTOM%\NT8.Adapters.dll" >nul
if errorlevel 1 (
echo ERROR: Failed to copy NT8.Adapters.dll
exit /b 1
)
echo Deploying wrapper sources...
copy /Y "%WRAPPERS_SRC%\BaseNT8StrategyWrapper.cs" "%NT8_STRATEGIES%\BaseNT8StrategyWrapper.cs" >nul
if errorlevel 1 (
echo ERROR: Failed to copy BaseNT8StrategyWrapper.cs
exit /b 1
)
copy /Y "%WRAPPERS_SRC%\SimpleORBNT8Wrapper.cs" "%NT8_STRATEGIES%\SimpleORBNT8Wrapper.cs" >nul
if errorlevel 1 (
echo ERROR: Failed to copy SimpleORBNT8Wrapper.cs
exit /b 1
)
echo Verifying deployment files...
if not exist "%NT8_CUSTOM%\NT8.Core.dll" (
echo ERROR: Verification failed for NT8.Core.dll
exit /b 1
)
if not exist "%NT8_CUSTOM%\NT8.Adapters.dll" (
echo ERROR: Verification failed for NT8.Adapters.dll
exit /b 1
)
if not exist "%NT8_STRATEGIES%\BaseNT8StrategyWrapper.cs" (
echo ERROR: Verification failed for BaseNT8StrategyWrapper.cs
exit /b 1
)
if not exist "%NT8_STRATEGIES%\SimpleORBNT8Wrapper.cs" (
echo ERROR: Verification failed for SimpleORBNT8Wrapper.cs
exit /b 1
)
echo.
echo Deployment complete.
echo Backup location: %BACKUP_DIR%
echo Manifest file : %MANIFEST_FILE%
echo.
echo Next steps:
echo 1. Open NinjaTrader 8.
echo 2. Open NinjaScript Editor and press F5 (Compile).
echo 3. Verify strategies appear in the Strategies list.
exit /b 0