Phase 0 completion: NT8 SDK core framework with risk management and position sizing
Some checks failed
Build and Test / build (push) Has been cancelled

This commit is contained in:
Billy Valentine
2025-09-09 17:06:37 -04:00
parent 97e5050d3e
commit 92f3732b3d
109 changed files with 38593 additions and 380 deletions

View File

@@ -0,0 +1,105 @@
# NT8 SDK - Code Review Checklist
## Pre-Commit Checklist for AI Agents
### ✅ Compatibility Check
- [ ] All projects target `net48`
- [ ] Language version set to `5.0` in all projects
- [ ] No modern C# features used (records, nullable refs, string interpolation)
- [ ] No .NET Core packages added
- [ ] `.\verify-build.bat` passes with zero errors
### ✅ Architecture Compliance
- [ ] All trading logic goes through IRiskManager
- [ ] Strategies are thin plugins (signal generation only)
- [ ] No direct market access from strategies
- [ ] Proper error handling and logging
### ✅ Code Quality
- [ ] All classes have proper constructors (no auto-properties with initializers)
- [ ] Dictionary initialization uses `.Add()` method
- [ ] String formatting uses `String.Format()` not interpolation
- [ ] All interfaces properly implemented
- [ ] Unit tests included for new functionality
### ✅ Testing Requirements
- [ ] MSTest framework used (not xUnit)
- [ ] Test coverage >80% for core components
- [ ] All risk scenarios tested
- [ ] Integration tests work with mock data
## Common Rejection Reasons
### ❌ Automatic Rejection
1. **Uses C# 6+ features** (records, nullable refs, etc.)
2. **Targets wrong framework** (.NET Core instead of Framework 4.8)
3. **Adds incompatible packages** (Microsoft.Extensions.*)
4. **Bypasses risk management** (direct order submission)
5. **Build fails** (compilation errors, warnings)
### ⚠️ Review Required
1. **Complex inheritance hierarchies**
2. **Performance-critical code** (may need optimization later)
3. **External dependencies** (evaluate NT8 compatibility)
4. **Configuration changes** (verify impact on existing functionality)
## Review Process
### For Human Reviewers
1. **Run verification**: `.\verify-build.bat`
2. **Check guidelines**: Verify compliance with `AI_DEVELOPMENT_GUIDELINES.md`
3. **Test coverage**: Ensure new features have adequate tests
4. **Architecture review**: Confirm risk-first design maintained
### For AI Agents
1. **Self-check**: Use this checklist before submitting
2. **Build verification**: Always run build verification
3. **Pattern matching**: Follow existing code patterns in the repo
4. **Documentation**: Update relevant docs if needed
## Phase-Specific Guidelines
### Current Phase (Phase 1)
- Focus on NT8 integration only
- Implement basic order management
- Enhance risk controls (Tier 2)
- No UI work or advanced features
### Future Phases
- Will be specified in separate guidelines
- Do not implement features from future phases
- Stay within current phase scope
## Examples of Good vs Bad Code
### ✅ Good (C# 5.0 Compatible)
```csharp
public class RiskDecision
{
public bool Allow { get; set; }
public string RejectReason { get; set; }
public RiskDecision(bool allow, string rejectReason)
{
Allow = allow;
RejectReason = rejectReason;
}
}
var metrics = new Dictionary<string, object>();
metrics.Add("risk", 100.0);
metrics.Add("reason", "Daily limit");
```
### ❌ Bad (Modern C# - Will Not Compile)
```csharp
public record RiskDecision(bool Allow, string? RejectReason);
var metrics = new Dictionary<string, object>
{
["risk"] = 100.0,
["reason"] = "Daily limit"
};
```
This checklist should be used by AI agents before every commit and by human reviewers for all pull requests.

View File

