Install
openclaw skills install @gmdeep/ninjatraderopenclawskillNinjaTrader 8 NinjaScript development reference: using directives, lifecycle, indicators, order mgmt, compile errors, deployment
openclaw skills install @gmdeep/ninjatraderopenclawskillA practical reference skill for coding, validating, and deploying NinjaTrader 8 strategies and indicators. Use this before every NT8 coding session.
Run this checklist before writing or deploying any strategy .cs file:
using directives present? (see §2 template)Draw.* methods backed by using NinjaTrader.NinjaScript.DrawingTools;?BarsInProgress, CurrentBars[], Closes[], Times[]) all valid?AddDataSeries() called in State.Configure with hardcoded arguments (not runtime variables)?AddChartIndicator() called ONLY from State.DataLoaded?State.SetDefaults kept lean — only defaults and AddPlot/AddLine?State.Configure or State.DataLoaded?SetStopLoss/SetProfitTarget using CalculationMode.Ticks (not .Price) unless intentional?EntriesPerDirection + EntryHandling configured explicitly in State.SetDefaults?using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.SuperDom;
using NinjaTrader.Gui.Tools;
using NinjaTrader.Data;
using NinjaTrader.NinjaScript;
using NinjaTrader.Core;
using NinjaTrader.NinjaScript.Indicators;
using NinjaTrader.NinjaScript.DrawingTools;
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Windows.Media;
using System.Xml.Serialization;
using NinjaTrader.Cbi; // Order, Execution, Position types
using NinjaTrader.Gui.Chart; // ChartControl, ChartPanel
using NinjaTrader.Data; // Bars, BarsPeriod, TradingHours
using NinjaTrader.NinjaScript;
using NinjaTrader.NinjaScript.Indicators; // SMA, EMA, ATR, RSI, etc.
using NinjaTrader.NinjaScript.DrawingTools; // Draw.HorizontalLine, Draw.Dot, etc.
| What you're using | Required using | Error if missing |
|---|---|---|
Draw.HorizontalLine(), Draw.Dot(), Draw.Text() | NinjaTrader.NinjaScript.DrawingTools | "The name 'Draw' does not exist" |
SMA(20), EMA(14), RSI(14,3) | NinjaTrader.NinjaScript.Indicators | Indicator not recognized |
Order, Execution, Position | NinjaTrader.Cbi | Type not found |
BarsPeriod, TradingHours | NinjaTrader.Data | Type not found |
Brushes.Blue | System.Windows.Media | "The name 'Brushes' does not exist" |
State.SetDefaults → UI defaults (keep lean!)
State.Configure → AddDataSeries, custom resources
State.DataLoaded → Instantiate indicators, Series<T>, Bars/Instrument access
State.Historical → Processing historical bars
State.Transition → Historical → Realtime handoff
State.Realtime → Live data
State.Terminated → Cleanup/dispose
| Resource | Earliest safe state | Notes |
|---|---|---|
AddDataSeries() | State.Configure | Hardcoded args only |
SMA(), EMA(), indicators | State.DataLoaded | Depend on bars being loaded |
Series<T> construction | State.DataLoaded | Needs this |
AddChartIndicator() | State.DataLoaded ONLY | Won't work elsewhere |
Bars, Instrument, TickSize | State.DataLoaded | Null before this |
Every time the Indicators/Strategies dialog opens, ALL scripts go through SetDefaults → Terminated. Keep State.SetDefaults lean — it runs constantly.
// In State.Configure — hardcoded arguments only
AddDataSeries(BarsPeriodType.Minute, 5); // 5-min secondary
// In OnBarUpdate
if (CurrentBars[0] < 20 || CurrentBars[1] < 20) return;
if (BarsInProgress == 0)
{
double secondaryClose = Closes[1][0]; // 5-min close
// Times[1][0], Highs[1][0], Lows[1][0], Opens[1][0]
}
If Strategy A hosts Indicator B and B calls AddDataSeries(), Strategy A must ALSO call the SAME AddDataSeries(). Otherwise: "A hosted indicator tried to load additional data..." error.
// Declare at class level
private SMA mySMA;
// Instantiate in State.DataLoaded
mySMA = SMA(20);
// Use in OnBarUpdate
double smaVal = mySMA[0];
double priorSma = mySMA[1];
SMA(int period)
EMA(int period)
ATR(int period)
RSI(int period, int smooth) // RSI(14, 3) standard
Bollinger(int period, double stdDev) // Bollinger(20, 2)
MIN(int period) / MAX(int period)
PriorDayOHLC()
Stochastics(int d, int k, int smooth) // Stochastics(14, 3, 3)
MACD(int fast, int slow, int smooth) // MACD(12, 26, 9)
AddChartIndicator(SMA(20));
// ⚠️ Must also reference in OnBarUpdate if you want historical processing
| Type | Purpose | Namespace |
|---|---|---|
| OrderFlowVolumeProfile | Indicator — read values programmatically | NinjaTrader.NinjaScript.Indicators |
| VolumeProfileSession | Drawing tool — visual only | NinjaTrader.NinjaScript.DrawingTools |
private OrderFlowVolumeProfile volProfile;
// In State.DataLoaded:
volProfile = OrderFlowVolumeProfile(
NinjaTrader.NinjaScript.Indicators.ProfileDisplayMode.Price,
NinjaTrader.NinjaScript.Indicators.ProfileResolution.Monthly,
NinjaTrader.NinjaScript.Indicators.ProfilePeriod.One,
NinjaTrader.NinjaScript.Indicators.ProfileTpoCount.Eight,
NinjaTrader.NinjaScript.Indicators.ProfileValueArea.Seventy,
NinjaTrader.NinjaScript.Indicators.ProfileSessionType.UseInstrumentSetting,
0, 0
);
// In OnBarUpdate:
double poc = volProfile.POC[0];
double vah = volProfile.VAH[0];
double val = volProfile.VAL[0];
// Stop loss / profit target (use Ticks mode by default)
SetStopLoss(CalculationMode.Ticks, 20);
SetProfitTarget(CalculationMode.Ticks, 40);
// Entry handling
EntriesPerDirection = 2;
EntryHandling = EntryHandling.AllEntries;
// Entry methods
EnterLong() / EnterShort()
EnterLongLimit(price) / EnterShortLimit(price)
[NinjaScriptProperty]
[Range(1, int.MaxValue)]
[Display(Name = "Fast Period", Order = 1, GroupName = "Strategy Parameters")]
public int FastPeriod { get; set; }
[Browsable(false)]
public bool InternalFlag { get; set; }
namespace NinjaTrader.NinjaScript.Strategies
{
public class MyStrategy : Strategy
{
#region Parameters
// [NinjaScriptProperty] user inputs
#endregion
#region State Management
// OnStateChange()
#endregion
#region Core Logic
// OnBarUpdate()
#endregion
#region Order Events
// OnExecutionUpdate, OnOrderUpdate, OnPositionUpdate
#endregion
#region Helpers
#endregion
}
}
| Error | Cause | Fix |
|---|---|---|
CS0234: 'Indicators' does not exist | Missing using | Add using NinjaTrader.NinjaScript.Indicators |
CS0234: 'DrawingTools' does not exist | Missing using | Add using NinjaTrader.NinjaScript.DrawingTools |
CS0103: 'Draw' does not exist | Missing DrawingTools using | Add using |
CS0117: 'Draw.HorizontalLine' not found | Old NT7 syntax | Use Draw.HorizontalLine(this, tag, price, brush) |
"Indicator not recognized" | Not instantiated or missing using | Instantiate in DataLoaded + add Indicators using |
"Hosted indicator tried to load data" | Missing AddDataSeries in host | Add matching AddDataSeries() |
"Object reference not set" | Accessing before DataLoaded | Move to correct lifecycle state |
"Unable to load bars series" | Dynamic AddDataSeries args | Hardcode all arguments |
Documents\NinjaTrader 8\bin\Custom\Strategies\MyStrategy.cs
.bak.cs or timestamped)MyStrategy.cs ← Current active
MyStrategy.bak.cs ← Previous version
MyStrategy_20260618.cs ← Timestamped backup
State.DataLoadedusing NinjaTrader.NinjaScript.Indicators present.Upper[n], .Lower[n], .Middle[n]using NinjaTrader.NinjaScript.DrawingTools presentDraw.HorizontalLine(this, tag, price, brush) NOT DrawHorizontalLine(tag, price, Color.Red)AddDataSeries() in State.Configure with hardcoded argsCurrentBars[1] guarded before accessing Closes[1][0]SetStopLoss/SetProfitTarget via CalculationMode.TicksEntriesPerDirection and EntryHandling set explicitlyState.SetDefaultsBars/Instrument in State.SetDefaults or State.ConfigureAddChartIndicator() ONLY in State.DataLoadedNinjaTrader.NinjaScript.StrategiesStrategypublic fields (use properties)Print($"Close: {Close[0]} | SMA: {mySMA[0]}");
TraceOrders = true; // In State.SetDefaults
Draw.Dot(this, "entry" + CurrentBar, true, 0, Low[0] - TickSize, Brushes.Green);
| NT7 | NT8 |
|---|---|
DrawHorizontalLine(tag, price) | Draw.HorizontalLine(this, tag, price, Brushes.Red) |
Color.Red | Brushes.Red |
CurrentBar (singular) | CurrentBars (plural array) |
Close[0] | Close[0] + Closes[1][0] (multi-series) |
SetStopLoss(ticks) | SetStopLoss(CalculationMode.Ticks, ticks) |
CalculateOnBarClose = true | Calculate = Calculate.OnBarClose |
# SSH deploy
scp MyStrategy.cs gmdeep:"C:/Users/stewa/Documents/NinjaTrader 8/bin/Custom/Strategies/"
# Verify arrival
ssh gmdeep "dir \"C:\Users\stewa\Documents\NinjaTrader 8\bin\Custom\Strategies\MyStrategy.cs\""
&& and | before PowerShellWhen doing NT8 NinjaScript work:
.cs codeOrderFlowVolumeProfile indicator, not VolumeProfileSession drawing tool (§6)1. Paste using directives template
2. Write State.SetDefaults (lean, parameters only)
3. Write State.Configure (AddDataSeries if needed)
4. Write State.DataLoaded (instantiate indicators)
5. Write OnBarUpdate core logic
6. Run validation checklist
7. Deploy → Compile → Fix → Repeat