NinjaScript Indicator builder

Build NinjaScript Indicators With AddPlot and Values

Define the calculation, plot, parameters, and bar timing in plain English. Pineify can turn that specification into one editable NT8 Indicator file with static diagnostics.

RsiLineExample.cs
Complete Indicator
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Windows.Media;
using System.Xml.Serialization;
using NinjaTrader.NinjaScript;

namespace NinjaTrader.NinjaScript.Indicators
{
    public class RsiLineExample : Indicator
    {
        private RSI rsi;

        protected override void OnStateChange()
        {
            if (State == State.SetDefaults)
            {
                Name = "RsiLineExample";
                Calculate = Calculate.OnBarClose;
                IsOverlay = false;
                Period = 14;
                AddPlot(Brushes.DodgerBlue, "RsiValue");
                AddLine(Brushes.Gray, 70, "Upper");
                AddLine(Brushes.Gray, 30, "Lower");
            }
            else if (State == State.DataLoaded)
            {
                rsi = RSI(Period, 3);
            }
        }

        protected override void OnBarUpdate()
        {
            if (CurrentBar < Period - 1)
                return;

            Value[0] = rsi[0];
        }

        [NinjaScriptProperty]
        [Range(1, 200)]
        [Display(Name = "Period", GroupName = "Parameters", Order = 0)]
        public int Period { get; set; }

        [Browsable(false)]
        [XmlIgnore]
        public Series<double> RsiValue => Values[0];
    }
}

This RSI example is a structural starting point. Compile it in NinjaScript Editor and check the chart output before using it in another script.

Direct answer

A NinjaScript Indicator is a C# class that inherits Indicator, declares display outputs with AddPlot, and assigns bar values through Value or Values in OnBarUpdate. Put stable UI defaults and plots in State.SetDefaults, initialize data-dependent indicator objects in State.DataLoaded, and guard each historical series access before calculation.

What to know first

  • AddPlot creates both a visual Plot and an associated Series<double> in Values.
  • Value is the first plot series; Values[n] follows AddPlot declaration order.
  • AddPlot belongs in State.SetDefaults or State.Configure, not OnBarUpdate.
  • BarsRequiredToPlot delays display but does not replace CurrentBar guards for data access.

The minimum Indicator structure

A custom NinjaTrader 8 Indicator needs the Indicators namespace, a public class derived from Indicator, and the OnStateChange and OnBarUpdate overrides. State.SetDefaults holds the name, Calculate mode, panel choice, parameter defaults, and ordinary plot declarations.

OnBarUpdate receives bar-processing events. It should return before a required lookback is ready, calculate the current value, and assign that result to the intended plot series. Keep the first version small enough that every state transition and output has an obvious purpose.

How AddPlot, Value, and Values connect

AddPlot(Brushes.DodgerBlue, "RsiValue") creates one display plot and one matching series. Value[0] writes the current bar of the first plot. The same assignment can be written as Values[0][0]. If the Indicator has two plots, Values[1][0] writes the second one.

Declaration order is a contract. Renaming a plot does not change its numeric index, but inserting a plot earlier in the list does. Review every Values index after changing plot order. Expose a named Series property when other scripts need to read a particular output.

  • Use a predefined System.Windows.Media Brushes value for an ordinary plot color.
  • Use AddLine for a fixed reference such as 70 or 30.
  • Use a plot when the displayed value changes on each bar.

Initialize reusable calculations after data loads

The example creates the RSI object in State.DataLoaded. At that point configured data is available, so the object can be retained and reused by OnBarUpdate. Recreating the same indicator on every bar makes the code harder to inspect and can add unnecessary work.

State.SetDefaults should remain light because NinjaTrader can create temporary instances while opening lists or compiling. Do not read Bars or Instrument data, open external resources, or create data-dependent objects there.

Choose the right lookback guard

If code reads Close[5], it needs at least five prior bars. If a 50-period calculation is used, guard for the longer dependency. In a single-series script, CurrentBar is enough. In a multi-series script, check CurrentBars for every series that the calculation reads.

BarsRequiredToPlot controls when plots appear. It does not make an unsafe Close[n] or secondary series access safe. The guard belongs in the code path before the read.

Generate, inspect, compile, and chart test

A useful generation prompt names the formula, source series, period limits, Calculate mode, panel, plot names, colors, and any fixed lines. Ask for one complete Indicator source file. Review the class name, property ranges, AddPlot order, lookback guards, and output assignments before checking it.

Pineify can report static C# and supported API diagnostics for that file. Then compile it in NinjaScript Editor, apply it to a chart, compare several known bars, and inspect behavior across reloads and realtime updates. Each stage can reveal a different problem.

Practical checks I use

Map each plot to one series

I write the AddPlot order beside each Values index during review. That catches mismatches when a second output is added later.

Guard the actual dependency

I base the CurrentBar check on the longest series access or calculation, not on the number that happens to look tidy in the UI.

Test visible bars by hand

After compilation, I inspect a few chart bars where the expected value can be calculated independently. A smooth plot is not proof that the formula is right.

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

Turn an Indicator Formula Into NinjaScript

State the inputs, calculation, plots, and bar timing. Inspect the generated file and static diagnostics before compiling it in NinjaTrader 8.

Build a NinjaScript Indicator