@@ -0,0 +1,273 @@
# NT8 SDK Code Style Guide
## Required Patterns for AI Agents
### Class Declaration Pattern
```csharp
using System;
using System.Collections.Generic;
namespace NT8.Core.SomeModule
{
/// <summary>
/// Class description
/// </summary>
public class ClassName
{
private readonly Type _field;
/// <summary>
/// Property description
/// </summary>
public Type PropertyName { get; set; }
/// <summary>
/// Constructor description
/// </summary>
public ClassName(Type parameter)
{
if (parameter == null) throw new ArgumentNullException("parameter");
_field = parameter;
}
/// <summary>
/// Method description
/// </summary>
public ReturnType MethodName(Type parameter)
{
// Implementation
}
}
}
```
### Interface Implementation Pattern
```csharp
/// <summary>
/// Interface description
/// </summary>
public interface IInterfaceName
{
/// <summary>
/// Method description
/// </summary>
ReturnType MethodName(Type parameter);
}
/// <summary>
/// Implementation description
/// </summary>
public class Implementation : IInterfaceName
{
public ReturnType MethodName(Type parameter)
{
// Implementation
}
}
```
### Dictionary Initialization Pattern (C# 5.0)
```csharp
// ✅ REQUIRED Pattern
var dictionary = new Dictionary<string, object>();
dictionary.Add("key1", value1);
dictionary.Add("key2", value2);
// ❌ FORBIDDEN Pattern
var dictionary = new Dictionary<string, object>
{
["key1"] = value1,
["key2"] = value2
};
```
### String Formatting Pattern (C# 5.0)
```csharp
// ✅ REQUIRED Pattern
var message = String.Format("Processing {0} with value {1:F2}", name, amount);
_logger.LogInformation("Order {0} status: {1}", orderId, status);
// ❌ FORBIDDEN Pattern
var message = $"Processing {name} with value {amount:F2}";
_logger.LogInformation($"Order {orderId} status: {status}");
```
### Async Method Pattern (C# 5.0)
```csharp
/// <summary>
/// Async method description
/// </summary>
public async Task<ReturnType> MethodNameAsync(Type parameter)
{
// Async implementation
var result = await SomeAsyncOperation();
return result;
}
```
### Error Handling Pattern
```csharp
public ReturnType MethodName(Type parameter)
{
if (parameter == null) throw new ArgumentNullException("parameter");
try
{
// Implementation
return result;
}
catch (SpecificException ex)
{
_logger.LogError("Specific error occurred: {0}", ex.Message);
throw; // or handle appropriately
}
catch (Exception ex)
{
_logger.LogError("Unexpected error: {0}", ex.Message);
throw;
}
}
```
### Test Class Pattern (MSTest)
```csharp
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NT8.Core.SomeModule;
namespace NT8.Core.Tests.SomeModule
{
[TestClass]
public class ClassNameTests
{
private ClassName _target;
[TestInitialize]
public void TestInitialize()
{
_target = new ClassName(/* parameters */);
}
[TestMethod]
public void MethodName_Condition_ExpectedResult()
{
// Arrange
var input = /* test data */;
// Act
var result = _target.MethodName(input);
// Assert
Assert.IsTrue(result.Success);
Assert.AreEqual(expected, result.Value);
}
[TestMethod]
public void MethodName_InvalidInput_ThrowsException()
{
// Act & Assert
Assert.ThrowsException<ArgumentNullException>(() => _target.MethodName(null));
}
}
}
```
### Configuration Class Pattern
```csharp
/// <summary>
/// Configuration class description
/// </summary>
public class ConfigurationClass
{
/// <summary>
/// Property description
/// </summary>
public Type PropertyName { get; set; }
/// <summary>
/// Constructor with all required parameters
/// </summary>
public ConfigurationClass(Type parameter1, Type parameter2)
{
PropertyName1 = parameter1;
PropertyName2 = parameter2;
}
}
```
### Enum Pattern
```csharp
/// <summary>
/// Enum description
/// </summary>
public enum EnumName
{
/// <summary>
/// First value description
/// </summary>
FirstValue,
/// <summary>
/// Second value description
/// </summary>
SecondValue
}
```
## Naming Conventions
### Classes and Interfaces
- **Classes**: PascalCase (`RiskManager`, `PositionSizer`)
- **Interfaces**: IPascalCase (`IRiskManager`, `IPositionSizer`)
### Methods and Properties
- **Methods**: PascalCase (`ValidateOrder`, `CalculateSize`)
- **Properties**: PascalCase (`Symbol`, `Quantity`)
### Fields and Variables
- **Private fields**: _camelCase (`_logger`, `_riskConfig`)
- **Local variables**: camelCase (`riskAmount`, `contracts`)
- **Constants**: UPPER_CASE (`MAX_CONTRACTS`, `DEFAULT_TIMEOUT`)
### Parameters
- **Parameters**: camelCase (`intent`, `context`, `config`)
## File Organization
### Using Statements Order
```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using NT8.Core.Common.Models;
using NT8.Core.Logging;
```
### Namespace and Class Structure
```csharp
namespace NT8.Core.ModuleName
{
/// <summary>
/// Class documentation
/// </summary>
public class ClassName
{
// 1. Private fields
private readonly Type _field;
// 2. Public properties
public Type Property { get; set; }
// 3. Constructor(s)
public ClassName() { }
// 4. Public methods
public void PublicMethod() { }
// 5. Private methods
private void PrivateMethod() { }
}
}
```
These patterns MUST be followed by all AI agents to ensure consistency and compatibility.

View File

