First Indicator 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.
There are two extremely important concepts that need to be understood when you are programming in NinjaTrader: CurrentBar and PriceSeries. Briefly, each bar on your chart is assigned a number, which is stored as a value in the variable CurrentBar. Also, each bar can reference certain data, such as the Close of the bar, based on the number of BarsAgo (bars to the left of the bar currently processing OnBarUpdate()).
The variable CurrentBar allows us to determine how many bars are currently on the chart, or if bars have been drawn on the chart at all. For example, let’s assume you open a new chart and no bars are present, CurrentBar will have a value of -1. Now, let’s assume one bar is drawn on that same chart (on the extreme left of your chart). CurrentBar will have a value of 0, which tells us that 1 bar is on the chart. Using the same chart with 1 bar (CurrentBar == 0), NinjaTrader will continue building the chart by adding 1 bar to the right, until all of your data is loaded. Each time NinjaTrader adds a bar to the chart, CurrentBar increases by 1, which can be expressed as CurrentBar = CurrentBar + 1, or CurrentBar++, or CurrentBar += 1. In the below image, I have drawn the value of CurrentBar above even and below odd numbered candles:
Think of PriceSeries as another name for all the price data that is available for us to reference on any given bar, which are as follows (we will not go into the multi-time frame consideration at this point, but we will later!):
- Close: Represents the Close of the referenced bar.
- High: Represents the High of the referenced bar.
- Input: Represents the Input of the referenced bar, which can be changed when you are editing the settings of an indicator–there is an option Input Series, which you can choose the Price Type and / or another indicator value as the input for that indicator. Instead of using Close while we are coding, we can choose to use Input, which will allow the user to select the desired value, such as Weighted, for the indicator calculation.
- Low: Represents the Low of the referenced bar.
- Median: Represents the Median of the referenced bar, which is defined as: (High + Low) / 2.
- Open: Represents the Open of the referenced bar.
- Typical: Represents the Typical price of the referenced bar, which is defined as: (High + Low + Close) / 3.
- Value: We will explore this option in a later Part when we add Plots to our chart.
- Weighted: Represents the Typical price of the referenced bar, which is defined as (Close + Close is not a typo): (High + Low + Close + Close) / 4 .
I know, I kept repeating referenced bar, so let’s define what I really mean with a little more explanation and some examples. First remember that CurrentBar starts counting at 0 (-1 represents no bars being on the chart) and then increments by 1 for each bar that is added to your chart, so think of CurrentBar as starting at 0 and counting in increments of 1 from left to right. It is important to remember this because the way we reference a PriceSeries, which is based on BarsAgo. Let’s assume we open a new chart and have 100 bars. If we want to reference the Close of the bar to the very right of your chart, we would write Close[BarsAgo], which would be Close. If we wanted to reference the bar to the immediate left of the right most bar, we would write Close, which says I want the Close 1 bar prior to the right most bar. So, think of PriceSeries as starting at 0 and counting in increments of 1 from right to left. Here is an example, similar to the CurrentBar example, where I print how we would reference the bar by plotting the BarsAgo number above / below the candle:
The one thing you most likely noticed is that the right most bar did not have a number over it. Well, that gets into what our setting is for Calculate. The image above was taken with Calculate.OnBarClose, which means NinjaTrader only processes the right most bar after it has closed and a new bar has opened. If we used a different setting, such as Calculate.OnEachTick, NinjaTrader will process the right most bar as each tick is processed by your data feed, which makes the image look like this:
As you will notice, the numbers all moved one bar to the right because of the Calculate setting. For now, we will assume our indicators are processed on Calculate.OnBarClose, since we are still learning and this is the least resource intensive option.
First Indicator Example
One of the first things we want to do when developing any indicator is to add a “check,” in OnBarUpdate, to determine if we have enough data loaded on our chart to begin processing our indicators logic. For example, if we are working on a Moving Average that has a Period of 5, we need at least 5 bars for the calculation, so we need to have our code check that we have at least 5 bars on the chart before we process any calculations. Since CurrentBar keeps track of the number of bars on the chart, we can use that variable to check if we can start processing (if we have a little more data loaded on the chart than we absolutely need, that is ok):
Once our If Statement from above is False, we have enough bars loaded on our chart and can begin processing information in OnBarUpdate (everything below return). The next thing we want to do is create an If Statement for IsFirstTickOfBar, which will be true if the incoming tick is the first tick of a new bar (otherwise it will be false). An important note is that this property is only of value when the Calculate property is set to Calculate.OnEachTick or Calculate.OnPriceChange, so we are adding this in if you decide to run this indicator on something other than OnBarClose. Why do we need this? Well, we are going to draw something, so we want to make sure we only draw it once per bar. If we did not have this check in place and you were using OnEachTick, as each tick was processed, NinjaTrader would redraw the draw object, which can end up being resource intensive. So, we can write something like:
Great, now we are going to create a temporary variable that will only be valid / able to be referenced within our If Statement, which we want to hold the value of CurrentBar as a string:
The next step is to draw the CurrentBar number above / below the bar. So, what we need to do is determine if a bar is even or odd. To do that we could divide the CurrentBar by 2 and see if there is a remainder, which we can accomplish with the % (Modulus) Operator:
Finally! We are at the part where we can draw something on our chart. We will be using Draw.Text. The important thing to know is how to reference methods such as these in the NinjaTarder help guide because under Syntax, NinjaTrader details all the valid ways to call this method. Under Parameters, NinjaTrader gives a detailed explanation for each input. Let’s take the first as an example: Draw.Text(NinjaScriptBase owner, string tag, string text, int barsAgo, double y)
- NinjaScriptBase owner: For our purposes this is extremely simple and the input will be “this”. Think to yourself, “this” indicator is the owner of the draw object.
- string tag: The “string” lets us know that the input must be a string variable and will be the draw objects tag. The tag will be view-able if you double click on the draw object on your chart.
- string text: Again “string” lets us know that the input must be a string variable and will be the text that is actually drawn.
- int barsAgo: The “int” lets us know that the input must be an integer and will draw the object based on the same BarsAgo logic in our PriceSeries discussion.
- double y: The “double” lets us know that the input must be a double data type and the y is where the draw object will be drawn, which is normally an offset from a PriceSeries object.
Let’s see what this looks like in action:
Great! Now save, compile, and load the indicator on your chart and it should look like the example in CurrentBar. We are almost finished, but we need to add one additional component–creating an option for the offset of our text. We can create a user input like this:
Now that we have an input, we need to incorporate the input into our logic, which if we wanted to recalculate our offset each time OnBarUpdate was called we would change Draw.Text to this:
- Draw.Text(this, “Even ” + xCB, xCB, 0, High + iOffsetTicks * TickSize);
- Draw.Text(this, “Odd ” + xCB, xCB, 0, Low – iOffsetTicks * TickSize);
There is another option that will demonstrate the importance State.DataLoaded. In State.DataLoaded, NinjaTrader has downloaded the Bar information, so starting at this point we can reference information such as Instrument Name, Instrument Description, and TickSize. Since we can reference TickSize at this point and our offset (in ticks) will not change, we can calculate what the offset is (iOffsetTicks * TickSize) by performing the following:
- Declare a new double variable: private double iOffset = 0;
- Inside of State.DataLoaded perform the following calculation: iOffset = iOffsetTicks * TickSize;
- Updated Draw.Text: Draw.Text(this, “Even ” + xCB, xCB, 0, High + iOffset);
Once those updates are made, our indicator should now look like this:
It’s As Simple As That
We reviewed a lot of important NinjaScript concepts in this Part and created our first indicator, even though it was simple, it demonstrated several concepts that you will be able to use in your own development. Now it’s time to checkout Part 7 – Series<T> Basics.