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

Loops

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

    Loops

    Hi

    I'm writing an indicator script which draws an arrow on a chart and a calculated number based on the price of that bar when various conditions are true. This all works fine, but what I would now like to do is also display on the chart some info about the candles prior to the one that meets my conditions.

    There are a number of things but I think once I get one done the others will be easy to add on.

    The first is to display in text on the chart, how many previous candles were bullish.

    I was thinking to check the previous candle to see ((IsRising(Close) == true) and then increment a counter until ((IsRising(Close) == false) and then display text on my chart "There are [x] previous bull candles"

    I'm struggling to get the loop to work and would appreciate any help.

    Thanks
    Tim

    Below is my code prior to adding in the loop.

    Code:
    namespace NinjaTrader.NinjaScript.Indicators
    {
        public class indFTB0 : Indicator
        {
            private Double dStoreHigherOpenOrClose;  // variable to store whether price close or open is higher value
            private Double dOpenClosePct; // variable to store % of bar open/close happens
    
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                    Description                                    = @"Indicator to show potential FTB setups";
                    Name                                        = "_indFTB0";
                    Calculate                                    = Calculate.OnBarClose;
                    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;
                    dStoreHigherOpenOrClose                        =0;
                    dOpenClosePct                                =0;
                    ;
                }
                if (BarsInProgress != 0) 
                    return;
    
                if (CurrentBars[0] < 2)
                    return;
    
                else if (State == State.Configure)
                {
                }
            }
    
            protected override void OnBarUpdate()
            {
                //Add your custom indicator logic here.
                     // Set 1
    
                dStoreHigherOpenOrClose = Close[0];
    
                if (Open[0] > Close[0])
                {
                    dStoreHigherOpenOrClose = Open[0];
                }
                // (higher of open/close less low) / (high less low)
    
                dOpenClosePct = ((dStoreHigherOpenOrClose - Low[0]) / (High[0] - Low[0]));
                Print ("dOpenClosePct " + dOpenClosePct.ToString());
                Print ("Open[0] " + Open[0].ToString());
                Print ("Close[0] " + Close[0].ToString());
                Print ("Low[0] " + Low    [0].ToString());
                Print ("High[0] " + High[0].ToString());
    
                if ((High[1] > High[2])
                     && (dOpenClosePct <= 0.5)
                     && (High[0] > High[1])
                     && (Times[0][0].TimeOfDay >= new TimeSpan(6, 0, 0))
                     && (Times[0][0].TimeOfDay <= new TimeSpan(10, 0, 0))
                     && (Close[1] > Close[2]))
    
                {
                    Draw.ArrowDown(this, @"FTB0 " + CurrentBars[0].ToString(), true, 0, (High[0] + (1 * (TickSize * 10))) , Brushes.Orange); //draw a red down arrow over the candle that could be a potential FTB setup
                    //Draw.Text(this, CurrentBars[0].ToString() + @" Text_1", dOpenClosePct.ToString(), 0, (High[0] + (75 * TickSize)) ); //draw the dOpenClosePct value so we can see which <= 50% value for that candle
    
                    string myText = string.Format("{0,0:N2}", (dOpenClosePct + (5 * (TickSize * 10))));
                    Draw.Text(this, CurrentBars[0].ToString() + @" Text_1a",myText , 0, Low[0] - 30 * TickSize);
    
    
                }
            }
        }
    }

    #2
    Hello timcjpfx,

    Thank you for the post.

    It would be helpful to see what you were trying that was not working to better understand what you are trying to do here.
    Also are you referring to a for loop? What kind of loop are you describing here?


    I was thinking to check the previous candle to see ((IsRising(Close) == true) and then increment a counter until ((IsRising(Close) == false) and then display text on my chart "There are [x] previous bull candles"
    IsRising would take a Series specifically, so this would not be the best choice to be used after the bar has been processed (assuming you are referring to using this in a loop). If you are speaking about a for loop, you would instead need to use BarsAgo and the series to achieve comparisons such as:

    Close[0] > Close[1]

    or in a loop, assuming i = 0:

    Close[i] > Close[i + 1]




    I look forward to being of further assistance.



    JesseNinjaTrader Customer Service

    Comment


      #3
      Thanks for the reply Jesse

      I think I'm a bit all over the place with my syntax. Below is as far as I've got with writing the loop with your suggestion but it doesn't compile and I'm struggling to see how to correct it. I'm sure it's very simple but still learning the basics!

      Regards
      Tim

      Code:
      #region Using declarations
      using System;
      using System.Collections.Generic;
      using System.ComponentModel;
      using System.ComponentModel.DataAnnotations;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      using System.Windows;
      using System.Windows.Input;
      using System.Windows.Media;
      using System.Xml.Serialization;
      using NinjaTrader.Cbi;
      using NinjaTrader.Gui;
      using NinjaTrader.Gui.Chart;
      using NinjaTrader.Gui.SuperDom;
      using NinjaTrader.Gui.Tools;
      using NinjaTrader.Data;
      using NinjaTrader.NinjaScript;
      using NinjaTrader.Core.FloatingPoint;
      using NinjaTrader.NinjaScript.DrawingTools;
      #endregion
      
      //This namespace holds Indicators in this folder and is required. Do not change it. 
      namespace NinjaTrader.NinjaScript.Indicators
      {
          public class indFTB1 : Indicator
          {
              private Double dStoreHigherOpenOrClose;  // variable to store whether price close or open is higher value
              private Double dOpenClosePct; // variable to store % of bar open/close happens
              private int x = 0;
              private    bool Loop1 = true;
      
              protected override void OnStateChange()
              {
                  if (State == State.SetDefaults)
                  {
                      Description                                    = @"Indicator to show potential FTB setups";
                      Name                                        = "_indFTB1";
                      Calculate                                    = Calculate.OnBarClose;
                      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;
                      dStoreHigherOpenOrClose                        =0;
                      dOpenClosePct                                =0;
                      ;
                  }
                  if (BarsInProgress != 0) 
                      return;
      
                  if (CurrentBars[0] < 2)
                      return;
      
                  else if (State == State.Configure)
                  {
                  }
              }
      
              protected override void OnBarUpdate()
              {
                  //Add your custom indicator logic here.
                       // Set 1
      
                  dStoreHigherOpenOrClose = Close[0];
      
                  if (Open[0] > Close[0])
                  {
                      dStoreHigherOpenOrClose = Open[0];
                  }
                  // (higher of open/close less low) / (high less low)
      
                  dOpenClosePct = ((dStoreHigherOpenOrClose - Low[0]) / (High[0] - Low[0]));
                  Print ("dOpenClosePct " + dOpenClosePct.ToString());
                  Print ("Open[0] " + Open[0].ToString());
                  Print ("Close[0] " + Close[0].ToString());
                  Print ("Low[0] " + Low    [0].ToString());
                  Print ("High[0] " + High[0].ToString());
      
                  if ((High[1] > High[2])
                       && (dOpenClosePct <= 0.5)
                       && (High[0] > High[1])
                       && (Times[0][0].TimeOfDay >= new TimeSpan(6, 0, 0))
                       && (Times[0][0].TimeOfDay <= new TimeSpan(10, 0, 0))
                       && (Close[1] > Close[2]))
      
                  {
      
                          do
      
                          {
      
                              if ((Close[x] > Close[x + 1] 
                              {
                                  x = x + 1;
                              }
                              else if
                              {
                                  Loop1 = false;
                              }
      
                          while (Loop1 = true)
      
                          }
                      Draw.ArrowDown(this, @"FTB0 " + CurrentBars[0].ToString(), true, 0, (High[0] + (1 * (TickSize * 10))) , Brushes.Orange); //draw a red down arrow over the candle that could be a potential FTB setup
      
                      string myText = string.Format("{0,0:N2}", (dOpenClosePct + (5 * (TickSize * 10))));
                      Draw.Text(this, CurrentBars[0].ToString() + @" Text_1a",myText , 0, Low[0] - 30 * TickSize);
      
                      string myText2 = ("There are " + x + "previous bull candles");
                      draw.text(this, CurrentBars[0].ToString() + @" Text_1b",myText2 , 3, High[3] - 50 * TickSize);
                  }
              }
          }
      }
      
      #region NinjaScript generated code. Neither change nor remove.
      
      namespace NinjaTrader.NinjaScript.Indicators
      {
          public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
          {
              private indFTB1[] cacheindFTB1;
              public indFTB1 indFTB1()
              {
                  return indFTB1(Input);
              }
      
              public indFTB1 indFTB1(ISeries<double> input)
              {
                  if (cacheindFTB1 != null)
                      for (int idx = 0; idx < cacheindFTB1.Length; idx++)
                          if (cacheindFTB1[idx] != null &&  cacheindFTB1[idx].EqualsInput(input))
                              return cacheindFTB1[idx];
                  return CacheIndicator<indFTB1>(new indFTB1(), input, ref cacheindFTB1);
              }
          }
      }
      
      namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
      {
          public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
          {
              public Indicators.indFTB1 indFTB1()
              {
                  return indicator.indFTB1(Input);
              }
      
              public Indicators.indFTB1 indFTB1(ISeries<double> input )
              {
                  return indicator.indFTB1(input);
              }
          }
      }
      
      namespace NinjaTrader.NinjaScript.Strategies
      {
          public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
          {
              public Indicators.indFTB1 indFTB1()
              {
                  return indicator.indFTB1(Input);
              }
      
              public Indicators.indFTB1 indFTB1(ISeries<double> input )
              {
                  return indicator.indFTB1(input);
              }
          }
      }
      
      #endregion

      Comment


        #4
        Hello timcjpfx,

        Thank you for providing more context.

        I see you are using a while loop, this generally would not be suggest in NinjaScript due to the possibility of a never ending loop. For this type of use case, you would likely want to use a finite for loop, or use a specific lookback period such as 20 bars to prevent infinite loops. In case of an infinite loop, your script will likely completely stop processing.

        A for loop could be used very similar to what you have now:

        Code:
        for(int i = 0; i < 10; i++)
        {
            if(Close[i] > Close[i + 1])
            {
        
            }
        }

        In what you have provided there are a few mistakes in the syntax used which is the reason for the compile error.

        One item is that you are missing a few ) ) from this statement:
        if ((Close[x] > Close[x + 1]

        else if by its self is not valid, you can use either just else or else if with a condition like:

        Code:
        else 
        {
        }
        else if(Close[0] > Open[0])
        {
        }
        The structure of the do/while was also incorrect, however I believe using a different type of loop would be a better direction to take here.

        For this type of question, I would also suggest looking at external C# resources as loops are a part of C# not NinjaScript. There are some samples of using loops in the following public C# tutorial page: https://www.tutorialsteacher.com/csharp/csharp-for-loop


        I look forward to being of further assistance.
        JesseNinjaTrader Customer Service

        Comment


          #5
          Thanks again Jesse, that seems to be clearer.

          I've managed to compile but it doesn't run. On the output it says "Error on calling 'OnBarUpdate' method on bar 0: 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 played with the
          Code:
          if (CurrentBars[0] < 25)
                          return;
          But that didn't seem to make a difference....?

          Here is updated code:

          Code:
          #region Using declarations
          using System;
          using System.Collections.Generic;
          using System.ComponentModel;
          using System.ComponentModel.DataAnnotations;
          using System.Linq;
          using System.Text;
          using System.Threading.Tasks;
          using System.Windows;
          using System.Windows.Input;
          using System.Windows.Media;
          using System.Xml.Serialization;
          using NinjaTrader.Cbi;
          using NinjaTrader.Gui;
          using NinjaTrader.Gui.Chart;
          using NinjaTrader.Gui.SuperDom;
          using NinjaTrader.Gui.Tools;
          using NinjaTrader.Data;
          using NinjaTrader.NinjaScript;
          using NinjaTrader.Core.FloatingPoint;
          using NinjaTrader.NinjaScript.DrawingTools;
          #endregion
          
          //This namespace holds Indicators in this folder and is required. Do not change it. 
          namespace NinjaTrader.NinjaScript.Indicators
          {
              public class indFTB1 : Indicator
              {
                  private Double dStoreHigherOpenOrClose;  // variable to store whether price close or open is higher value
                  private Double dOpenClosePct; // variable to store % of bar open/close happens
                  private int x = 0;
                  private    bool Loop1 = true;
          
                  protected override void OnStateChange()
                  {
                      if (State == State.SetDefaults)
                      {
                          Description                                    = @"Indicator to show potential FTB setups";
                          Name                                        = "_indFTB1";
                          Calculate                                    = Calculate.OnBarClose;
                          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;
                          dStoreHigherOpenOrClose                        =0;
                          dOpenClosePct                                =0;
                          ;
                      }
                      if (BarsInProgress != 0) 
                          return;
          
                      if (CurrentBars[0] < 25)
                          return;
          
                      else if (State == State.Configure)
                      {
                      }
                  }
          
                  protected override void OnBarUpdate()
                  {
                      //Add your custom indicator logic here.
                           // Set 1
          
                      dStoreHigherOpenOrClose = Close[0];
          
                      if (Open[0] > Close[0])
                      {
                          dStoreHigherOpenOrClose = Open[0];
                      }
                      // (higher of open/close less low) / (high less low)
          
                      dOpenClosePct = ((dStoreHigherOpenOrClose - Low[0]) / (High[0] - Low[0]));
                      Print ("dOpenClosePct " + dOpenClosePct.ToString());
                      Print ("Open[0] " + Open[0].ToString());
                      Print ("Close[0] " + Close[0].ToString());
                      Print ("Low[0] " + Low    [0].ToString());
                      Print ("High[0] " + High[0].ToString());
          
                      if ((High[1] > High[2])
                           && (dOpenClosePct <= 0.5)
                           && (High[0] > High[1])
                           && (Times[0][0].TimeOfDay >= new TimeSpan(6, 0, 0))
                           && (Times[0][0].TimeOfDay <= new TimeSpan(10, 0, 0))
                           && (Close[1] > Close[2]))
          
                      {
          
                      for(int i = 0; i < 5; i++)
                      {
                          if(Close[i] > Close[i + 1])
                          {
                              x = x + 1;
                          }
                      }
                          Draw.ArrowDown(this, @"FTB0 " + CurrentBars[0].ToString(), true, 0, (High[0] + (1 * (TickSize * 10))) , Brushes.Orange); //draw a red down arrow over the candle that could be a potential FTB setup
          
                          string myText = string.Format("{0,0:N2}", (dOpenClosePct + (5 * (TickSize * 10))));
                          Draw.Text(this, CurrentBars[0].ToString() + @" Text_1a",myText , 0, Low[0] - 30 * TickSize);
          
                          string myText2 = ("There are " + x + "previous bull candles");
                          Draw.Text(this, CurrentBars[0].ToString() + @" Text_1b",myText2 , 3, High[3] - 50 * TickSize);
                      }
                  }
              }
          }
          
          #region NinjaScript generated code. Neither change nor remove.
          
          namespace NinjaTrader.NinjaScript.Indicators
          {
              public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
              {
                  private indFTB1[] cacheindFTB1;
                  public indFTB1 indFTB1()
                  {
                      return indFTB1(Input);
                  }
          
                  public indFTB1 indFTB1(ISeries<double> input)
                  {
                      if (cacheindFTB1 != null)
                          for (int idx = 0; idx < cacheindFTB1.Length; idx++)
                              if (cacheindFTB1[idx] != null &&  cacheindFTB1[idx].EqualsInput(input))
                                  return cacheindFTB1[idx];
                      return CacheIndicator<indFTB1>(new indFTB1(), input, ref cacheindFTB1);
                  }
              }
          }
          
          namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
          {
              public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
              {
                  public Indicators.indFTB1 indFTB1()
                  {
                      return indicator.indFTB1(Input);
                  }
          
                  public Indicators.indFTB1 indFTB1(ISeries<double> input )
                  {
                      return indicator.indFTB1(input);
                  }
              }
          }
          
          namespace NinjaTrader.NinjaScript.Strategies
          {
              public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
              {
                  public Indicators.indFTB1 indFTB1()
                  {
                      return indicator.indFTB1(Input);
                  }
          
                  public Indicators.indFTB1 indFTB1(ISeries<double> input )
                  {
                      return indicator.indFTB1(input);
                  }
              }
          }
          
          #endregion
          Appreciate your continued help.

          Regards
          Tim

          Comment


            #6
            Hello timcjpfx,

            Thank you for the reply.

            That is a step in the right direction, now that you have moved past the compile error you have run into a runtime error. This error is specifically relating to using a BarsAgo when not enough data is present. With the loop that is easily possible but this can also be seen just by using Close[1] on bar 0.

            You can correct this by adding a check in OnBarUpdate like the following with the maximum BarsAgo you use:

            Code:
                protected override void OnBarUpdate()
                    {
                        if(CurrentBar < 10) return;
            5 because you used 5 BarsAgo in your loop.

            I look forward to being of further assistance.
            JesseNinjaTrader Customer Service

            Comment


              #7
              Hi Jesse

              Your last message confused me because in my last message I mentioned I'm already using that which was included in the code I sent over. Have I not used it correctly?

              Thanks
              Tim

              Comment


                #8
                Hello timcjpfx,

                I had made this comment because it appeared that this was not in your syntax, it actually is but it is not in a valid location which is why I missed it. OnStateChange cannot be used for processing bar data, you need to move this logic to OnBarUpdate as shown in the sample I provided.

                Please let me know if I may be of additional assistance.
                JesseNinjaTrader Customer Service

                Comment

                Latest Posts

                Collapse

                Topics Statistics Last Post
                Started by algospoke, Yesterday, 06:40 PM
                2 responses
                19 views
                0 likes
                Last Post algospoke  
                Started by ghoul, Today, 06:02 PM
                3 responses
                14 views
                0 likes
                Last Post NinjaTrader_Manfred  
                Started by jeronymite, 04-12-2024, 04:26 PM
                3 responses
                44 views
                0 likes
                Last Post jeronymite  
                Started by Barry Milan, Yesterday, 10:35 PM
                7 responses
                20 views
                0 likes
                Last Post NinjaTrader_Manfred  
                Started by AttiM, 02-14-2024, 05:20 PM
                10 responses
                180 views
                0 likes
                Last Post jeronymite  
                Working...
                X