@@ -0,0 +1,204 @@
ALWAYS verify with the live Ninjascript reference available on the web at https://developer.ninjatrader.com/docs/desktop before making final edits.
This third file confirms a recurrence of CS0246 compiler errors in VWAP_Pro.cs, specifically related to undefined types like ModeType and AnchorModeType.
🔍 CS0246 - "The type or namespace name 'X' could not be found"
Line Column Missing Type
371 28 ModeType
371 43 AnchorModeType
391 39 ModeType
391 54 AnchorModeType
376 51 ModeType
✅ How to Fix It
🔧 1. Define Missing Enums (Recommended Fix)
It seems that ModeType and AnchorModeType are custom enums that were expected to exist in the code but were never declared.
Create a separate file or include this in the same VWAP_Pro.cs file near the top:
public enum ModeType
{
Standard,
Aggressive,
Conservative
}
public enum AnchorModeType
{
SessionStart,
FixedTime,
Custom
}
Youll need to customize the enum values (Standard, Aggressive, etc.) to match your strategy logic. These names are placeholders based on typical VWAP settings.
🔧 2. OR Add Missing using Directives
If these types exist in another NinjaTrader script or add-on you've imported before, ensure you include the right namespace:
using NinjaTrader.NinjaScript.AddOns.MyVWAPEnums; // Example
But since these errors suggest the types are completely undefined, it's much more likely they are simply not declared anywhere.
🔧 3. Verify File Inclusion in NinjaTrader
If these enums are defined in another file (e.g., VWAPTypes.cs), make sure:
It's saved in the same directory as VWAP_Pro.cs
It's added to the NinjaScript Editor, not just sitting in the file system
You can add it using:
Tools > NinjaScript Editor > Right-click > Add > Existing Item...
🧼 Suggested Organization
If these enums are used across multiple indicators/strategies, you should centralize them:
VWAP_Enums.cs
namespace NinjaTrader.NinjaScript.VWAP
{
public enum ModeType
{
Standard,
Aggressive,
Conservative
}
public enum AnchorModeType
{
SessionStart,
FixedTime,
Custom
}
}
Then use:
using NinjaTrader.NinjaScript.VWAP;
These are occurring in VWAP_Pro.cs, mainly on lines 132134:
Line Error Message (Truncated)
132 Argument 2: cannot convert from 'int' to 'NinjaTrader.Gui.Tools.SimpleFont'
132 Argument 3: cannot convert from 'NinjaTrader.Gui.Tools.SimpleFont' to 'System.Windows.Media.Brush'
133 Same as above
134 Same as above
🔧 Interpretation:
It looks like a method (likely a drawing method like Draw.Text() or Draw.TextFixed()) is being called with the wrong argument types — specifically:
An int is being passed where a SimpleFont is expected.
A SimpleFont is being passed where a Brush is expected.
This suggests that arguments are out of order or misassigned.
✅ Proper Fix
Lets consider the proper usage of Draw.Text() in NinjaTrader 8:
Draw.Text(NinjaScriptBase owner, string tag, bool isAutoScale, string text, int barsAgo, double y, Brush textBrush, SimpleFont font, TextAlignment alignment, Brush outlineBrush, int outlineWidth);
Or for simpler usage:
Draw.Text(this, "tag1", "Hello", 0, Close[0], Brushes.White);
Your issue likely looks like this:
Draw.Text(this, "tag1", true, "Label", 0, 100, 12, someFont, ...);
Where 12 (int) is mistakenly passed as a font or brush, causing the error.
🔧 Corrected Example:
Assuming you want to draw text with a specific font and color:
SimpleFont font = new SimpleFont("Arial", 12);
Draw.Text(this, "tag1", true, "VWAP Label", 0, Close[0], Brushes.White, font, TextAlignment.Center, Brushes.Black, 1);
Brushes.White → text color
font → SimpleFont object
TextAlignment.Center → alignment
Brushes.Black → outline brush
1 → outline width
✅ Steps to Fix:
Replace the integer (e.g., 12) with a SimpleFont:
new SimpleFont("Arial", 12)
Ensure arguments are in the correct order:
Double-check the method signature from the NinjaTrader 8 Help Guide
.
Use Brushes for colors, not fonts.
Summary of Errors:
Line Column Missing Type
403 39 ModeType
403 54 AnchorModeType
408 63 ModeType
408 78 AnchorModeType
367 28 ModeType
✅ Fixes:
These types — ModeType and AnchorModeType — are not recognized. Here are the likely causes and solutions:
🔍 1. Missing using Directive
These types might be defined in a different namespace. If they are from a custom or NinjaTrader add-on:
Fix: Add the appropriate using statement at the top of your file.
Example:
using NinjaTrader.NinjaScript.AddOns.VWAP;
Adjust according to where ModeType and AnchorModeType are defined.
🔍 2. Missing Class Definitions
If they are not in any existing libraries, they might be custom enum types that should be defined in your project but are missing.
Fix: Add enum declarations like these (if applicable):
public enum ModeType
{
Standard,
Aggressive,
Conservative
}
public enum AnchorModeType
{
SessionStart,
FixedTime,
Custom
}
Only do this if you know what the enum values should be. These names are placeholders — you should match them with how your indicator/strategy is designed.

View File

