Referencing Indicators with NinjaScript
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.
An important skill to develop while learning to code in NinjaTrader is referencing another (custom or system) indicator from the indicator, or strategy you are designing. In this Part we will go over the basics so you can see how easy it really is. Before we do that, we need to learn a little more about the code NinjaTrader auto-generates in each indicator.
NinjaScript Generated Code Basics
Every time we add a parameter to our indicator (and then save), like iOffsetTicks, NinjaTrader creates code at the bottom of the indicator that we will refer to as Generated Code. The Generated Code allows and gives us instructions on referencing that indicator elsewhere. When we then save and compile our indicator(s), NinjaTrader goes through a set of internal functions / methods to make sure the indicator(s) do not have errors, which includes the Generated Code. Here’s an example of the Generated Code we are interested in from our first indicator:
More specifically, we are interested in this portion of the code:
The above code tells us we can reference our indicator (from another indicator) in two ways. The first is using MyFirstIndicator(int offsetTicks) and the second using MyFirstIndicator(ISeries input, int offsetTicks). So, the two pieces of code that tell us the referenced information is as follows (shortened from above):
What does the above mean? If we want to reference MyFirstIndicator, we must pass one, or two inputs into our logic depending on what type of indicator we wish to develop. The most simple logic (the first line), only requires us to pass a integer (int) value, or variable into the reference for the variable offsetTicks, which we know refers to iOffsetTicks. In comparison, the second logic also requires us to pass a integer (int) value, or variable for offsetTicks, but it will also allow us to pass in an ISeries<T> variable for input (think of input as Input that we reviewed in Part 6). If you have an indicator, like an SMA that uses Input to calculate it’s value, we can pass an alternative ISeries into the indicator and the SMA will know to use that new ISeries instead of Input. It’s important to note that the ISeries we pass into SMA will ONLY replace Input and no other PriceSeries. If you do not pass in an Input, the Input in your Indicator Settings will be used by default. An example would be if we call an SMA from our indicator, but we want to see what the SMA of a CCI looks like. We could pass in CCI as the ISeries and the CCI would replace the Input in the SMA calculation. A 5 Period SMA of a 21 Period CCI would look like SMA(CCI(21), 5). In our indicator, if we passed in CCI as the Input, even though we do not use Input in any of our calculations, it would look like MyFirstIndicator(CCI(5), 1). Additionally, this ISeries input can be used in order to make multi time frame indicators, which we will cover in another tutorial.
Default Settings Examples
The best way to learn how to call indicators from other indicators is to start with an example. We are going to start with improving the Simple SMA Crossover. We will take two SMAs, but one of the SMAs (the shorter period SMA) will use an EMA as its Input. The first thing we have to do is create a new indicator, so create a new indicator like we did previously in Part 1. Set the name to ImprovedSmaCross and then click Generate. Now, from the indicator we developed in Part 6, copy our settings from State.SetDefaults and set the Indicator Name / Description, so your new indicator looks like this:
Since we know what indicator we want to develop, we can first create three inputs: 1) EMA Period used in our short term EMA, 2) short term SMA Period, and 3) long term SMA Period, which would look as follows:
Great, now calling an indicator is a two step process: 1) we create a variable where instead of using int or double as the Data Type, we use the indicator name and 2) create the indicator in State.DataLoaded. Step 1, creating the indicator variable, would look like this:
After we create the variable we need to set the variable to the EMA, or SMA, inside of State.DataLoaded. The reason we perform this inside of State.DataLoaded is because both SMA and EMA need Data / Bars to function correctly, so State.DataLoaded is the first time we have Data / Bars available to reference. The following would go in State.DataLoaded:
We are almost done, but we need to make sure OnBarUpdate will not process unless we have enough data loaded (the max of the three variable inputs). We could do this two ways, the first like I showed you in Part 6, or we can set the variable BarsRequiredToPlot:
It’s As Simple As That
We are going to continue using the example from above to plot the two SMAs on a chart, so checkout Part 9 – AddPlot and Plot Variables.