PTS Logo

Beginners guide to NinjaScript code with simple examples

How to make indicators, signals and strategies in NinjaTrader 8

Programming in NinjaScript: This tutorial guide gives easy examples of NinjaScript code that are easily understood. Creating indicators and code signals made easy.

How to code simple strategies and indicators coded in NinjaScript that can be used in NinjaTrader 8 for improving your coding skills in steps. There is a chess puzzle too.

 

Leadership joke

 

 The fix for division by zero errors are shown lower down this page. Taking regular brain breaks when coding can easily help performance

 



Beginners example No.1 ( Creating a check or tick box for a strategy to use as true or false)

using NinjaTrader.Gui.Tools;
using NinjaTrader.NinjaScript.Strategies;

namespace NinjaTrader.NinjaScript.Strategies
{
public class MyStrategy : Strategy
{
private bool useMovingAverageFilter = true; // Default to true

protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Description = "My Strategy Description";
Name = "MyStrategy";
Calculate = Calculate.OnEachTick;
IsOverlay = false;
BarsRequiredToTrade = 1;
}
else if (State == State.Configure)
{
AddBoolean("UseMovingAverageFilter", true, "Use Moving Average Filter");
}
}

protected override void OnBarUpdate()
{
// Check the value of the checkbox
if (useMovingAverageFilter)
{
// Your code to apply the moving average filter goes here
}
}
}
}


The code in bold text creates the tick box that is visible in the strategy properties window

The 2nd bold text gives permission to the code undernearth it to run or be disabled depending on if it is true or false. ( Ticked or un ticked )




Beginners example No.2 (Making indicators change colour or become transparent invisible on different conditions) 


The code below changes the indicator called "Average" when the currentbar is > "Length" variable

Just change the names to the plots you use.

if (CurrentBar > Length)
{
if (Average[0] >= Average[1])
PlotBrushes[0][0] = Brushes.White;

else if (Average[0] < Average[1])
PlotBrushes[0][0] = Brushes.Transparent;
}

The Average plot dissapears if it starts falling and reappears when it is rising.

 

Beginners example No.3 (Using the print command to check things are working)


In the code say you want to check the values of "Average" you can type this into the script below the section protected override void OnBarUpdate()


Print("Average: " + average);

// Replace average with what you need to check and be sure to get the first letters in upper or lower case as shown.

Then go to control centre and click on New > NinjaScript Output

This opens a window which will be blank.

Remove your indicator from the chart and then add it again, the values will then populate the output window so you can check them over.



Just added this new page with some open code on using the Qstick Indicator with two different lengths.

Surprisingly good for a trading strategy

Both versions of Quick stick have to be above zero to go long in this code example.
Opens up a new tab so you dont lose your place in the page

Qstick trading system

The simple qstick trading system 

Beginners example No.4 ( Adding and removing plots and plot names from NinjaScript ) 


The code starts with the first indicator as values[0]
 
The 2nd plot will be values[1]

The 3rd plot will be values[2]

Etc...

If you decide to remove the first plot during your build you may find none of the plots work anymore.

To suggest a catch, always always make the most important plots as values[0] and the 2nd most important as values[1] etc

Here is an example of how things can go wrong during editing code.

So for example if the plot called "nextLongEntry" is to be removed by commenting out, then nothing will work.
To fix this issue see the next snippet below.

[Browsable(false)]
[XmlIgnore]
public Series<double> nextLongEntry
{
get { return Values[0]; }
}

[Browsable(false)]
[XmlIgnore]
public Series<double> nextShortEntry
{
get { return Values[1]; }
}

[Browsable(false)]
[XmlIgnore]
public Series<double> lowStop // Long emergency stop
{
get { return Values[2]; }
}

Correct method to remove plot 0 is to comment it out AND rename the next plot as 0, 1, 2, 3 etc so that the first one is always Values[0]

//[Browsable(false)]
//[XmlIgnore]
//public Series<double> nextLongEntry // Removed the original plot called Values[0] from plotting.
//{
//get { return Values[0]; }
//}

[Browsable(false)]
[XmlIgnore]
public Series<double> nextShortEntry
{
get { return Values[0]; }
}

[Browsable(false)]
[XmlIgnore]
public Series<double> lowStop
{
get { return Values[1]; }
}

If you have plot colour changing code or other actions being performed on the code then this will need to be altered also thus