@@ -0,0 +1,502 @@
o help ensure that NinjaTrader 8 (NT8) code compiles successfully the first time, every time, you can give your developers a clear set of compile-time directives, guardrails, and best practices. Below is a comprehensive guide you can use or adapt as a compile spec or code review checklist.
✅ NinjaTrader 8 Compile-Time Success Directives
🧱 1. Code Structure & Class Guidelines
Each script must extend only the correct NT8 base class:
Indicator, Strategy, MarketAnalyzerColumn, etc.
Use [GeneratedCode] attributes only where required.
Avoid partial classes unless absolutely necessary.
🔍 2. File & Naming Conventions
Class name and file name must match.
No duplicate class names, even across namespaces.
Avoid reserved words or NT8 system identifiers.
📦 3. Namespace Hygiene
Always use:
using System;
using NinjaTrader.Cbi;
using NinjaTrader.Gui.Tools;
using NinjaTrader.NinjaScript;
using NinjaTrader.Data;
using NinjaTrader.Gui;
using NinjaTrader.NinjaScript.Strategies;
using NinjaTrader.NinjaScript.Indicators;
Avoid unnecessary or ambiguous using directives (e.g., from other frameworks).
🧪 4. Method & Lifecycle Integrity
Ensure these NT8 methods are implemented correctly:
protected override void OnStateChange()
protected override void OnBarUpdate()
protected override void OnMarketData(MarketDataEventArgs e) // if used
Avoid:
Missing break statements in switch.
Logic in OnBarUpdate() without BarsInProgress checks when using multiple series.
🛡️ 5. Error-Free State Management
Always check states in OnStateChange():
if (State == State.SetDefaults) { ... }
if (State == State.Configure) { ... }
if (State == State.DataLoaded) { ... }
Avoid placing runtime logic or order submissions in SetDefaults or Configure.
⛔ 6. No Runtime Calls at Compile-Time
Do not call:
Print() inside SetDefaults
AddDataSeries() inside wrong state
CalculateXXX() outside Configure
🧯 7. Null Checks and Bounds
Always check:
if (CurrentBar < X) return;
if (BarsInProgress != 0) return; // If multi-series used
if (mySeries == null) return;
Prevent index out of range errors:
if (CurrentBar < myPeriod) return;
double value = Close[0]; // Only if safe
🧰 8. Avoid Common Pitfalls
No empty catch blocks or silent exceptions.
No hardcoded bar indexes or array sizes.
Avoid referencing objects that may be null (e.g., BarsArray[1], SMA() without initialization).
📚 9. Dependencies & Resources
No external libraries unless they are approved and included in the solution.
Ensure all custom indicators or referenced strategies exist and are compiled.
📏 10. Strategy Parameters & UI Defaults
Provide all necessary [NinjaScriptProperty] parameters.
Set default values cleanly inside State.SetDefaults.
Use Name = "MyStrategy" for naming.
🧹 11. Code Hygiene & Readability
Consistent indentation, spacing, and braces.
No commented-out blocks of old code in final delivery.
Regions (#region) for each main section: Inputs, Initialization, Logic, etc.
🧪 12. Pre-Compile Self-Test Macro (Optional)
If feasible, add a conditional debug directive:
#if DEBUG
Print("DEBUG: Compiling MyStrategy");
#endif
Pre-Delivery Checklist for Developers
Checkpoint Status
No compile errors or warnings
Clean OnStateChange() structure
Safe OnBarUpdate() logic
Proper BarsInProgress handling
All inputs and parameters declared
Class name matches file name
No unused using directives
Strategy or indicator tested
Heres a practical compile-spec + guardrails you can hand to any dev so their NinjaTrader 8 code compiles cleanly the first timeno surprises, no Order Flow+ dependencies, and no signature mismatches.
NinjaTrader 8 First-Time Compile Spec
0) Golden rules (pin these in the PR template)
Target base class: public class <Name> : Strategy in the namespace NinjaTrader.NinjaScript.Strategies.
File name = class name (e.g., ORBV4.cs contains public class ORBV4 : Strategy).
Correct override access: all NT8 overrides must be protected override, never public or private.
No dead APIs: do not implement OnStartUp() (doesnt exist). Use OnStateChange() with state switches.
No Order Flow+ unless requested: never reference indicators like OrderFlow VWAP if the environment may not have it.
No invented enum values: never use things like OrderState.PendingSubmit or RejectedByExchange. Only use enums that exist in NT8.
Attributes present: using System.ComponentModel.DataAnnotations; for [Range] and [Display]. Use [NinjaScriptProperty] for user inputs.
Indicators & series created only in State.DataLoaded (not in State.SetDefaults).
Bar guards at top of OnBarUpdate: if (BarsInProgress != 0) return; if (CurrentBar < BarsRequiredToTrade) return;
Managed vs Unmanaged: pick exactly one model and stick to its API patterns in the whole file.
1) Required using directives (top of every strategy file)
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using NinjaTrader.Cbi;
using NinjaTrader.Data;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.Tools;
using NinjaTrader.NinjaScript;
using NinjaTrader.NinjaScript.Strategies;
using NinjaTrader.NinjaScript.Indicators;
2) Required lifecycle pattern (no OnStartUp)
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Name = "StrategyName";
Description = "Short description";
Calculate = Calculate.OnBarClose; // Change only if truly needed
IsInstantiatedOnEachOptimizationIteration = true;
IsOverlay = false;
BarsRequiredToTrade = 20;
// Defaults for public properties
RiskTicks = 16;
UseRthOnly = true;
}
else if (State == State.Configure)
{
// Set up data series, trading hours behavior, etc. (no indicators here)
// Example: AddDataSeries(BarsPeriodType.Minute, 1);
}
else if (State == State.DataLoaded)
{
// Create indicators/series
sma = SMA(20); // Allowed; built-in indicator
// vwap = VWAP(...); // Avoid if Order Flow+ isnt guaranteed
}
}
3) Correct signatures for event hooks (copy exactly)
OnBarUpdate
protected override void OnBarUpdate()
{
if (BarsInProgress != 0) return;
if (CurrentBar < BarsRequiredToTrade) return;
// Strategy logic here
}
OnOrderUpdate (Managed or Unmanagedsignature is the same)
protected override void OnOrderUpdate(
Order order,
double limitPrice,
double stopPrice,
int quantity,
int filled,
double averageFillPrice,
OrderState orderState,
DateTime time,
ErrorCode error,
string nativeError)
{
// Observe state transitions or errors here
}
OnExecutionUpdate
protected override void OnExecutionUpdate(
Execution execution,
string executionId,
double price,
int quantity,
MarketPosition marketPosition,
string orderId,
DateTime time)
{
// Post-fill logic here
}
OnPositionUpdate (when needed)
protected override void OnPositionUpdate(Position position, double averagePrice, int quantity, MarketPosition marketPosition)
{
// Position tracking here
}
Guardrail: If you ever see CS0507 (“cannot change access modifiers when overriding protected’…”) it means you used public override or private override. Switch to protected override.
4) Property pattern (inputs that always compile)
Use [NinjaScriptProperty] + [Range] + [Display].
Put properties after fields, inside the strategy class.
#region Inputs
[NinjaScriptProperty]
[Range(1, int.MaxValue)]
[Display(Name = "RiskTicks", GroupName = "Parameters", Order = 1)]
public int RiskTicks { get; set; }
[NinjaScriptProperty]
[Display(Name = "UseRthOnly", GroupName = "Parameters", Order = 2)]
public bool UseRthOnly { get; set; }
#endregion
5) Indicator & resource creation rules
Only instantiate indicators/Series in State.DataLoaded.
Never new built-in indicators; call factory methods (e.g., SMA(20)).
Dont assume Order Flow+. If you need VWAP, either:
Use a custom rolling VWAP you implement locally, or
Wrap the reference behind a feature flag and compile-time fallbacks.
6) Managed orders compile-safe usage
Set targets/stops before entry on the same bar:
SetStopLoss(CalculationMode.Ticks, RiskTicks);
SetProfitTarget(CalculationMode.Ticks, RiskTicks * 2);
EnterLong(); // or EnterShort()
Dont mix EnterLong/Short with Unmanaged SubmitOrderUnmanaged() in the same strategy.
If using signals, use consistent signal names across entries/exits.
7) Unmanaged orders compile-safe usage (if chosen)
Opt-in once:
else if (State == State.Configure)
{
Calculate = Calculate.OnBarClose;
// Enable unmanaged if needed
// this.IsUnmanaged = true; // uncomment only if youre actually using unmanaged
}
Always check Order objects for null before accessing fields.
Maintain your own OCO/quantity state.
Do not call Managed Set* methods in Unmanaged mode.
8) Enums & constants that trip compilers
Use only valid enum members. Examples that compile:
OrderAction.Buy, OrderAction.SellShort
OrderType.Market, OrderType.Limit, OrderType.StopMarket, OrderType.StopLimit
TimeInForce.Day, TimeInForce.Gtc
MarketPosition.Flat/Long/Short
OrderState.Accepted/Working/PartFilled/Filled/Cancelled/Rejected/Unknown (names vary by NT build; dont invent PendingSubmit”, RejectedByBroker”, RejectedByExchange”).
Use ToTime(Time[0]) or anchors like Times[0][0] for session-aware checks; avoid DateTime.Now for bar logic.
9) Safe OnBarUpdate header (paste into every strategy)
protected override void OnBarUpdate()
{
if (BarsInProgress != 0) return;
if (CurrentBar < BarsRequiredToTrade) return;
if (UseRthOnly && !TradingHours.Contains(Time[0])) return; // requires proper session template
// Logic...
}
10) Logging & messages
Use Print() for debug; never MessageBox.Show or Windows-only UI calls (breaks compile or runtime).
Wrap optional debug in a bool DebugMode input and guard if (DebugMode) Print(...).
11) Namespaces & class hygiene
Exactly one public strategy per file.
No top-level statements; everything inside the namespace/class.
No async/await; stick to synchronous NT8 patterns.
12) No-surprises build checks (optional but recommended)
If you run pre-lint or Roslyn analyzers externally, do not add NuGet packages inside NinjaTraders compile domain.
Keep analyzers in your editor/CI only, not as runtime dependencies in NT8.
13) Minimal, compile-safe template (drop-in)
Copy this as your starting point; it compiles on a vanilla NT8 (no Order Flow+).
// ============================================================================
// Strategy Name : CompileSafeTemplate
// Description : Minimal, first-time-compile-safe NinjaTrader 8 strategy
// ============================================================================
#region Using declarations
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using NinjaTrader.Cbi;
using NinjaTrader.Data;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.Tools;
using NinjaTrader.NinjaScript;
using NinjaTrader.NinjaScript.Strategies;
using NinjaTrader.NinjaScript.Indicators;
#endregion
namespace NinjaTrader.NinjaScript.Strategies
{
public class CompileSafeTemplate : Strategy
{
private SMA sma;
#region Inputs
[NinjaScriptProperty]
[Range(1, int.MaxValue)]
[Display(Name = "RiskTicks", GroupName = "Parameters", Order = 1)]
public int RiskTicks { get; set; }
[NinjaScriptProperty]
[Display(Name = "UseRthOnly", GroupName = "Parameters", Order = 2)]
public bool UseRthOnly { get; set; }
[NinjaScriptProperty]
[Display(Name = "DebugMode", GroupName = "Parameters", Order = 3)]
public bool DebugMode { get; set; }
#endregion
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Name = "CompileSafeTemplate";
Description = "Minimal, compile-safe NT8 strategy template";
Calculate = Calculate.OnBarClose;
IsOverlay = false;
BarsRequiredToTrade = 20;
IsInstantiatedOnEachOptimizationIteration = true;
// Defaults
RiskTicks = 16;
UseRthOnly = true;
DebugMode = false;
}
else if (State == State.Configure)
{
// AddDataSeries(...) if needed
}
else if (State == State.DataLoaded)
{
sma = SMA(20);
}
}
protected override void OnBarUpdate()
{
if (BarsInProgress != 0) return;
if (CurrentBar < BarsRequiredToTrade) return;
if (UseRthOnly && !TradingHours.Contains(Time[0])) return;
// Example trivial logic just to show structure (does nothing fancy)
if (CrossAbove(Close, sma, 1) && Position.MarketPosition == MarketPosition.Flat)
{
SetStopLoss(CalculationMode.Ticks, RiskTicks);
SetProfitTarget(CalculationMode.Ticks, RiskTicks * 2);
EnterLong();
if (DebugMode) Print($"EnterLong at {Time[0]}");
}
else if (CrossBelow(Close, sma, 1) && Position.MarketPosition == MarketPosition.Flat)
{
SetStopLoss(CalculationMode.Ticks, RiskTicks);
SetProfitTarget(CalculationMode.Ticks, RiskTicks * 2);
EnterShort();
if (DebugMode) Print($"EnterShort at {Time[0]}");
}
}
protected override void OnOrderUpdate(
Order order, double limitPrice, double stopPrice, int quantity, int filled,
double averageFillPrice, OrderState orderState, DateTime time,
ErrorCode error, string nativeError)
{
if (DebugMode) Print($"OnOrderUpdate: {order?.Name} {orderState} {nativeError}");
}
protected override void OnExecutionUpdate(
Execution execution, string executionId, double price, int quantity,
MarketPosition marketPosition, string orderId, DateTime time)
{
if (DebugMode) Print($"OnExecutionUpdate: {execution?.Name} {quantity}@{price}");
}
}
}
14) Quick dev checklist (paste in your repo README)
File name matches class name; class derives from Strategy.
All overrides are protected override and signatures match exactly.
No OnStartUp(); lifecycle is handled in OnStateChange.
All indicators/Series created in State.DataLoaded.
No Order Flow+ indicators unless explicitly requested.
OnBarUpdate starts with BarsInProgress and CurrentBar guards.
Inputs use [NinjaScriptProperty], [Range], [Display].
No invented enum values; only valid OrderState, MarketPosition, etc.
Managed vs Unmanaged is consistent; do not mix APIs.
No MessageBox/UI calls; optional logs gated behind DebugMode.

