AddPlot with NinjaScript
Brief Introduction
We’ve put together a series of posts to help you in your journey to learn how to program from scratch, or edit existing NinjaTrader indicators and strategies. All of our posts are geared toward the non-programmer, so even though we will present a lot of information, for all of you more technical people out there, we will not go into all the technicalities of C#, NinjaTrader, or NinjaScript. It’s also important to note that even though we show you how to do something in NinjaTrader, that is by no way the only way to do it. We will present what has worked best for us and what will be most easily understood by someone learning how to program. Finally, for the more advance users, we are going to leave things out and over simplify certain parts because we are focused on learning what we need to so we can get started on our NinjaScript journey.
A key to programming NinjaTrader indicators is utilizing Values and Plots, which we can think of as the line that represents a Moving Average, or Oscillator (on a chart). In this part we will go over how to declare / create a new Plot, reference the plot via Values and Name for both visual and programmatic access, and set default values for the most common inputs.
Plot / Plots Basics
To declare / add a Plot to a chart all we need to do, in State.SetDefaults, is use one of the two following AddPlot() syntax:
We jumped right into an example to explain what happens when we add a plot to a chart–we will explain the settings later. The word Plots has a special meaning in NinjaTrader because it holds an array / list of all the plots that have been added to the indicator. So, when you AddPlot(), the first Plot will be added to the “list” of Plots and we can reference that Plot through an index. What that means is even though the total number of plots on our chart is 1, if we want to reference the first Plot we added to the chart, we can do so using this syntax: Plots[index], or in our case Plots[0]. Each time we add a Plot to our chart it will be added to Plots and we can reference that Plot through its index. If we AddPlot() a second time, there will be 2 Plots and we can reference the second Plot with the syntax Plots[1]. If we AddPlot() a third time, there will be 3 Plots and we can reference the third Plot with the syntax Plots[2].
Let’s initialize two plots using the Example 1 syntax, like this:
After the plot is initialized, you can set default visual inputs for each plot separately through their index. Some of the main visuals you can set are:
- Width: Width can be set as part of Stroke, so you could set this when you initialize your Plot (see below), but this controls the thickness of your plot and can be set through Plots[index].Width.
- Brush: Brush can be set as part of Stroke, so you could set this when you initialize your Plot (see below), but this controls the color of your plot and can be set through Plots[index].Brush.
- DashStyleHelper: DashStyleHelper can be set as part of Stroke, so you could set this when you initialize your Plot (see below), but this controls one visual plotting aspect of your Plot and can be set through Plots[index].DashStyleHelper. The following are valid inputs for DashStyleHelper: DashStyleHelper.Dash, DashStyleHelper.DashDot, DashStyleHelper.DashDotDot, DashStyleHelper.Dot, and DashStyleHelper.Solid.
- PlotStyle: PlotStyle can be set through Plots[index].PlotStyle and is the the second aspect of the visual plotting and can take on the following values: PlotStyle.Bar, PlotStyle.Block, PlotStyle.Cross, PlotStyle.Dot, PlotStyle.Hash,, PlotStyle.HLine, PlotStyle.Line, PlotStyle.Square, PlotStyle.TriangleDown, PlotStyle.TriangleLeft, PlotStyle.TriangleRight, and PlotStyle.TriangleUp.
Alternatively, you can set all of the above settings when you initialize the Plot. If we review the AddPlot() syntax, AddPlot(Stroke stroke, PlotStyle plotStyle, string name), and take into consideration that three of the settings from above are part of Stroke, then we can substitute the syntax in the Stroke Class for “Stroke stroke,” as follows: AddPlot(Stroke(Brush brush, DashStyle dashStyleHelper, float width), PlotStyle plotStyle, string name), which can be used to simplify our above example:
Great! Now let’s see what that looks like inside of our Improved SMA Cross indicator:
Value / Values Basics
Now that we have initialized two Plots, it’s time to learn how to assign each plot a Value (what you will see on your chart). Each time you use AddPlot(), not only does a the Plot get added to Plots, but something similar happens to Values, which is a Series<double>. That simply means we can assign a value for each bar on the chart and then reference that value later. So, Values is referenced in a similar fashion, but this time it’s a two step process:
- We must first identify the index of the Value we want to reference Values[index]. If you AddPlot() once, then one Plot will be added and we can reference the Value through Values[0]. If we AddPlot() a second time, we can reference the second plots Value through Values[1], and so on (same concept as referencing Plots).
- After we determine which Value we want to reference, we then have to specify BarsAgo, so the full syntax for Values is: Values[index][barsago]. For example, if we want to set the Value for the first Plot we added AND for the most current bar (right most bar), we would write Values[0][0]. If we want to set the Value of the second Plot we added to the chart AND for the most current bar (right most bar), we would write Values[1][0]. BarsAgo works exactly as we previously described for PriceSeries, so if you wanted to set the value of the first Plot on the chart, but for 1 BarsAgo, we would write Values[0][1].
Now that we have the basics down, let’s see how we would use this in our indicator–in our indicator we have declared Plots and referenced indicators, but we have not set the value for the two Plots we initialized. Using the logic we just reviewed, we can set FastMA (Plots[0] / Values[0]) to indSmaShort and SlowMA (Plots[1] / Values[1]) to indSmaLong, as follows:
Awesome! Now if you save and compile, your chart should look like this:
Even though we successfully assigned two plots values, don’t you think it would be cumbersome to continually reference our Plots Values using the meaningless name of Values[index][barsago]? I agree, we need to reference the Plots / Values differently, which it’s a good thing we have an alternative. What we need to do is create a Public Series and assign it the same name that we used when we declared our Plot using AddPlot()–up until now we have used Private, but now it’s time to use Public for the first time. After we declare a Public Series, we need to link the Values[index] to that Public variable, which looks like this:
What we just did above will allow us to use the public Series variable instead of Values[index][barsago]–the syntax we will use is Series[BarsAgo], which looks like this:
Our indicator code should now look like:
It’s As Simple As That
We are going to continue using the example from above to color the two Plots and Background, so checkout Part 10 – Coloring Plots and Backgrounds.