// long mode
if (CurrentBar > 10)
{
if (upcount > 0 && downcount == 0)
{
PlotBrushes[3][0] = Brushes.Transparent; // this was setting value 3 to transparent but value 3 no longer exists, so it needs to be changed to
}

// Corrected line of code below
PlotBrushes[2][0] = Brushes.Transparent;



 
Tip

To be a better programmer: Eat oily fish or take omega 3 capsules. It does not make you smarter but seems to enable better organisation, concentration and focus.

Notice how easy on your eyes this colour scheme is, try adjusting your schema to suit your preferences so you can work easier.

Grey-Green tones are good.

Some say that listening to gentle and low volume classical music boosts exam results in students.

Some others say that green is good because it is the only colour your eyes do not need to adjust to view it. Maybe this is why forests are relaxing?

Tip

To be a worse programmer: Listen to loud rap or rock n roll music while coding: Seems to cause a massive decrease in performance. 

Stay up until 3am to complete the project. The work you do between 2-3 will totally mess up what you did before 1am or 2am.

Enthusiam to complete a task is great but is counteracted by the dumb brain function caused by the tiredness

Notice the pink background is not as easy on the eyes as the green or grey?


Beginners example No.5 ( Adding Maximum and Mininum values to indicator plots to prevent a beginner entering an unsuitable value ) 




The code below sets "Range" of an indicator plot called Sensitivity to a minimum of 10 and a maximum of 999.

If a value less than 10 is entered it will auto correct itself to 10 and the same applies if a value above 999 is entered it will revert to 999 automatically

The first block is set to a "public double" which means it can take decimal places as inputs such as 53.54

[NinjaScriptProperty]
[Range(10, 999)]
[Display(Name="Sensitivity", Order=1, GroupName="Parameters")]
public double Sensitivity
{ get; set; }

If you want a free value of an integer to be anything you can leave the code like this below.
This second block is set to "public int" which means it can only take a whole number like 33 or 53 and will not accept decimal places.

 [NinjaScriptProperty]
 [Range(1, int.MaxValue)]
 [Display(Name="Sensitivity", Order=1, GroupName="Parameters")]
 public int Length
 { get; set; }





This page contains the formula for a regular weighted moving average together with diagrams and table showing it.

 Beginners example No.6 ( How to prevent division by zero errors )


This example shows how to correct division by zero errors in NinjaScript

The image below is a good likeness for a division by zero event.

Computers act like the functioning of the road in the picture. They can't deal with it in a manly fashion.
Division by zero causes problemsDivide by zero and the World ends


Division by zero is a frequent problem experienced in programming. The answer is always infinity, so we have to prevent anything getting divided by zero in the first place.

There are two methods of doing this.

Method 1

If value1 = 0 then value1=value1+0.000000001;

So we simply add a tiny number to it, which is so tiny it will not make too much difference to the outputs.

This is not ideal and a more precise and programmatically correct method is show in method 2 below.

Method 2

If value1 <> 0 then value2 = value3 / value1;

This forces the computer to ask if the value1 is 0 or not before doing its calculations.

If it is 0 it will return the default value that was assigned to value1 in the variables when you created it.

Voila
 


Method 3

double value1 = 0.0; // Some value
double value2 = 0.0; // Result
double value3 = 10.0; // Some value

// Check if value1 is not equal to zero before performing division
if (value1 != 0.0)
{
value2 = value3 / value1;
}
else
{
// Set value2 to 0 to prevent division by zero
value2 = 0.0;
// You can also print a message or take other actions here
}





If you like what you see, feel free to SIGN UP to ideas new product and zero spam less than 10 emails per year.


Beginners example No.7 ( When using the Print command and incorrect values appear in the output window )

Print("NextLongEntry: " + NextLongEntry); // This is incorrect

NextShortEntry: NinjaTrader.NinjaScript.Series`1[System.Double]
NextShortEntry: NinjaTrader.NinjaScript.Series`1[System.Double]
NextShortEntry: NinjaTrader.NinjaScript.Series`1[System.Double]

Print("NextLongEntry: " + NextLongEntry[0]); // correct

If you are printing a series and you see the output window filled with the above then it needs to be indexed to each bar by adding [0] next to it.

If you want to print the date and time you can add this code below.

Print(Time + " - NextLongEntry: " + NextLongEntry[0]);

Tip

Further notes on division.

Using division in programming is the slowest of all the basic maths functions and it uses up more resources faster than multiplication.

If you can use multiplication instead then use it and your code will easily run faster

EG.

Bad method     XYZ = (Low + High) /2;

Better method XYZ = (Low + High) * 0.5;


Making this change to your code can be the difference between missing or getting filled in a fast market.

One day this could mean a load of money is saved and even if it doesnt it will reduce your energy bill by a penny or two over fifty years, or a dollar / pound / euro in five

minutes when the inevitable hyper inflation kicks in.
 Floating point overflow.


A Mnemonics expert advised taking regular 5-10 minute breaks each hour to rest your programming brain while keeping it active by doing some other brain actions


CHESS PUZZLE

You can figure this one out with a bit of time

White to move

Mate in two moves.

Solution lower down the page and some more relaxing trading related items that you can use during brain rest breaks.

 
Chess puzzle No.1 






Tip

To solve this puzzle the theme is that a player cannot miss a move, the rules state that each player has to move when it is their turn, even if the only move is certain death.

It may look impossible at first glance, but it isnt.

The clue is there just think it through.

After whites move then black is in "Zugzwang" which is a German term meaning there is no move to do that doesn't make the position worse.

If you solved it, there is another chess puzzle on this page It is a very hard one with not much chance of solving it unless you are a grandmaster.

Code Tip

How to comment out code in NinjaScript code language to stop it being used.

The way to comment code to stop it being read by the programme

//Two slashes at the start of the text means everything to the right of the slashes is invisible to the programme.





Hidden text appears in green font so you can see it is commented out and is there just for your notation to understand that part of code.


Videos of trading systems in action

Forcing indicators to be linear scaling instead of logarithmic scaling. 


Often if a chart axis is using a logarithmic axis and a new indicator is constructed, then the new indicator when plotted in subgraph 2 or panel 2 will copy the

axis type of the chart when it is not supposed to.

The solution is to insert a code snippet into the top on state change section to force the correct scaling of the indicator.

//Add this code in the  variables under public class (name of your indicator) : Indicator

private bool YAxisScalingType;
private bool Linear;

//Add this code in the  protected override void OnStateChange()


YAxisScalingType = Linear;


Please note this code can sometimes work and sometimes not. If it does not work for you, then right click on the axis beside the indicator the click properties

then choose type linear from the drop down box.


Beginners example No.8 (What happens when you get everything right after a lot of hard work)


Over the last thirty five years I have studied many aspects of technical analysis and automatic trading systems, bespoke indicators drawing tools etc.

The PLA Dynamical GOLD moving average uses over 1000 lines of NinjaScript code to compute its values, it was worth the effort.

It does not happen by luck, mostly it is a few hundred ideas that are not as good as hoped but one or two work well.

Perseverence is vital, it takes time to be able to design cycle finding code like John Ehlers, also takes time to be that good at maths.

Here are some of my best formulas all completely solid in their execution they are all done in NinjaScript code.





Practice makes perfect and persistence is vital. You can make anything you want if you keep at it.

Most of the things I make get abandoned it is the continual trying and testing that leads to a good concept making it to the finishing line.



Some of the excellent qualities of Demand Index went into the creation of the Precision Index Oscillator shown below, a highly complex consensus indicator that provides

pinpoint top and bottom identification in the form of highlights when plus or minus 3.141 is reached ( hence the name Pi-Osc ) the results speak for themselves.
 

The Pi-Osc 


There are some other code samples in other languages below



If you use Tradestation or MultiCharts there are some easy to follow EasyLanguage code examples on this page



If you use ProRealTime there are some easy to follow ProRealCode code examples on this page


 
 

Code above

 


More examples of clever things you can do with NinjaScript code.




Beginners example No.9  Goertzels algorithm
Beginners example No.10  Understanding arrays
Beginners example No.11  Understanding arrays
Beginners example No.12  Elapsure strategies using decaying algorithmic solutions
Beginners example No.13  Machine learning trading strategy

More educational geek stuff below for your amusment to help you refresh your programming mind in between coding sessions

REAL DEAL Stock market calculators


This page explains the essential but lightly read topic of risk control which demonstrate How to compute optimal risk


You might also enjoy this 100% accurate formula which is designed to  Compute the maximum and minimum highs and lows 30 days into the future

 

Calculate how much you will lose if the next crash is the same magnitude as it was in the 1987 crash with the Magic crash calculator

 

Real World trading practice and fun time study


Generate a report that shows your trading style and lake ratio, risk reward raio, winning trade percentage, drawdowns and more all the time your brain will

keep busy but it will relax the programming part of it while you enjoy some trading practice with actual market prices in the Trading IQ Game  which is

rather difficult.

Probably you will not exceed a 1000 Trading IQ and will give up after a few sessions. Those winners with determination can get my three of my paid

products and the MultiCharts platform as prizes.

Some extracts of ProRealCode are on this page which are easily converted to EasyLanguage code.

Samples include- Drawdown system switch off, Trailing stops, position size algorithms, infinite loops and more

  The journey of a thousand miles begins with the first step     Start the Trading IQ Game   the winning comes from the doing. Yes it is free 100%


Theoretical study


More educational content the pages below are for you Trading Lessons in several parts for new traders and improvers some parts of it are more advanced.


The least visited page on PTS site is called "Correct answer"  hopefully you can find it instead of the more popular "Incorrect answer" page.


If you still have not solved the chess puzzle, consider moving the rook somewhere which looks wrong before you scroll down to the answer below.
 

 

The help and advice of customers and readers is valuable to me.

Have a suggestion?

Tell me what you need...Send it in JUST DO IT

The contact page here has my email address and you can search the site

 

Return to the top of page (Keep within the legal speed limit)

 

 

If you like what you see, feel free to SIGN UP  to be notified of new products - articles - less than 8 emails a year and ZERO spam-

less than 10 emails a year and ZERO spam and ZERO hard selling

 

About

 

Precision Trading Systems was founded in 2006 providing high quality indicators and trading systems for a wide range of markets and levels of experience.

Supporting NinjaTrader, Tradestation. MultiCharts, TradingView, MetaTrader 4 and MT5

 
Bio 
 

 

 

Admin notes: page created 27th October 2023 sm icons added sc and ga at base....too early for caveat

Chess puzzle solution RH6! leads to Zugzwang for black as if pawn takes rook, then pawn G7 is check mate. Or if the bishop moves away then rook x H7 is mate

Next chess puzzle here