NinjaScript for beginners

Learn NinjaScript From One Small NT8 Indicator

The fastest way to understand NinjaScript is to trace one complete Indicator from defaults to bar updates, then change one behavior at a time and verify the result in NinjaTrader 8.

ThreeBarAverage.cs
Beginner Example
using System.Windows.Media;
using NinjaTrader.NinjaScript;

namespace NinjaTrader.NinjaScript.Indicators
{
    public class ThreeBarAverage : Indicator
    {
        protected override void OnStateChange()
        {
            if (State == State.SetDefaults)
            {
                Name = "ThreeBarAverage";
                Calculate = Calculate.OnBarClose;
                IsOverlay = true;
                AddPlot(Brushes.Orange, "Average");
            }
        }

        protected override void OnBarUpdate()
        {
            if (CurrentBar < 2)
                return;

            Value[0] = (Close[0] + Close[1] + Close[2]) / 3.0;
        }
    }
}

The guard permits Close[2] only after two prior bars exist. Compile the file in NinjaScript Editor, add it to a chart, and check a few averages by hand.

Direct answer

Learn NinjaScript in this order: identify the script type, understand OnStateChange, follow OnBarUpdate, read series indexes, add a plot, guard the lookback, compile in NinjaScript Editor, and verify known bars on a chart. C# knowledge helps, but platform lifecycle and series rules are the parts most likely to cause NT8-specific mistakes.

What to know first

  • NinjaScript uses C#, but NinjaTrader controls when lifecycle and bar methods run.
  • Close[0] is the current bar and Close[1] is the prior bar, not an array in chronological order.
  • State.SetDefaults defines light defaults and visible plot declarations.
  • Every lesson should end with compilation and a small, observable platform test.

Lesson 1: read the script shape

The example lives in NinjaTrader.NinjaScript.Indicators and inherits Indicator. Those two choices identify the platform script type. A Strategy uses the Strategies namespace and inherits Strategy instead. Do not mix both shapes in one public entry class.

The using directives import types used by the file. System.Windows.Media supplies Brushes. NinjaTrader.NinjaScript supplies Indicator, State, Calculate, and the series members inherited by the class.

Lesson 2: follow the lifecycle

OnStateChange runs as NinjaTrader moves the script through states. State.SetDefaults is for the name, Calculate mode, panel choice, parameter defaults, and ordinary AddPlot or AddLine declarations. Keep it deterministic because NinjaTrader can create temporary script instances while compiling or opening UI lists.

State.Configure is for fixed structural configuration such as AddDataSeries. State.DataLoaded is where data-dependent Series objects and reusable indicators can be created. The small example needs neither branch, which makes it a useful first script.

Lesson 3: understand bar indexing

OnBarUpdate is the main bar-processing event. Close[0] means the current bar for the active series. Close[1] means one bar ago. The example reads through Close[2], so it returns while CurrentBar is less than 2.

This guard is part of the algorithm, not defensive decoration. When you change the formula to read a longer history, update the guard too. In a multi-series script, inspect BarsInProgress and use CurrentBars for every series dependency.

  • Trace each barsAgo index in the calculation.
  • Find the largest required lookback.
  • Place the guard before any dependent read.

Lesson 4: connect a value to a plot

AddPlot creates a plot and a platform-owned output series. Since this file has one plot, Value[0] writes its current value. With multiple plots, use Values[plotIndex][0] and keep the index aligned with AddPlot order.

IsOverlay = true places the plot on the price panel. Set it to false when the output belongs in a separate panel. The visual choice does not change the calculation.

Lesson 5: make one controlled change

After the example compiles, change only one element. Try a five-bar average, a separate panel, or Calculate.OnEachTick. Predict the result before you run it, update the lookback guard where needed, and compare the actual chart with that prediction.

When a change fails, use the editor diagnostic or a narrow Print statement to locate the problem. Avoid adding parameters, multiple series, drawing objects, and order logic in the same lesson. Smaller changes produce clearer evidence.

Use AI as an inspectable coding loop

A useful prompt states the target as one NT8 Indicator or Strategy and describes every input, output, state, and timing rule. Ask for complete source so namespace, imports, class, properties, lifecycle methods, and guards can be inspected together.

Pineify can generate that artifact and check it against a fixed static reference profile. Read the code, repair source-located diagnostics, compile it in NinjaScript Editor, and test it in NinjaTrader. Do not skip the native platform steps because an external checker returned clean.

Practical checks I use

Predict before running

I write down what one code change should do on a known bar. The comparison between prediction and chart output is the lesson.

Change one contract at a time

I do not add a parameter, a second series, and order logic in the same edit. A narrow change makes the cause of a failure visible.

Read generated code line by line

I treat AI output as source to inspect. I identify the script type, states, guards, series reads, outputs, and side effects before compiling it.

Primary sources

This page explains NinjaScript development and Pineify code generation. It is not investment advice. Generated code can be wrong, a static check does not replace NinjaScript Editor compilation, and no example promises future results.

Frequently asked questions

Learn From a Script You Can Inspect

Describe a small Indicator, ask the coding agent to explain each contract, and carry the complete file into NinjaScript Editor.

Create a Beginner NinjaScript