Referencing Indicators 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.

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:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

// We are interested in the code with the namespace NinjaTrader.NinjaScript.Indicators

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):

1

2

publicMyFirstIndicator MyFirstIndicator(intoffsetTicks)

publicMyFirstIndicator MyFirstIndicator(ISeries input,intoffsetTicks)

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:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

privateintiPeriodEma=3;

[NinjaScriptProperty]

[Display(Name="01. EMA Period",Description="EMA Period used in our short term SMA",GroupName="01. Indicator Parameters",Order=1)]

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:

1

2

3

privateEMA indEma;

privateSMA indSmaShort;

privateSMA indSmaLong;

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:

1

2

3

4

5

6

7

8

// Set indEma to EMA with a period of iPeriodEma. Set this FIRST if we are going to use it in indSmaShort

indEma=EMA(iPeriodEma);

// Set indSmaShort to SMA with a period of iPeriodSmaShort, BUT use indEma as the Input

indSmaShort=SMA(indEma,iPeriodSmaShort);

// Set indSmaLong to EMA with a period of iPeriodSmaLong

indSmaLong=SMA(iPeriodSmaLong);

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:

NinjaTrader Disclosure: NinjaTrader® is a registered trademark of NinjaTrader Group, LLC. No NinjaTrader company has any affiliation with the owner, developer, or provider of the products or services described herein, or any interest, ownership or otherwise, in any such product or service, or endorses, recommends or approves any such product or service.

RISK DISCLOSURE: Futures and forex trading contains substantial risk and is not for every investor. An investor could potentially lose all or more than the initial investment. Risk capital is money that can be lost without jeopardizing ones financial security or life style. Only risk capital should be used for trading and only those with sufficient risk capital should consider trading. Past performance is not necessarily indicative of future results.

HYPOTHETICAL PERFORMANCE DISCLAIMER: HYPOTHETICAL PERFORMANCE RESULTS HAVE MANY INHERENT LIMITATIONS, SOME OF WHICH ARE DESCRIBED BELOW. NO REPRESENTATION IS BEING MADE THAT ANY ACCOUNT WILL OR IS LIKELY TO ACHIEVE PROFITS OR LOSSES SIMILAR TO THOSE SHOWN; IN FACT, THERE ARE FREQUENTLY SHARP DIFFERENCES BETWEEN HYPOTHETICAL PERFORMANCE RESULTS AND THE ACTUAL RESULTS SUBSEQUENTLY ACHIEVED BY ANY PARTICULAR TRADING PROGRAM. ONE OF THE LIMITATIONS OF HYPOTHETICAL PERFORMANCE RESULTS IS THAT THEY ARE GENERALLY PREPARED WITH THE BENEFIT OF HINDSIGHT. IN ADDITION, HYPOTHETICAL TRADING DOES NOT INVOLVE FINANCIAL RISK, AND NO HYPOTHETICAL TRADING RECORD CAN COMPLETELY ACCOUNT FOR THE IMPACT OF FINANCIAL RISK OF ACTUAL TRADING. FOR EXAMPLE, THE ABILITY TO WITHSTAND LOSSES OR TO ADHERE TO A PARTICULAR TRADING PROGRAM IN SPITE OF TRADING LOSSES ARE MATERIAL POINTS WHICH CAN ALSO ADVERSELY AFFECT ACTUAL TRADING RESULTS. THERE ARE NUMEROUS OTHER FACTORS RELATED TO THE MARKETS IN GENERAL OR TO THE IMPLEMENTATION OF ANY SPECIFIC TRADING PROGRAM WHICH CANNOT BE FULLY ACCOUNTED FOR IN THE PREPARATION OF HYPOTHETICAL PERFORMANCE RESULTS AND ALL WHICH CAN ADVERSELY AFFECT TRADING RESULTS.