Dark Theme
Light Theme
Trading Articles
Article Categories
Article Tools
Welcome to NexusFi: the best trading community on the planet, with over 150,000 members Sign Up Now for Free
Genuine reviews from real traders, not fake reviews from stealth vendors
Quality education from leading professional traders
We are a friendly, helpful, and positive community
We do not tolerate rude behavior, trolling, or vendors advertising in posts
We are here to help, just let us know what you need
You'll need to
register in order to view the content of the threads and start contributing to our community.
It's free for basic access, or support us by becoming an Elite Member -- see if you qualify for a discount below.
-- Big Mike, Site Administrator
(If you already have an account, login at the top of the page)
Coding NinjaScript Variables
Updated November 6, 2020
trending_up
3,049 views
thumb_up
9 thanks given
group
3 followers
forum
8 posts
attach_file
2 attachments
Coding NinjaScript Variables
November 5th, 2020, 09:49 AM
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?
Best Threads (Most Thanked) in the last 7 days on NexusFi
November 5th, 2020, 04:56 PM
Chicago IL
Posts: 180 since Apr 2016
Thanks Given: 573
Thanks Received: 129
Stonewall
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];
November 5th, 2020, 08:21 PM
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.
November 5th, 2020, 09:00 PM
Chicago IL
Posts: 180 since Apr 2016
Thanks Given: 573
Thanks Received: 129
Stonewall
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
November 6th, 2020, 06:19 AM
Washington DC
Experience: Beginner
Platform: NinjaTrader7
Trading: ES
Posts: 74 since Oct 2010
Thanks Given: 108
Thanks Received: 84
Stonewall
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
November 6th, 2020, 10:18 AM
Houston TX USA
Posts: 4 since May 2020
Thanks Given: 6
Thanks Received: 1
userque
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
November 6th, 2020, 10:57 AM
Chicago IL
Posts: 180 since Apr 2016
Thanks Given: 573
Thanks Received: 129
Stonewall
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.
November 6th, 2020, 11:08 AM
Washington DC
Experience: Beginner
Platform: NinjaTrader7
Trading: ES
Posts: 74 since Oct 2010
Thanks Given: 108
Thanks Received: 84
Stonewall
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
November 6th, 2020, 01:09 PM
Houston TX USA
Posts: 4 since May 2020
Thanks Given: 6
Thanks Received: 1
Jack22
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.
Last Updated on November 6, 2020