NexusFi: Find Your Edge


Home Menu

 





Coding NinjaScript Variables


Discussion in NinjaTrader

Updated
    1. trending_up 3,049 views
    2. thumb_up 9 thanks given
    3. group 3 followers
    1. forum 8 posts
    2. attach_file 2 attachments




 
 

Coding NinjaScript Variables

 
Stonewall
Houston TX USA
 
Posts: 4 since May 2020
Thanks Given: 6
Thanks Received: 1

Hello, everyone! A few details about myself -
I began learning the ThinkScript coding language at the beginning of this year, and feel that I understand the basic methods of that language. Now I am attempting to transfer/convert indicators from ThinkScript into NinjaScript. I have always found it easier to "learn by doing" and through trial and error, although I am doing my best to read through C# coding resources.

I have hit a stumbling block, though, in that I cannot find how to recreate a ThinkScript recursive variable in NinjaScript. I was wondering if someone could guide me through it. This is the ThinkScript code snippet -

 
Code
def LargeDonchianLow = Lowest(low, 30);
def SmallDonchianHigh = Highest(high, 3);
def LongTrigger = if high > SmallDonchianHigh[1] then 1
                           else if low < LargeDonchianLow[1] then 0
                           else LongTrigger[1];
def LongLine = if high > SmallDonchianHigh[1] and LongTrigger  == 1 and LongTrigger[1] < 1 then SmallDonchianHigh[1]
                       else if LongTrigger == 0 then double.nan
                       else LongLine[1];
Thanks for any help given, it is greatly appreciated!

*Edit: I posted this in the wrong area, so deleted it and reposted here.


Can you help answer these questions
from other members on NexusFi?
Exit Strategy
NinjaTrader
Build trailing stop for micro index(s)
Psychology and Money Management
Futures True Range Report
The Elite Circle
New Micros: Ultra 10-Year & Ultra T-Bond -- Live Now
Treasury Notes and Bonds
ZombieSqueeze
Platforms and Indicators
 
 
userque
Chicago IL
 
Posts: 180 since Apr 2016
Thanks Given: 573
Thanks Received: 129


Stonewall View Post
Hello, everyone! A few details about myself -
I began learning the ThinkScript coding language at the beginning of this year, and feel that I understand the basic methods of that language. Now I am attempting to transfer/convert indicators from ThinkScript into NinjaScript. I have always found it easier to "learn by doing" and through trial and error, although I am doing my best to read through C# coding resources.

I have hit a stumbling block, though, in that I cannot find how to recreate a ThinkScript recursive variable in NinjaScript. I was wondering if someone could guide me through it. This is the ThinkScript code snippet -

def LargeDonchianLow = Lowest(low, 30);
def SmallDonchianHigh = Highest(high, 3);
def LongTrigger = if high > SmallDonchianHigh[1] then 1
else if low < LargeDonchianLow[1] then 0
else LongTrigger[1];
def LongLine = if high > SmallDonchianHigh[1] and LongTrigger == 1 and LongTrigger[1] < 1 then SmallDonchianHigh[1]
else if LongTrigger == 0 then double.nan
else LongLine[1];

Thanks for any help given, it is greatly appreciated!

*Edit: I posted this in the wrong area, so deleted it and reposted here.

In your snippet, you only go back one [1] with your recursives. Is that also the furthest you go back in the rest of your code as well?

