Files
nt8-sdk/rules/nt8compilespec.md
Billy Valentine 92f3732b3d
Some checks failed
Build and Test / build (push) Has been cancelled
Phase 0 completion: NT8 SDK core framework with risk management and position sizing
2025-09-09 17:06:37 -04:00

4.9 KiB

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():
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("""