25
.kilocode/rules/archon.md Normal file
View File

@@ -0,0 +1,25 @@
# Archon Integration & Workflow
**CRITICAL: This project uses Archon for knowledge management, task tracking, and project organization.**
## Core Archon Workflow Principles
### The Golden Rule: Task-Driven Development with Archon
**MANDATORY: Always complete the full Archon task cycle before any coding:**
1. **Check Current Task** → Review task details and requirements
2. **Research for Task** → Search relevant documentation and examples
3. **Implement the Task** → Write code based on research
4. **Update Task Status** → Move task from "todo" → "doing" → "review"
5. **Get Next Task** → Check for next priority task
6. **Repeat Cycle**
**Task Management Rules:**
- Update all actions to Archon
- Move tasks from "todo" → "doing" → "review" (not directly to complete)
- Maintain task descriptions and add implementation notes
- DO NOT MAKE ASSUMPTIONS - check project documentation for questions

View File

@@ -0,0 +1,243 @@
# NT8 Institutional SDK - Development Workflow
## Overview
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.
## Archon Workflow Principles
The development process follows these core principles adapted from the Archon workflow:
### 1. Check Current Task
Before beginning any work, clearly define what needs to be accomplished:
- Review requirements and specifications
- Understand success criteria
- Identify dependencies and blockers
### 2. Research for Task
Conduct thorough research before implementation:
- Review existing code and documentation
- Understand best practices and patterns
- Identify potential challenges and solutions
### 3. Implement the Task
Execute the implementation with focus and precision:
- Follow established patterns and conventions
- Write clean, maintainable code
- Include comprehensive error handling
- Add structured logging for observability
### 4. Update Task Status
Track progress and document completion:
- Mark tasks as completed in the todo list
- Document any issues or deviations
- Note lessons learned for future reference
### 5. Get Next Task
Move systematically through the implementation:
- Prioritize tasks based on dependencies
- Focus on one task at a time
- Ensure quality before moving forward
## Development Process
### Phase 1: Planning and Design
1. Review specifications and requirements
2. Create architecture diagrams and documentation
3. Identify core components and their interactions
4. Plan implementation approach and timeline
### Phase 2: Environment Setup
1. Create project structure and configuration files
2. Set up build and test infrastructure
3. Configure CI/CD pipeline
4. Verify development environment
### Phase 3: Core Implementation
1. Implement core interfaces and models
2. Develop risk management components
3. Create position sizing algorithms
4. Build supporting utilities and helpers
### Phase 4: Testing and Validation
1. Create comprehensive unit tests
2. Implement integration tests
3. Run validation scripts
4. Verify all success criteria
### Phase 5: Documentation and Delivery
1. Create developer documentation
2. Write user guides and examples
3. Prepare release notes
4. Conduct final validation
## Code Quality Standards
### 1. Code Structure
- Follow established naming conventions
- Use consistent formatting and style
- Organize code into logical modules
- Maintain clear separation of concerns
### 2. Error Handling
- Validate all inputs and parameters
- Provide meaningful error messages
- Handle exceptions gracefully
- Log errors for debugging
### 3. Testing
- Write unit tests for all public methods
- Include edge case testing
- Validate error conditions
- Maintain >90% code coverage
### 4. Documentation
- Include XML documentation for all public APIs
- Add inline comments for complex logic
- Document configuration options
- Provide usage examples
## Git Workflow
### Branching Strategy
- Use feature branches for all development
- Create branches from main for new features
- Keep feature branches short-lived
- Merge to main after review and testing
### Commit Guidelines
- Write clear, descriptive commit messages
- Make small, focused commits
- Reference issues or tasks in commit messages
- Squash related commits before merging
### Pull Request Process
- Create PRs for all feature work
- Include description of changes and testing
- Request review from team members
- Address feedback before merging
## Development Environment
### Required Tools
- .NET 6.0 SDK
- Visual Studio Code or Visual Studio
- Git for version control
- Docker Desktop (recommended)
### Recommended Extensions
- C# for Visual Studio Code
- EditorConfig for VS Code
- GitLens for enhanced Git experience
- Docker extension for container management
## Build and Test Process
### Local Development
1. Restore NuGet packages: `dotnet restore`
2. Build solution: `dotnet build`
3. Run tests: `dotnet test`
4. Run specific test categories if needed
### Continuous Integration
- Automated builds on every commit
- Run full test suite on each build
- Generate code coverage reports
- Deploy to test environments
## Debugging and Troubleshooting
### Common Issues
1. **Build Failures**
- Check for missing NuGet packages
- Verify .NET SDK version
- Ensure all projects reference correct frameworks
2. **Test Failures**
- Review test output for specific errors
- Check test data and setup
- Verify mock configurations
3. **Runtime Errors**
- Check logs for error details
- Validate configuration settings
- Review dependency injection setup
### Debugging Tools
- Visual Studio debugger
- Console logging
- Structured logging with correlation IDs
- Performance profiling tools
## Release Process
### Versioning
- Follow semantic versioning (MAJOR.MINOR.PATCH)
- Increment version in Directory.Build.props
- Update release notes with changes
- Tag releases in Git
### Deployment
- Create NuGet packages for SDK components
- Publish to internal package repository
- Update documentation with release notes
- Notify stakeholders of new releases
## Best Practices
### 1. Code Reviews
- Review all code before merging
- Focus on correctness, maintainability, and performance
- Provide constructive feedback
- Ensure adherence to coding standards
### 2. Performance Considerations
- Minimize allocations in hot paths
- Use efficient data structures
- Cache expensive operations
- Profile performance regularly
### 3. Security
- Validate all inputs
- Sanitize user data
- Protect sensitive configuration
- Follow secure coding practices
### 4. Maintainability
- Write self-documenting code
- Use meaningful variable and method names
- Keep methods small and focused
- Refactor regularly to improve design
## Task Management Without Archon
Since we're not using the Archon MCP server, we'll manage tasks using:
1. **Todo Lists**: Track progress using markdown checklists
2. **Documentation**: Maintain detailed records of implementation decisions
3. **Git**: Use commits and branches to track work progress
4. **Issue Tracking**: Use GitHub Issues or similar for task management
### Task Status Tracking
- **Todo**: Task identified but not started
- **In Progress**: Actively working on task
- **Review**: Task completed, awaiting validation
- **Done**: Task validated and completed
## Communication and Collaboration
### Team Coordination
- Hold regular standups to discuss progress
- Use collaborative tools for communication
- Document architectural decisions
- Share knowledge and best practices
### Knowledge Sharing
- Conduct code walkthroughs for complex features
- Create technical documentation
- Share lessons learned from issues
- Mentor new team members
## Conclusion
This development workflow ensures consistent, high-quality implementation of the NT8 Institutional SDK. By following these principles and practices, we can deliver a robust, maintainable, and scalable trading platform that meets institutional requirements for risk management and performance.
The workflow emphasizes systematic progress, quality assurance, and continuous improvement. Each task should be approached with thorough research, careful implementation, and comprehensive validation to ensure the highest quality outcome.

