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

for loop barIndex of a for loop

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

    for loop barIndex of a for loop

    Hello,

    I would like to know how its possible to for loop the for loop of another bar index?

    HTML Code:
    for(int Period = 0; Period <= CurrentBar;barIndex++)
    {
    for(int barIndex = Period; barIndex <= CurrentBar;barIndex++)
                {
    If i do that only the last number will be tested and not all the Periods.

    If there is 100 bar only Period 100 is looped not Period 1, 2, 3, etc.

    Ty

    #2
    Hello frankduc,

    Thank you for your note.

    Let's say we currently have 100 bars on the chart. Period would start at 0, Current bar would be 99, but I have no indication of what the value of barIndex is, nor are we using it in the comparison:

    Code:
    for(int Period = 0; Period <= CurrentBar;barIndex++)
    The upshot of this is that unless something is incrementing the period value, period will remain 0 and this outer loop would run indefinitely.

    You'd need to increment Period and not barIndex in that line for it to ever reach the terminal point of the loop. So let's say we change that to Period:

    Code:
    for(int Period = 0; Period <= CurrentBar;Period++)
    {
    for(int barIndex = Period; barIndex <= CurrentBar;barIndex++)
    {
    }
    }
    Now here's what will occur. At start, Period is 0, and CurrentBar is 99. We enter the first loop and come to the second loop for the first time. This loop barPeriod = Period, which, right now is 0. Current bar is still 99, so we now enter this loop, and execute that for each bar in the period, so we run through 100 times incrementing barIndex each time, before we exit the inner loop and go back to finish the first go round of the outer loop. Period gets incremented, and we're still below currentBar of 99, so we re-enter the second loop. This time, since Period is now 1, barIndex is reset to 1. That is still below 99, so we execute the loop. It runs another 99 times, incrementing barIndex each time before sending us back to the outer loop for a third time. Period is incremented again, so it's now 2. We go back into the inner loop, which this time runs 98 times.

    You can probably see where this is going. On the final pass through both loops, Period would be 99, so the inner loop would only execute one time.

    Now that we know what the code you have here does, we can address what you're attempting to accomplish.
    • What is the purpose in looping through the same bars essentially an exponential number of times?
    • Are you saving values to a dataseries with each iteration?
    • What is the expected behavior?
    Thanks in advance; I look forward to assisting you further.






    Kate W.NinjaTrader Customer Service

    Comment


      #3
      Kate,

      I created a cumulative moving average and i am trying to run several times the moving average on the chart. Have a CMA for each period of the chart like we can see in the RMMA. I tried several solutions but no luck, i dont understand how to solve the problem. I tried by modifying the RMMA but i get error messages. But it would be more practical to create multiple cma's in OnRender.

      HTML Code:
      for(int barIndex = Period; barIndex <= CurrentBar; barIndex++)
                  {
                      closePrice = Bars.GetClose(barIndex);
                      volumes = Bars.GetVolume(barIndex);
      
                      clovol = closePrice * volumes; 
      
                      sum1 += clovol++;
                      sum2 += volumes++;
      
      
                  cma = sum1 / sum2;
      If there is 100 bars in the chart than i want to create 100 cma's I dont need the addplot, i dont want to see the cma in the chart i just want the result in the output Window.

      Ty

      Comment


        #4
        Hello frankduc,

        Thank you for your reply.

        If you are not rendering anything you should not be calculating these values in OnRender. Let's look at the RMMA for NinjaTrader 8 that's available on our User App Share here:

        This is a conversion of the NT7 indicator RMMA ver 2 by member xTrader1 Description (From NT7): This is an implementation of Rainbow Multiple Moving averages . It is much more flexible than an original, posted here a few years ago. It creates automatically a number of plots and their colors, according to input parameters. [&#8230;]


        If you take a look at the code for this, we can see that a) they are doing all of the calculations in OnBarUpdate, so we can use the bar indexing.

        Code:
        protected override void OnBarUpdate()
                {
                    if (CurrentBar < 10) 
                        return;
        
                    int count = 0;
                    for (int i = LowPeriod; i <= HighPeriod; i += StepAverage)
                    {
                        switch (MaToUse)
                        {
                            case MultiMA1types.DEMA:
                                Values[count][0] = DEMA(i)[0];
                                break;
        
                            case MultiMA1types.EMA:
                                Values[count][0] = EMA(i)[0];
                                break;    
        
                            case MultiMA1types.HMA:
                                Values[count][0] = HMA(i)[0];
                                break;    
        
                            case MultiMA1types.SMA:
                                Values[count][0] = SMA(i)[0];
                                break;    
        
                            case MultiMA1types.TEMA:
                                Values[count][0] = TEMA(i)[0];
                                break;    
        
                            case MultiMA1types.TMA:
                                Values[count][0] = TMA(i)[0];
                                break;    
        
                            case MultiMA1types.VWMA:
                                Values[count][0] = VWMA(i)[0];
                                break;    
        
                            case MultiMA1types.WMA:
                                Values[count][0]  = WMA(i)[0];
                                break;
        
                            case MultiMA1types.ZLEMA:
                                Values[count][0] = ZLEMA(i)[0];
                                break;    
        
                            default:
                                Values[count][0] = EMA(i)[0];
                                break;                    
                        }
        
                        count++;
                    }        
                }
        Let's simplify that a little so we can better see what they're up to. In our case, we're not giving the option for using different indicators, so let's strip out the switch:

        Code:
                protected override void OnBarUpdate()
                {
                    if (CurrentBar < 10) 
                        return;
        
                    int count = 0;
                    for (int i = LowPeriod; i <= HighPeriod; i += StepAverage)
                    {
                        Values[count][0] = EMA(i)[0];                
                        count++;
                    }        
                }
        Here we can see that we start at our low index, and we increment to our high index in our loop. We've also got a second incrementing variable, count. This keeps track of which plot we're assigning the current value to.

        So, how can we use this to achieve what you're looking to do?

        I've attached an example of what I believe you're trying to achieve to this post, created by modifying the RMMA script. Here's the code:

        Code:
            public class aHundredCMA : Indicator
            {
        
                protected override void OnStateChange()
                {
                    if (State == State.SetDefaults)
                    {
                        Description                                    = @" Indicator based on Rainbow Multiple Moving Averages";
                        Name                                        = "aHundredCMA";
                        Calculate                                    = Calculate.OnBarClose;
                        IsOverlay                                    = false;
                        DisplayInDataBox                            = true;
                        DrawOnPricePanel                            = true;
                        DrawHorizontalGridLines                        = true;
                        DrawVerticalGridLines                        = true;
                        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;
                        Period                                    = 100;
        
                    }
                    else if (State == State.Configure)
                    {
        
                        for (int i = 0; i <Period; i++)
                        {
                            AddPlot(Brushes.Aqua, "MyPlot"+i);
                        }    
                    }
        
                }
        
                protected override void OnBarUpdate()
                {
                    if (CurrentBar < Period)
                        return;
        
                    int count = 0;
                    double sum1 = 0;
                    double sum2 = 0;
                    double cma = 0;
                    Print("***** Bar " + CurrentBar + " CMA Values: *****");
                    for (int i = Period-1; i >= 0; i--)
                    {
        
                        sum1 += Close[i];
                        sum2 += Volume[i];
        
                        cma = sum1 / sum2;
        
                        Values[count][0] = cma;
                        Print("Bar " + count + " of Period CMA value: " + cma);
                        count++; 
        
        
                    }        
                }
        
                #region Properties
                [NinjaScriptProperty]
                [Range(2, int.MaxValue)]
                [Display(Name="Period", Description="How many Bars Back to create CMAs", Order=1, GroupName="Parameters")]
                public int Period
                { get; set; }
                #endregion
        The first point of note is that we are dynamically adding plots in State == State.Configure, based on what was in the original RMMA indicator. We cycle through a loop and add a plot for each of our 100 bars in the period.

        Now that we have our 100 plots we can do something with them in OnBarUpdate. For ease of use, I have this indicator so it requires 100 bars of data on the chart prior to it beginning calculations. Once we reach that 100 bars of data on the chart, it will begin to go through the rest of OnBarUpdate. What we're doing here is looping through, starting at the earliest bar on our charts. For each bar, we get the close price of the bar and add that to our previous value for sum1, and we get the volume for the bar and add it to the previous volumes, then divide those two to get the CMA. Based on which bar we are on in our loop, we then assign it to one of our plots. We use the separate count variable instead of i when we are assigning the values since i is counting down to 0, but we need to assign to our plots in ascending order.

        This indicator will also print the calculated values for each plot on each bar to the NinjaScript Output window if one is open.

        I'd take a look at this and run it on a chart - it may make some of your questions regarding loops and bar indexes more clear.

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

        The NinjaTrader Ecosystem website is for educational and informational purposes only and should not be considered a solicitation to buy or sell a futures contract or make any other type of investment decision. The add-ons listed on this website are not to be considered a recommendation and it is the reader's responsibility to evaluate any product, service, or company. NinjaTrader Ecosystem LLC is not responsible for the accuracy or content of any product, service or company linked to on this website.
        Attached Files
        Kate W.NinjaTrader Customer Service

        Comment


          #5
          Kate,

          We are not there yet. Thanks for your example i learned a few things but the result is not what i was expecting.

          I tried to modify the RMMA to get what i want by introducing in public enum MultiMA1types my CMA : CMA01
          Than i added :

          Code:
          case MultiMA1types.CMA01:
                Values[count][0] = CMA01(i)[0];
                break;
          in the switch statement.

          My CMA01 is coded in OBU:

          Code:
          int allbar = 0;
               for(int i = ChartBars.FromIndex; i < ChartBars.ToIndex; i++)
                                   {
                 allbar = i;
          
                }  
          
          
               if (CurrentBar < (allbar-Period))
                return;
          
               double volus = Volume[0];
          
                   double price = Input[0];
          
          
          
             double privol = volus * price;
          
              sum01 += privol;
              sum02 += volus;
          
              cma0 = sum01/sum02;
          
          
               Value[0] = cma0;
          If i try the modify RMMA i get 2 errors:

          Indicator 'CMA01': Error on calling 'OnBarUpdate' method on bar 0: Object reference not set to an instance of an object.
          Indicator 'RMMA': Error on calling 'OnBarUpdate' method on bar 11: 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.

          The problem with your example is that you are indexing the volume and the prices when in fact its the period that need indexing. Well the way i see it.
          I dont understand why in the RMMA the other moving average like sma, ema works but not my cma. What's the difference?

          As you can see in the chart i provided this is how it should look why a period of 1178 and average step of aprox 50. Of course i just created 3 cma01 manually.

          Frank
          TY
          Attached Files

          Comment


            #6
            Kate,

            I am almost there. Apparently there is something i am doing wrong because cma's dont start at the right place.

            Code:
            int allbar = 0;
                 for(int i = ChartBars.FromIndex; i < ChartBars.ToIndex; i++)
                                     {
                   allbar = i;
            
                  }   
            
               
               if (CurrentBar < (allbar-Period))
                return;
            
               int count = 0;
               double sum01 = 0;
               double sum02 = 0;
               double cma = 0;
               Print("***** Bar " + CurrentBar + " CMA Values: *****");
               for (int i = Period-1; i >= 0; i--)
               {
            
                 double volus = Volume[i];
                double price = Input[i];
                double privol = volus * price;
            
                sum01 += privol;
                sum02 += volus;
            
                cma = sum01 / sum02;
            
                Values[count][0] = cma;
                Print("Bar " + count + " of Period CMA value: " + cma);
                count++;
            Many thanks again for your help. Its been months i struggle with that.
            Attached Files

            Comment


              #7
              Hello frankduc,

              Thank you for your reply.

              I am not sure what you mean by "the CMAs don't start in the right place". You cannot start them at the first bar because you don't have 100 prior bars of data to calculate the CMA on. You will need to have prior data before the point the CMA begins to be calculated.

              Thanks in advance; I look forward to assisting you further.
              Kate W.NinjaTrader Customer Service

              Comment


                #8
                Kate,

                If you look at the chart at post 526, 6# you can see that the lines of the cma in the chart are reversed.

                Something in that for loop:
                for (int i = Period-1; i >= 0; i--)
                the lines at the end should not end up in the middle of nowhere. It should look like the chart on the previous post. 5#

                That barsago, barindex in NT is so complicated to manage, why not just create one or the other. Without the for loop the cma is ok. Once you put the for loop and indexing its all wrong. Like the period are calculated on the reverse.

                Frank
                ty


                Comment


                  #9
                  Hello frankduc,

                  Thank you for your reply.

                  I do not follow what "the lines at the end should not end up in the middle of nowhere" means. Please provide the code you have for what is "working" so I may review, and please clarify.

                  Thanks in advance; I look forward to resolving this for you.
                  Kate W.NinjaTrader Customer Service

                  Comment


                    #10
                    Kate,

                    I modified the code so it looks more like RMMA:

                    Code:
                    protected override void OnBarUpdate()
                      {
                       int allbar = 0;
                         for(int i = ChartBars.FromIndex; i < ChartBars.ToIndex; i++)
                                             {
                           allbar = i;
                    
                          }   
                    
                       
                       if (CurrentBar < (allbar-LowPeriod))
                        return;
                    
                       int count = 0;
                       double sum01 = 0;
                       double sum02 = 0;
                       double cma = 0;
                       Print("***** Bar " + CurrentBar + " CMA Values: *****");
                       for (int i = LowPeriod; i <= HighPeriod; i += StepAverage)
                       {
                    
                         double volus = Volume[i];
                        double price = Input[i];
                        double privol = volus * price;
                    
                        sum01 += privol;
                        sum02 += volus;
                    
                        cma = sum01 / sum02;
                    
                        Values[count][0] = cma;
                        Print("Bar " + count + " of Period CMA value: " + cma);
                        count++;
                    
                    
                       }
                    As you can see on the chart the blue line are starting at the bottom of the chart. The yellow lines show how the result should look.

                    It seems the problem come's from
                    [CODE]
                    if (CurrentBar < (allbar-LowPeriod))
                    return;
                    [CODE]

                    When creating a single cma like below:

                    Code:
                    {
                        int allbar = 0;
                         for(int i = ChartBars.FromIndex; i < ChartBars.ToIndex; i++)
                                             {
                           allbar = i;
                    
                          }  
                    
                    
                         if (CurrentBar < (allbar-Period))
                          return;
                    
                         double volus = Volume[0];
                             double price = Input[0];
                    
                       double privol = volus * price;
                    
                        sum01 += privol;
                        sum02 += volus;
                    
                        cma0 = sum01/sum02;
                    
                    
                         Value[0] = cma0;
                    
                    
                        }
                    
                    
                    [LEFT][COLOR=#4D4D4D][FONT=Helvetica][/FONT][/COLOR][/LEFT]


                    The cma start at the CurrentBar
                    < (allbar-Period)) and draw the line. But in the case where you try to create more than one cma it seems you need a

                    Code:
                     if (CurrentBar < (allbar-Period))
                    Code:
                    [LEFT][COLOR=#4D4D4D][FONT=Helvetica][SIZE=13px]      return;
                    [/SIZE][/FONT][/COLOR][/LEFT]


                    for each line cma you want to create.

                    But its not possible to index and int so there is no way i can index the if statement. I cant imagine how to solve that issue. In the RMMA the period is indexed,
                    CMA01(i)[0] and in my case the volume and input are indexed but what produces the period is not. That explain why the lines are pictured wrong.

                    In my example the yellow line are period 125,120,103, 69. But the blue lines start with 4 periods and end with 4 periods equal.

                    Thanks
                    Attached Files

                    Comment


                      #11
                      Kate,

                      Here's an update. As you can see on the chart i attached the cma's are not calculated in the right direction.

                      By changing :

                      Code:
                      for (int i = 0; i <= Period-1; i++)
                      Now its calculating in the right direction but every cma are starting at 100.

                      As you can see in the chart with the yellow line the other lines dont fit correctly. The yellow line at 3146,13 is myplot27 this is what the cma looks like at cma 27.

                      As you can see the blue line cma 100 all begin at period 100. While the first 100 should begin at 100, the 99 should start at period 99, etc.

                      If you have any idea…

                      Maybe ill find the answer by myself before the end of the week.

                      thanks
                      Attached Files

                      Comment


                        #12
                        Hello frankduc,

                        We would advise using BarsAgo indexes for your indicator calculation instead of looping over bars with specific indexes.

                        When Calculate is set to OnBarClose, OnBarUpdate will update whenever a new bar is closed. Whenever OnBarUpdate occurs, this would be your opportunity to assign the plot value for the bar that just closed.

                        For example, in the EMA indicator, we have the following code:

                        Code:
                        protected override void OnBarUpdate()
                        {
                            Value[0] = (CurrentBar == 0 ? Input[0] : Input[0] * constant1 + constant2 * Value[1]);
                        }
                        Whenever a new bar forms, the plot associated with the bar that has just closed (Value[0]) is assigned a value multiplying the current Input value by constant1, and adding it to the quantity of constant2 multiplied by the previous indicator value (Value[1]).

                        The indicator uses BarsAgo references for Value[1] reference the previous plot value. Whenever a new bar forms, the code is still looking at the current input value and the previous indicator value to create the calculation. The same approach should be taken to calculate your indicator plots so the references are relevant to the current bar.

                        In your snippet above we see that you are using ChartBars.FromIndex and ChartBars.ToIndex. We have advised you several times not to use these in OnBarUpdate calculations since what is visible on the chart does not have any relevance in OnBarUpdate.

                        I suggest starting with a less complex indicator and using BarsAgo references instead of looping through bars. After you are able to create a simple that uses BarsAgo indexes, it will be easier to create the indicator you are working on.

                        Please let us know if you have any questions.
                        JimNinjaTrader Customer Service

                        Comment


                          #13
                          Hello,

                          I understand your point of view but CurrentBar returns the number of bars in the chart and the way i see it, it returns barIndex. Print CurrentBar and you get a number that goes from left chart to right side of the chart (barIndex).

                          Now my code to calculate the CMA works fine, i did the test with excel this code return the right answer:

                          Code:
                          for(int barsAgo = ChartBars.FromIndex; barsAgo < ChartBars.ToIndex; barsAgo++)
                                                   {
                                 allbar = barsAgo;
                          
                                }   
                          
                             
                             if (CurrentBar < (allbar-Period))
                              return;
                          
                             int count = 0;
                             double sum01 = 0;
                             double sum02 = 0;
                             double cma = 0;
                          
                             {
                          
                               double volus = Volume[0];
                              double price = Input[0];
                              double privol = volus * price;
                          
                              sum01 += privol;
                              sum02 += volus;
                          
                              cma = sum01 / sum02;
                          
                              Values[0] = cma;
                          
                          
                          }
                          Its true i have been warn not to use a for loop with
                          ChartBars.FromIndex and ChartBars.ToIndex in OBU many times on the forum. But i dont see how its possible to make the code use barsAgo instead of barIndex. Some how i have to substract all the bars in the chart less the period to return the position in barsAgo.

                          That is probably the reason why i cant obtain the result i am seeking, somehow barsAgo and barIndex are in conflict in the code.

                          Code:
                          for (int i = 0; i <= Period-1; i++)
                          For looping for (int i =
                          Period-1
                          ; i >= 0; i--) will return barsAgo when CurrentBar returns barIndex its somehow conflicting. No?

                          I agree in the EMA it makes the code more efficient and small but i dont get where you see a barsAgo.

                          Thanks

                          Comment


                            #14
                            Hello frankduc,

                            Thank you for your reply.

                            You can loop through bars either forward or backward using the Bars Ago indexes. Bars ago, when we speak of it, means starting at the currently forming bar on the chart.

                            If this is confusing, it may be useful to open a data box, then right click on it and select to view both Bars Ago and Bar Index. Then you can hover over any bar on the chart and see its bars ago index as well as its bar index.

                            I've attached a quick indicator that shows how you can always find the first and last bar on the chart using current bar and bars ago indexes. This will print the Current bar ( the bar index counting up from 0), then print the Close price for the current first and last bars on the chart to a NinjaScript Output window. You should fully understand how this works and focus on using this method instead of references to ChartBars.FromIndex and ChartBars.ToIndex. I concur with Jim that you should focus on starting with a less complex indicator and using BarsAgo references instead of looping through bars. After you are able to create a simple that uses BarsAgo indexes, I agree it will be easier to create the indicator you are working on.

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

                            Comment


                              #15
                              Kate,

                              First of all, thank you for your file example and explanation.

                              Now even if the for loop to create allbar variable is not good practice it is not the culprit. If it was i would just remove allbar and use Period and my cma's would appear right in the chart and in calculation. Unfortunately, it is not the case something i am missing is preventing the creation of those cma's correctly. I cant find what is at fault and not understanding the problem stop me from solving it.

                              Is it possible to do the indexing in OnRender? I know you will say it is not a good idea. But for curiosity i tried to index :

                              Code:
                              double closePrice[i] = Bars.GetClose(barIndex);
                              
                              or
                              
                              [LEFT][COLOR=#4D4D4D][FONT=Helvetica][SIZE=13px]double closePrice= Bars.GetClose(barIndex)[i] ;[/SIZE][/FONT][/COLOR][/LEFT]
                              and it is not working. Is there another way to do that?

                              Thank you
                              Frank

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by Kaledus, Today, 01:29 PM
                              1 response
                              7 views
                              0 likes
                              Last Post NinjaTrader_Jesse  
                              Started by frankthearm, Yesterday, 09:08 AM
                              13 responses
                              45 views
                              0 likes
                              Last Post frankthearm  
                              Started by PaulMohn, Today, 12:36 PM
                              2 responses
                              16 views
                              0 likes
                              Last Post PaulMohn  
                              Started by Conceptzx, 10-11-2022, 06:38 AM
                              2 responses
                              55 views
                              0 likes
                              Last Post PhillT
                              by PhillT
                               
                              Started by yertle, Yesterday, 08:38 AM
                              8 responses
                              37 views
                              0 likes
                              Last Post ryjoga
                              by ryjoga
                               
                              Working...
                              X