Also, your code is more easily readable by wrapping it in 'code' tags (see '#' button above 'compose message:' editor box.

 
Code
def LargeDonchianLow = Lowest(low, 30);
def SmallDonchianHigh = Highest(high, 3);
def LongTrigger = if high > SmallDonchianHigh[1] then 1
                           else if low < LargeDonchianLow[1] then 0
                           else LongTrigger[1];
def LongLine = if high > SmallDonchianHigh[1] and LongTrigger  == 1 and LongTrigger[1] < 1 then SmallDonchianHigh[1]
                       else if LongTrigger == 0 then double.nan
                       else LongLine[1];

Thanked by:
 
Stonewall
Houston TX USA
 
Posts: 4 since May 2020
Thanks Given: 6
Thanks Received: 1


Here is the whole ThinkScript code, I probably should have posted it instead -

 
Code
# Donchian Channel Reversals

input long = yes;
input short = yes;

# Long Side
def LargeDonchianLow = Lowest(low, 30);
def SmallDonchianHigh = Highest(high, 3);
def LongTrigger = if high > SmallDonchianHigh[1] then 1
                           else if low < LargeDonchianLow[1] then 0
                           else LongTrigger[1];
def LongLine = if high > SmallDonchianHigh[1] and LongTrigger  == 1 and LongTrigger[1] < 1 then SmallDonchianHigh[1]
                      else if LongTrigger == 0 then double.nan
                      else LongLine[1];

plot LEntry = if long and LargeDonchianLow < LongLine then LongLine else double.nan;
      LEntry.SetDefaultColor(Color.green);
plot LStop = if long then LargeDonchianLow else double.nan;
      LStop.SetDefaultColor(Color.blue);

# Short Side
def LargeDonchianHigh = Highest(high, 30);
def SmallDonchianLow = Lowest(low, 3);
def ShortTrigger = if low < SmallDonchianLow[1] then -1
                            else if high > LargeDonchianHigh[1] then 0
                            else ShortTrigger[1];
def ShortLine = if low < SmallDonchianLow[1] and ShortTrigger == -1 and ShortTrigger[1] > -1 then SmallDonchianLow[1] 
                        else if ShortTrigger == 0 then double.nan
                        else ShortLine[1];

plot SEntry = if short and LargeDonchianHigh > ShortLine then ShortLine else double.nan;
      SEntry.SetDefaultColor(color.red);
plot SStop = if short then LargeDonchianHigh else double.nan;
      SStop.SetDefaultColor(color.magenta);

# end of code

So far, I've gotten this completed in NinjaScript by using the built-in Donchian channel indicator (and other codes as well) -


 
Code
namespace NinjaTrader.NinjaScript.Indicators
{
	public class DonchianChannelReversals : Indicator
	{
		private MAX max1;
		private MIN min1;
		private MAX max2;
		private MIN min2;
		
		protected override void OnStateChange()
		{
			if (State == State.SetDefaults)
			{
				Description									= @"Enter the description for your new custom Indicator here.";
				Name										= "DonchianChannelReversals";
				Calculate									= Calculate.OnPriceChange;
				IsOverlay									= true;
				DisplayInDataBox							= true;
				DrawOnPricePanel							= true;
				DrawHorizontalGridLines						= true;
				DrawVerticalGridLines						= true;
				PaintPriceMarkers							= true;
				ScaleJustification							= NinjaTrader.Gui.Chart.ScaleJustification.Right;
				//Disable this property if your indicator requires custom values that cumulate with each new market data event. 
				//See Help Guide for additional information.
				IsSuspendedWhileInactive	= true;
				ShortLength					= 3;
				LongLength					= 30;
				ShowShort					= true;
				ShowLong					= true;
				AddPlot(Brushes.Red, "ShortDonchianLow");
				AddPlot(Brushes.Lime, "ShortDonchianHigh");
				AddPlot(Brushes.DodgerBlue, "LongDonchianLow");
				AddPlot(Brushes.DodgerBlue, "LongDonchianHigh");
				AddPlot(Brushes.Aqua, "EntryLineLong");
				AddPlot(Brushes.Fuchsia, "EntryLineShort");
				}
			else if (State == State.Configure)
			{
			}
			else if (State == State.DataLoaded)
			{
				max1 = MAX(High, ShortLength);
				min1 = MIN(Low, ShortLength);
				max2 = MAX(High, LongLength);
				min2 = MIN(Low, LongLength);
			}
		}

		protected override void OnBarUpdate()
		{
			// toggles on/off two plots at the same time:
			// a) the high band of the shorter Donchian Channel
			// b) the low band of the longer Donchian Channel
			if(ShowShort)
			{
			ShortDonchianLow[0] = min1[0];
			LongDonchianHigh[0] = max2[0];
			}
			
			// toggles on/off two plots at the same time:
			// a) the low band of the shorter Donchian Channel
			// b) the high band of the longer Donchian Channel
			if(ShowLong)
			{
			ShortDonchianHigh[0] = max1[0];
			LongDonchianLow[0] = min2[0];
			}

		}

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

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

		[NinjaScriptProperty]
		[Display(Name="ShowShort", Order=3, GroupName="Parameters")]
		public bool ShowShort
		{ get; set; }

		[NinjaScriptProperty]
		[Display(Name="ShowLong", Order=4, GroupName="Parameters")]
		public bool ShowLong
		{ get; set; }

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

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

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

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

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

		[Browsable(false)]
		[XmlIgnore]
		public Series<double> EntryLineShort
		{
			get { return Values[5]; }
		}
		#endregion

	}
}

Ive tried to code the variables in, but no matter what I do, I seem to throw error codes and /or make the plots disappear. It is very different from ThinkScript.
BTW, thanks for showing how to wrap the code.

 
userque
Chicago IL
 
Posts: 180 since Apr 2016
Thanks Given: 573
Thanks Received: 129


Stonewall View Post
Ive tried to code the variables in, but no matter what I do, I seem to throw error codes and /or make the plots disappear. It is very different from ThinkScript.
BTW, thanks for showing how to wrap the code.

Having the whole code is very helpful.

Knowing the error codes you get would also be helpful.

Try replacing "min1[0]" with just "min1"
Do the same for min2, max1, and max2

Thanked by:
 
 Jack22 
Washington DC
 
Experience: Beginner
Platform: NinjaTrader7
Trading: ES
Posts: 74 since Oct 2010
Thanks Given: 108
Thanks Received: 84


Stonewall View Post
Here is the whole ThinkScript code, I probably should have posted it instead -

Ive tried to code the variables in, but no matter what I do, I seem to throw error codes and /or make the plots disappear. It is very different from ThinkScript.
BTW, thanks for showing how to wrap the code.

In OnBarUpdate, you are missing a check to make sure you have enough bars. Try the attached.

Attached Files
Elite Membership required to download: DonchianChannelReversals.cs
Thanked by:
 
Stonewall
Houston TX USA
 
Posts: 4 since May 2020
Thanks Given: 6
Thanks Received: 1


userque View Post
Having the whole code is very helpful.

Knowing the error codes you get would also be helpful.

Try replacing "min1[0]" with just "min1"
Do the same for min2, max1, and max2

When I do this, the compiler says "cannot implicitly convert type 'NinjaTrader.NinjaScript.Indicators.MIN' to 'double'", with the error code CS0029. The ninja code posted above earlier plots properly on the chart with the "[0]" after the "min1", etc., so I guess its good with the brackets?

I'm doing my best to continue with the variables. For some reason, the code compiles properly after I add code for the variables, but then nothing will show up on a chart. I can't figure out why, is it affected by using the bracketed numbers after "max1", etc?

Thank you, @Jack22, Ive added the necessary code as you pointed out. My code probably makes a professional coder cringe.

 
Code
namespace NinjaTrader.NinjaScript.Indicators
{
	public class DonchianChannelReversals : Indicator
	{
		private MAX max1;
		private MIN min1;
		private MAX max2;
		private MIN min2;
		private int maxPeriod;
		private Series<int> LongTrigger;
		private Series<int> LongLine;
				
		protected override void OnStateChange()
		{
			if (State == State.SetDefaults)
			{
				Description									= @"Enter the description for your new custom Indicator here.";
				Name										= "DonchianChannelReversals";
				Calculate									= Calculate.OnPriceChange;
				IsOverlay									= true;
				DisplayInDataBox							= true;
				DrawOnPricePanel							= true;
				DrawHorizontalGridLines						= true;
				DrawVerticalGridLines						= true;
				PaintPriceMarkers							= true;
				ScaleJustification							= NinjaTrader.Gui.Chart.ScaleJustification.Right;
				//Disable this property if your indicator requires custom values that cumulate with each new market data event. 
				//See Help Guide for additional information.
				IsSuspendedWhileInactive	= true;
				ShortLength					= 3;
				LongLength					= 30;
				ShowShort					= true;
				ShowLong					= true;
				AddPlot(Brushes.Red, "ShortDonchianLow");
				AddPlot(Brushes.Lime, "ShortDonchianHigh");
				AddPlot(Brushes.DodgerBlue, "LongDonchianLow");
				AddPlot(Brushes.DodgerBlue, "LongDonchianHigh");
				AddPlot(Brushes.Aqua, "EntryLineLong");
				AddPlot(Brushes.Fuchsia, "EntryLineShort");
				}
			else if (State == State.Configure)
			{
			}
			else if (State == State.DataLoaded)
			{
				max1 = MAX(High, ShortLength);
				min1 = MIN(Low, ShortLength);
				max2 = MAX(High, LongLength);
				min2 = MIN(Low, LongLength);
				LongTrigger = new Series<int>(this);
				LongLine = new Series<int>(this);
			}
		}

		protected override void OnBarUpdate()
		{
			if(CurrentBar < maxPeriod)
				return;
			
			// ThinkScript: def LongTrigger = if high > SmallDonchianHigh[1] then 1 else if low < LargeDonchianLow[1] then 0 else LongTrigger[1];
			LongTrigger[0] = High[0] > max1[1] ? 1 : Low[0] < min2[1] ? 0 : LongTrigger[1];
			
			//ThinkScript: def LongLine = if high > SmallDonchianHigh[1] and LongTrigger  == 1 and LongTrigger[1] < 1 then SmallDonchianHigh[1]
            //        			          else if LongTrigger == 0 then double.nan
            //    			              else LongLine[1];
			if(High[0] > max1[1] && LongTrigger[0] == 1 && LongTrigger[1] < 1)
			{
				EntryLineLong[0] = max1[1];
			}
			else if(LongTrigger[0] == 0)
			{
				EntryLineLong[0] = 0;  //can't figure out how to say "EntryLineLong[0] = null" without throwing errors
			}
			else EntryLineLong[0] = EntryLineLong[1];
						
			// toggles on/off two plots at the same time:
			// a) the high band of the shorter Donchian Channel
			// b) the low band of the longer Donchian Channel
			if(ShowShort)
			{
			ShortDonchianLow[0] = min1[0];
			LongDonchianHigh[0] = max2[0];
			}
			
			// toggles on/off two plots at the same time:
			// a) the low band of the shorter Donchian Channel
			// b) the high band of the longer Donchian Channel
			if(ShowLong)
			{
			ShortDonchianHigh[0] = max1[0];
			LongDonchianLow[0] = min2[0];
			}

		}

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

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

		[NinjaScriptProperty]
		[Display(Name="ShowShort", Order=3, GroupName="Parameters")]
		public bool ShowShort
		{ get; set; }

		[NinjaScriptProperty]
		[Display(Name="ShowLong", Order=4, GroupName="Parameters")]
		public bool ShowLong
		{ get; set; }

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

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

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

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

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

		[Browsable(false)]
		[XmlIgnore]
		public Series<double> EntryLineShort
		{
			get { return Values[5]; }
		}
		#endregion

 
userque
Chicago IL
 
Posts: 180 since Apr 2016
Thanks Given: 573
Thanks Received: 129


Stonewall View Post
When I do this, the compiler says "cannot implicitly convert type 'NinjaTrader.NinjaScript.Indicators.MIN' to 'double'", with the error code CS0029. The ninja code posted above earlier plots properly on the chart with the "[0]" after the "min1", etc., so I guess its good with the brackets?

I'm doing my best to continue with the variables. For some reason, the code compiles properly after I add code for the variables, but then nothing will show up on a chart. I can't figure out why, is it affected by using the bracketed numbers after "max1", etc?

That was my bad, I was wrong on that. The brackets are syntactically ok, as they are types Min and Max. I hadn't noticed at first that the types weren't doubles/integers.

I'll take a closer look and actually try to run it myself this weekend to see what errors it gives, if you and/or @Jack22 don't figure it out by then.

Thanked by:
 
 Jack22 
Washington DC
 
Experience: Beginner
Platform: NinjaTrader7
Trading: ES
Posts: 74 since Oct 2010
Thanks Given: 108
Thanks Received: 84


Stonewall View Post
When I do this, the compiler says "cannot implicitly convert type 'NinjaTrader.NinjaScript.Indicators.MIN' to 'double'", with the error code CS0029. The ninja code posted above earlier plots properly on the chart with the "[0]" after the "min1", etc., so I guess its good with the brackets?

I'm doing my best to continue with the variables. For some reason, the code compiles properly after I add code for the variables, but then nothing will show up on a chart. I can't figure out why, is it affected by using the bracketed numbers after "max1", etc?

Thank you, @Jack22, Ive added the necessary code as you pointed out. My code probably makes a professional coder cringe.

MIN and MAX are indicators and when you are calling them from your indicator, you are trying to reference Values[0] in MIN/MAX, which is a Series<double>--that needs to be referenced with [#] in your indicator in OnBarUpdate.

To make it a little easier for you, I went ahead and converted the TOS code into NT8 (it follows the TOS logic 99% except in one area of IsValidDataPoint).

Without seeing the indicator on TOS, everything seems to be working correctly for me on NT8.

Attached Files
Elite Membership required to download: DonchianChannelReversals.cs
Thanked by:
 
Stonewall
Houston TX USA
 
Posts: 4 since May 2020
Thanks Given: 6
Thanks Received: 1


Jack22 View Post
MIN and MAX are indicators and when you are calling them from your indicator, you are trying to reference Values[0] in MIN/MAX, which is a Series<double>--that needs to be referenced with [#] in your indicator in OnBarUpdate.

To make it a little easier for you, I went ahead and converted the TOS code into NT8 (it follows the TOS logic 99% except in one area of IsValidDataPoint).

Without seeing the indicator on TOS, everything seems to be working correctly for me on NT8.

Thanks @userque!

@Jack22 - Thanks for the code sample! I'm likely going to have to take a step back and start again with something simpler to code, such as a moving average - seeing how you did that, I don't think I could have figured that code out.

I see that you also used "Reset()" where I was attempting to use "null", and declared two variables under a single "private <Series>double/int" line of code, among other things. Clearly I have a lot to learn.

Thanked by:

 



Last Updated on November 6, 2020


© 2024 NexusFi™, s.a., All Rights Reserved.
Av Ricardo J. Alfaro, Century Tower, Panama City, Panama, Ph: +507 833-9432 (Panama and Intl), +1 888-312-3001 (USA and Canada)
All information is for educational use only and is not investment advice. There is a substantial risk of loss in trading commodity futures, stocks, options and foreign exchange products. Past performance is not indicative of future results.
About Us - Contact Us - Site Rules, Acceptable Use, and Terms and Conditions - Privacy Policy - Downloads - Top
no new posts