View File

@@ -0,0 +1,139 @@
## Purpose
A single source of truth to ensure **first-time compile** success for all NinjaTrader 8 strategies, indicators, and add-ons generated by an LLM.
---
## Golden Rules (Pin These)
1. **NT8 only.** No NT7 APIs. If NT7 concepts appear, **silently upgrade** to NT8 (proper `OnStateChange()` and `protected override` signatures).
2. **One file, one public class.** File name = class name. Put at the top: `// File: <ClassName>.cs`.
3. **Namespaces:**
- Strategies → `NinjaTrader.NinjaScript.Strategies`
- Indicators → `NinjaTrader.NinjaScript.Indicators`
4. **Correct override access:** All NT8 overrides are `protected override` (never `public` or `private`).
5. **Lifecycle:** Use `OnStateChange()` with `State.SetDefaults`, `State.Configure`, `State.DataLoaded` to set defaults, add data series, and instantiate indicators/Series.
6. **Indicator creation:** Instantiate indicators **once** in `State.DataLoaded`. Add to chart (if desired) in `State.Configure` via `AddChartIndicator()`.
7. **Managed orders by default:** Use `SetStopLoss`/`SetProfitTarget` **before** entries on the same bar. Do **not** mix Managed & Unmanaged in the same file.
8. **MTF discipline:** Add secondary series **only** in `State.Configure`. In `OnBarUpdate()`, gate logic with `BarsInProgress` and `CurrentBars[i]`.
9. **No Order Flow+ by default:** Assume unavailable. If VWAP is needed, implement a **local fallback** or feature flag (OFF by default).
10. **Valid enums only:** Use real NT8 members for `OrderState`, `MarketPosition`, etc.
11. **Starter header in every strategy `OnBarUpdate()`:**
```csharp
if (BarsInProgress != 0) return;
if (CurrentBar < BarsRequiredToTrade) return;
Required Using Block (Strategy)
Always show details
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Windows.Media;
using NinjaTrader.Cbi;
using NinjaTrader.Data;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.Tools;
using NinjaTrader.NinjaScript;
using NinjaTrader.NinjaScript.Strategies;
using NinjaTrader.NinjaScript.Indicators;
using NinjaTrader.NinjaScript.DrawingTools;
Indicators omit some GUI usings unless needed.
Inputs Pattern
Use DataAnnotations so properties render properly in the UI:
Always show details
[NinjaScriptProperty, Range(1, int.MaxValue)]
[Display(Name = "Quantity", GroupName = "Parameters", Order = 0)]
public int Quantity { get; set; } = 1;
[NinjaScriptProperty]
[Display(Name = "DebugMode", GroupName = "Parameters", Order = 999)]
public bool DebugMode { get; set; } = false;
Managed Order Rules
Call SetStopLoss and SetProfitTarget before you place an entry order.
Re-arm stops/targets when intended direction changes (e.g., flatlong or flatshort).
Use unique signal names per direction to bind OCO correctly (e.g., "L1", "S1").
Multi-Timeframe Rules
Add secondary series in State.Configure:
Always show details
AddDataSeries(BarsPeriodType.Minute, 5);
Guard in OnBarUpdate():
Always show details
if (BarsInProgress == 1) { /* 5-min logic */ }
if (CurrentBars[0] < BarsRequiredToTrade || CurrentBars[1] < 20) return;
Price Rounding & Tick Math
Always round to tick size to avoid rejections:
Always show details
private double Rt(double p) => Instrument.MasterInstrument.RoundToTickSize(p);
double target = Rt(Close[0] + 10 * TickSize);
Historical vs. Realtime
Always show details
private bool IsLive => State == State.Realtime;
Avoid timers/threads/file I/O by default.
Common Safety Defaults
Always show details
Calculate = Calculate.OnBarClose;
IsOverlay = false;
BarsRequiredToTrade = 20;
IsSuspendedWhileInactive = true;
IsInstantiatedOnEachOptimizationIteration = true;
Valid NT8 Signatures (paste as needed)
Always show details
protected override void OnOrderUpdate(
Order order, double limitPrice, double stopPrice, int quantity,
int filled, double averageFillPrice, OrderState orderState,
DateTime time, ErrorCode error, string nativeError) { }
protected override void OnExecutionUpdate(
Execution execution, string executionId, double price, int quantity,
MarketPosition marketPosition, string orderId, DateTime time) { }
protected override void OnMarketData(MarketDataEventArgs e) { }
protected override void OnMarketDepth(MarketDepthEventArgs e) { }
protected override void OnPositionUpdate(Position position, double averagePrice, int quantity, MarketPosition marketPosition) { }
Compile Checklist (Preflight)
NT8 only; no OnStartUp() or NT7 methods.
Exactly one public class; file name matches class name.
Required usings present.
Indicators/Series created in State.DataLoaded.
Starter header present in OnBarUpdate().
Managed orders only (unless explicitly asked otherwise).
Secondary series added only in State.Configure.
Enums & members verified against NT8.
Price rounding helper present for any custom prices.
DebugMode gating for Print() calls.
""").format(date=datetime.date.today().isoformat())
files["NT8_Templates.md"] = textwrap.dedent("""