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:
207
deployment/Deploy-To-NT8.ps1
Normal file
207
deployment/Deploy-To-NT8.ps1
Normal 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
|
||||
|
||||
99
deployment/NT8/install-instructions.md
Normal file
99
deployment/NT8/install-instructions.md
Normal 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.
|
||||
75
deployment/Verify-Deployment.ps1
Normal file
75
deployment/Verify-Deployment.ps1
Normal 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
|
||||
|
||||
123
deployment/deploy-to-nt8.bat
Normal file
123
deployment/deploy-to-nt8.bat
Normal 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
|
||||
|
||||
Reference in New Issue
Block a user