Announcement

Collapse

Looking for a User App or Add-On built by the NinjaTrader community?

Visit NinjaTrader EcoSystem and our free User App Share!

Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less

Partner 728x90

Collapse

GRTMultiLines User Apps Share NT7 to NT8 convert

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    GRTMultiLines User Apps Share NT7 to NT8 convert

    I'm trying to convert the GRTMultiLines https://ninjatraderecosystem.com/use...ad/multilines/ to NT8.

    My code so far attached. It compiles ok but nothing shows on the chart.

    Please help, thanks!

    Attached Files

    #2
    Hello PaulMohn,

    Thank you for your note.

    I note you've created user inputs for LineCount, MidPoint, LineSpacing, LineColor, LineWidth, ResetPlots, and LineStyle, but then are also declaring variables at the class level that hold the same values:

    Code:
    public class GRTMultiLines : Indicator
    {
    private double midPoint = 0;
    private int lineCount = 21;
    private double lineSpacing = 2;
    private int lineWidth = 1;
    private Brush lineColor;
    private DashStyleHelper lineStyle;
    private bool resetPlots = true;
    You then assign default values to the ones set up as User Inputs:

    Code:
    LineCount = 21;
    MidPoint = 0;
    LineSpacing = 2;
    LineColor = Brushes.Lime;
    LineWidth = 1;
    ResetPlots = true;
    LineStyle = DashStyleHelper.Dash;
    But then you use the camel case variables in OnBarUpdate():

    Code:
    Plots[0].Brush =  lineColor;
    Code:
    Plots[0].DashStyleHelper = lineStyle;
    And the issue is that you never assigned lineStyle or lineColor a value, so while your plots have value, they don't actually get plotted.

    What you need to do is remove all those camel case variables at the top of the script and use the title case User Input ones (eg. LineCount instead of lineCount) throughout the script.

    Please let us know if we may be of further assistance to you.

    Kate W.NinjaTrader Customer Service

    Comment


      #3
      Hello Ninjatrader_Kate and thanks for your keen eye.

      I've updated the variable as follows:

      Code:
       public class GRTMultiLines : Indicator
      {
      private double MidPoint;
      private int LineCount;
      private double LineSpacing;
      private int LineWidth;
      private Brush LineColor;
      private DashStyleHelper LineStyle;
      private bool ResetPlots;
      And left the ones in SetDefaults as is:

      Code:
       protected override void OnStateChange()
      {
      if (State == State.SetDefaults)
      {
      Description = @"Plots lines at user defined price, and equally spaced apart.";
      Name = "GRTMultiLines";
      Calculate = Calculate.OnBarClose;
      IsOverlay = false;
      DisplayInDataBox = false;
      DrawOnPricePanel = true;
      DrawHorizontalGridLines = false;
      DrawVerticalGridLines = false;
      PaintPriceMarkers = false;
      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;
      LineCount = 21;
      MidPoint = 0;
      LineSpacing = 2;
      LineColor = Brushes.Lime;
      LineWidth = 1;
      ResetPlots = true;
      LineStyle = DashStyleHelper.Dash;
      AddPlot(Brushes.Lime, "Line0");
      AddPlot(Brushes.Lime, "Line1");
      AddPlot(Brushes.Lime, "Line2");
      AddPlot(Brushes.Lime, "Line3");
      AddPlot(Brushes.Lime, "Line4");
      AddPlot(Brushes.Lime, "Line5");
      AddPlot(Brushes.Lime, "Line6");
      AddPlot(Brushes.Lime, "Line7");
      AddPlot(Brushes.Lime, "Line8");
      AddPlot(Brushes.Lime, "Line9");
      AddPlot(Brushes.Lime, "Line10");
      AddPlot(Brushes.Lime, "Line11");
      AddPlot(Brushes.Lime, "Line12");
      AddPlot(Brushes.Lime, "Line13");
      AddPlot(Brushes.Lime, "Line14");
      AddPlot(Brushes.Lime, "Line15");
      AddPlot(Brushes.Lime, "Line16");
      AddPlot(Brushes.Lime, "Line17");
      AddPlot(Brushes.Lime, "Line18");
      AddPlot(Brushes.Lime, "Line19");
      AddPlot(Brushes.Lime, "Line20");
      }
      Is that correct?

      But now I get compile errors The type 'NinjaTrader.NinjaScript.Indicators.GTRMultiLines' already contains a definition for 'LineCount' CS0102 Line 215
      Same for all other variables (screenshot) lines 221, 227, 233, 246, 251, 257.


      Here's my updated code as txt GTRMultiLines(1) (can't export because of compile errors):

      And the original NT7 code GTRMultilLinesNT7:

      I noticed the NT7 code uses
      Code:
      if (lineCount >= 1)        Add(new Plot(lineColor, PlotStyle.Line, "Line0"));
      in initialize, whereas in the NT8 wizard generated code in SetDefaults it only uses
      Code:
      AddPlot(Brushes.Lime, "Line0");
      .
      Is that right?


      Attached Files
      Last edited by PaulMohn; 09-15-2021, 11:15 AM. Reason: Added update code, and NT7 code, and initialize and SetDefaults remark

      Comment


        #4
        Hello PaulMohn,

        Thank you for your reply.

        No, you want to completely remove the following in bold:

        Code:
        public class GRTMultiLines : Indicator
        {
        private double MidPoint;
        private int LineCount;
        private double LineSpacing;
        private int LineWidth;
        private Brush LineColor;
        private DashStyleHelper LineStyle;
        private bool ResetPlots;
        These have already been initialized down in the #region Properties, so you don't need to initialize them there as well, simply set the values in State.SetDefaults and you should be good to go.

        Please let us know if we may be of further assistance to you.
        Kate W.NinjaTrader Customer Service

        Comment


          #5
          Hello Ninjatrader_Kate and thanks for your help.

          Now it works, I had to correct if (resetPlots) to if (ResetPlots) as last compile errors.

          But it displays funny on the chart screenshot.

          My latest code export attached.

          Attached Files

          Comment


            #6
            Hello PaulMohn,

            Thank you for your reply.

            That would be because you have the midline set to 0, so all your lines are going to be plotted around 0. It's expecting you to put in a user defined price for that midline value when you apply it to the chart. Try putting in the current price when you apply it to the chart.

            Please let us know if we may be of further assistance to you.
            Kate W.NinjaTrader Customer Service

            Comment


              #7
              Hello Ninjatrader_Kate and thanks for your remark.

              I tested setting MidPoint = 4468 on ES and it works, thanks.

              Can we set a dynamic value for example the daily open price?

              I tested those but they don't work.

              MidPoint = ToDay(Time[0]).Open[0];

              Compile error
              GRTMultiLines.cs 'int' does not contain a definition for 'Open' and no extension method 'Open' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?) CS1061 47 35

              MidPoint = ToDay(Time[0]).CurrentOpen[0];

              Compile error
              GRTMultiLines.cs 'int' does not contain a definition for 'CurrentOpen' and no extension method 'CurrentOpen' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?) CS1061 47 35

              MidPoint = CurrentDayOHL(BarsArray[1]).CurrentOpen[0];

              Log error
              16/09/2021 09:26:13 Default Indicator 'GRTMultiLines': Error on calling 'OnStateChange' method: Index was outside the bounds of the array.

              Comment


                #8
                Hello PaulMohn,

                This is Jim responding on behalf of Kate who is out of the office at this time.

                The compile errors are informing you that the C# syntax is incorrect. ToDay() returns an integer, and there is no Open property of an integer variable.

                I would suggest going through our Indicator tutorials to get more familiar with indicator development before attempting a conversion, and to use the Strategy Builder and the View Coe button to create small pieces of logic that reference the CurrentDayOHL indicator so you can see how the syntax is used.

                Indicator tutorials - https://ninjatrader.com/support/help...indicators.htm

                Strategy Builder 301 (publicly available reference) - https://www.youtube.com/watch?v=_KQF2Sv27oE

                Out side of these materials, it will be helpful to review C# educational materials which can be found external to NinjaTrader. I have included a couple publicly available resources below.

                https://docs.microsoft.com/en-us/dot...arp/tutorials/

                https://www.tutorialsteacher.com/csh...harp-tutorials

                As for the runtime error, it means you are referencing an element that is outside of an array. This is typically seen in OnBarUpdate when a current bar check is not included to prevent the indicator from referencing, for example, 6 bars ago when the script only processed 3 bars.

                Making sure there are enough bars in the data series you are accessing - https://ninjatrader.com/support/help...nough_bars.htm

                In this case, however, we are referring to BarsArray[1], which would reference an added data series. It sounds like this Data Series was not added, so the BarsArray[1] reference would be out of range. If you are working with a Multi Time Frame, or Multi Series script, you will want to be familiar with the documentation below for usage.

                Multi Time Frame and Instruments - https://ninjatrader.com/support/help...nstruments.htm
                JimNinjaTrader Customer Service

                Comment


                  #9
                  Hello NinjaTrader_Jim,

                  Thank you for the tutorial references, very useful. I've read the BarsArray reference and updated the code to add a Data series of 60 minutes. Now I have
                  MidPoint = CurrentDayOHL(BarsArray[1]).CurrentOpen[0]; and

                  else if (State == State.Configure)
                  {
                  AddDataSeries(BarsPeriodType.Minute, 60);
                  }

                  The rest is the left the same.

                  The Log error now is:
                  16/09/2021 20:02:47 Default Indicator 'GRTMultiLines': Error on calling 'OnStateChange' method: You are accessing an index with a value that is invalid since it is out-of-range. I.E. accessing a series [barsAgo] with a value of 5 when there are only 4 bars on the chart.
                  I don't understand the error. On the chart there are obviously more than 4 bars. I don't understand why the script tries to access 5 bars ago. Nor why the script only finds 4 bars on the chart. There are at least 80 bars on the chart.
                  Why does a check is needed? What does the check do? I don't understand the concept. I've seen some check in other scripts like if(CurrentBar<2) return; . But I don't understand it. What does it mean "when there are only 4 bars on the chart"? There are a lot more bars on my chart.

                  Comment


                    #10
                    Hello PaulMohn,

                    Thanks for your reply.

                    The error message is advising that there is an indexing error and provided you with an example. The example error is not the specific issue but is trying to give you the concept that your code is trying to access a bar that is not there.

                    While your chart may have plenty of bars what you are missing is a basic understanding of how a script is run. In a nutshell, when you apply a script, the script will start with the very first historical bar in your data series and will attempt to run your code and perform any actions. Once your script is run on that bar, the script then loads the next historical bar and again executes your code. This process is repeated in historical sequence through all bars.

                    With that in mind, if you have a code that accesses a prior bar you need to account for that in your script. For example, if your code has something like if (High[3] > High[2]), when the first bar is loaded in the script, it will fail with that indexing error because with the first bar there is no bar 2 or 3 ago at that point. So you need to review your code and determine how many bars ago is the longest and then use a check of the CurrentBar (system bar counter) to make sure the script has loaded x number of bars before executing your code. X is again the number of bars to have the script load before executing your code. Typically in the OnBarUpdate() you would add:
                    if (CurrenBar < 20) return; // do not process below this line until 20 bars 20 is just an example, you may need a smaller or larger value.

                    Reference: https://ninjatrader.com/support/help...currentbar.htm

                    Paul H.NinjaTrader Customer Service

                    Comment


                      #11
                      Hello NinjaTrader_PaulH and many thanks for the very clear explanation, I finally get it! In summary, the check serves as a skipping measure of the oldest bars (the leftmost bars or the oldest bars).
                      In clear it means simply "skip the X few oldest bars" and only start executing from the/a bar that has enough prior bars required by the script logic minimum number of bars back. You explained it better than my paraphrase.
                      I didn't know it worked that way. Thank you very much.

                      I've added the check and the Log error is gone.

                      But I got a new one:
                      16/09/2021 21:23:21 Default Indicator 'GRTMultiLines': Error on calling 'OnStateChange' method: Index was outside the bounds of the array.
                      I added the 60 minute Data Series in
                      else if (State == State.Configure)
                      {
                      AddDataSeries(BarsPeriodType.Minute, 60);
                      }

                      and set the MidPoint variable as MidPoint = CurrentDayOHL(BarsArray[1]).CurrentOpen[0];

                      I've read the Multi Time Frame reference shared by NinjaTrader_Jim and some other posts about AddDataSeries. I don't understand the error "Index was outside the bounds of the array." It says in BarsArray documentation that the BarsArray[1] references the secondary time frame. And the secondary time frame is the AddDataSeries(BarsPeriodType.Minute, 60); in my example (there are no other data series), as the BarsArray[0] is the primary time frame. What index is meant to be outside the bounds of the array? I'm not sure the CurrentDayOHL indicator is appropriate for the 60 minute added data series, but I don't know what else to use if it's not the right one. I simply need the open of the current 60 minute bar to make the indicator dynamic so not to have to constantly update the Midpoint value manually.

                      Comment


                        #12
                        Hello PaulMohn,

                        Thank you for your reply.

                        If you're adding a secondary bars series, this will not process until after the primary series. Try adding a check to the top of OnBarUpdate that there is at least one bar in the secondary series for you to get the Current Day OHL from:

                        if (CurrentBars[1] < 1) return;

                        Please let us know if we may be of further assistance to you.
                        Kate W.NinjaTrader Customer Service

                        Comment


                          #13
                          Hello NinjaTrader_Kate and thank you for the check recommandation.

                          I've added it but the error persists:
                          17/09/2021 16:32:01 Default Indicator 'GRTMultiLines': Error on calling 'OnStateChange' method: Index was outside the bounds of the array.

                          I'm not sure about the MidPoint = CurrentDayOHL(BarsArray[1]).CurrentOpen[0];

                          I put the updated script in attachement.
                          Attached Files

                          Comment


                            #14
                            Hello PaulMohn,

                            Thank you for your reply.

                            You're getting the error because of where you're assigning the midpoint variable value. You're assigning this in State.SetDefaults - at that point, data has not yet been loaded and indicators calculated, so CurrentDayOHL(BarsArray[1]).CurrentOpen[0] does not have a value.

                            I would recommend making Midpoint a regular variable instead of a user input if you're going to assign it a value you don't want the user to be able to change. To do so, you can remove this section from #region Properties:

                            Code:
                            [NinjaScriptProperty]
                            [Range(0, double.MaxValue)]
                            [Display(Name="MidPoint", Description="Midpoint price of lines to be drawn. Lines will be drawn above && below this price.", Order=2, GroupName="Parameters")]
                            public double MidPoint
                            { get; set; }
                            Then instantiate MidPoint as a double variable at the top of the script, and also create a bool variable so we can only set the value of MidPoint once, when the script first starts up:

                            Code:
                            public class GRTMultiLines : Indicator
                            {
                            
                            private double MidPoint;
                            private bool InitialMidPointValueSet = false;
                            
                            protected override void OnStateChange()
                            {
                            Finally, assign the value of MidPoint in OnBarUpdate. Since we want that to stay the same and not change throughout the script, we can use our bool we created to check that we haven't assigned it already:

                            Code:
                            protected override void OnBarUpdate()
                            {
                            //if (CurrentBar < 10) return;
                            if (CurrentBars[1] < 1) return;
                            
                            if (InitialMidPointValueSet == false)
                            {
                            MidPoint = CurrentDayOHL(BarsArray[1]).CurrentOpen[0];
                            InitialMidPointValueSet = true;
                            }
                            Note, if you want to update the midpoint each day, you could reset the InitialMidPointValueSet to false when it's the first bar of a new session:

                            Code:
                            protected override void OnBarUpdate()
                            {
                            //if (CurrentBar < 10) return;
                            if (CurrentBars[1] < 1) return;
                            
                            if(Bars.IsFirstBarOfSession)
                            {
                            InitialMidPointSet = false;
                            }
                            
                            if (InitialMidPointValueSet == false)
                            {
                            MidPoint = CurrentDayOHL(BarsArray[1]).CurrentOpen[0];
                            InitialMidPointValueSet = true;
                            }
                            Please let us know if we may be of further assistance to you.
                            Last edited by NinjaTrader_Kate; 09-17-2021, 08:58 AM.
                            Kate W.NinjaTrader Customer Service

                            Comment


                              #15
                              Hello NinjaTrader_Kate and many tanks for the awesome assistance, I couldn't have figured it without your help, much appreciated. Now it seems to work fine. A screenshot below.
                              Just a last question about how the midpoint value updates. I thought setting it to CurrentDayOHL(BarsArray[1]).CurrentOpen[0]; with the AddDataSeries(BarsPeriodType.Minute, 60); would make it update every new hour by taking the new hour candle's Open as midpoint. For example, the current hourly candle Open Price of ES is 4430.50, then the plots would be set around this value, and so on every hour. But it seems it does it from the daily bar's Open value instead. It's mostly fine as is, but it would be accomplished with the hourly update to make sure it follows the recent price across the day and not having to update it manually in case of big swing for example.
                              isn't the CurrentOpen[0] in CurrentDayOHL(BarsArray[1]).CurrentOpen[0]; referencing the Hourly candle and not the daily candle? If not is it possible to reference the hourly candle's open instead of the daily candle Open in another way? I thought it meant "get the Current Day, then, get the current hourly candle, and finally get the open of that hourly candle". That way it would be truly dynamic and we never would have to worry about updating the Midpoint value.

                              I put the updated script in attachment.

                              Finally, once done with it, could you please post the script in the User Apps Share? I took it from there originally from a 2010 script from user zacharydw00.
                              Thank you very much.
                              Attached Files

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by SydniBuck, Today, 12:54 AM
                              0 responses
                              6 views
                              0 likes
                              Last Post SydniBuck  
                              Started by ketostrongbuyno, Yesterday, 11:50 PM
                              0 responses
                              10 views
                              0 likes
                              Last Post ketostrongbuyno  
                              Started by ReinaKutch, Yesterday, 11:08 PM
                              0 responses
                              9 views
                              0 likes
                              Last Post ReinaKutch  
                              Started by JackyThur, Yesterday, 10:51 PM
                              0 responses
                              10 views
                              0 likes
                              Last Post JackyThur  
                              Started by sjeffblack, Yesterday, 01:22 PM
                              2 responses
                              31 views
                              0 likes
                              Last Post sjeffblack  
                              Working...
                              X