Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

access a list from OBU

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

    access a list from OBU

    Hello,

    This might be considered as an c# issue rather than Nt but by any luck.

    I get an error message saying :

    NinjaScript File Error Code Line Column
    NEWSDBA.cs 'NinjaTrader.NinjaScript.Indicators.Indicator.NEWS DBA (int, int)' is a 'method', which is not valid in the given context CS0119 78 34

    I want to access my list from OnRender to OnBarUpdate. The base.OnRender methods work fine but cant access the list outside that class unless declared in public class.
    Any inputs on how to deal with that NT error?
    Thank you
    1. public class NEWSDBA : Indicator
    2. {
    3. public List<double> listm { get; set; }
    4. protected override void OnBarUpdate()
    5. {
    6. NEWSDBA newsdba = new NEWSDBA();
    7. foreach(var item in NEWSDBA.listm)
    8. {
    9. Value[0] = item;
    10. }
    11. }
    12. }

    #2
    Hello frankduc,

    Thanks for your post.

    This is a C# syntax error/compile error, not a NinjaTrader error.

    In your snippet "newsdba" is of type "NEWSDBA" which is the same class as the indicator you are creating. You cannot create an indicator of the same type within that same indicator. This is the same case for any class.

    If it is not clear on the syntax you are writing, we suggest taking a step back and to consider C# educational materials and to also consider programming classes to get the fundamentals of C# down before creating custom indicators with NinjaScript.

    I want to access my list from OnRender to OnBarUpdate. The base.OnRender methods work fine but cant access the list outside that class unless declared in public class.
    If I understand correctly, you are wanting to access a list that is populated in OnRender, from OnBarUpdate. We have discussed this serval times in the past that this would not be the way to do things.

    OnRender has to do with what is visible on the chart, and OnBarUpdate has to do with what data gets processed. It makes sense to create a Series<T> and populate it with data in OnBarUpdate to keep track of things that should be drawn and to reference those in OnRender, but it does not make sense to perform calculations in OnRender and feed them to OnBarUpdate. If this is what you are attempting, we strongly advise to reconsider your approach. OnRender should only be used for drawing, that's it.

    I have an example for how you can create a public List and access it from another script if it can help, but the above information must be considered to create functional scripts. This is very similar to the SampleBoolSeries indicator and strategy that show how to expose indicator values that are not plots.

    SampleBoolSeries - https://ninjatrader.com/support/help...alues_that.htm

    We look forward to assisting.
    Attached Files

    Comment


      #3
      Jim,

      Well actually the list is in OnRender and i want to access the values of the list in OBU so i can use AddPlot(Brushes.Yellow, "NEWSDBA"); and draw the line in the chart from the data in the list.

      I have been told by the team of NT that i can use base.OnRender(chartControl, chartScale); and than use AddPlot in OBU to retreive the data from the list. Unless i misinterpreted.

      Now i cant use the list values in OBU unless its declared from outside OR. So i am trying to find out a way to do it.
      Actually, a line does appear in the chart but it is the wrong data coming out.

      Thank you

      Comment


        #4
        Hello frankduc,

        Well actually the list is in OnRender and i want to access the values of the list in OBU so i can use AddPlot(Brushes.Yellow, "NEWSDBA"); and draw the line in the chart from the data in the list.
        This is the wrong approach. You should not create anything in OnRender that should be referenced in OnBarUpdate, it just doesn't work like that.

        Please consider this:
        1. OnBarUpdate processes historical data and calculates some values we want to plot or draw. We processed bars 0 to the far right bar on the chart at this point.
        2. We reach realtime processing, and the chart starts rendering. The chart renders the bars visible on the chart, and should only draw what is visible on the chart. (Between ChartBars.FromIndex and ChartBars.ToIndex)
        3. The chart is scrolled and the visible bars change. As the chart scrolls, we get numerous OnRender updates. (This is why OnRender should only perform drawing, and should not perform any calculations on data, and should not feed anything back to OnBarUpdate)

        Even if you are calculating things from bar 0 to the current bar in OnRender (so it does not matter what the visible bars are,) you shouldn't. This would be extremely resource intensive, because what you are calculating is based on data, and does not matter what is visible. Data based calculation work should only happen in OnBarUpdate.

        The above is a necessary fundamental that needs to be understood. It seems we come back to this, and while we do want to be helpful, we cannot if we keep going back to this approach.

        The process should be:
        1. Calculate what I need to model in OnBarUpdate. I should organize my calculations and data so they are tracked in Series<T> objects so I can reference the specific Series<T> values that are between visible bars later in OnRender.
        2. Use OnRender to look loop between visible bars, and draw what I need to draw, and only what I need to draw.

        OnRender should be for drawing ONLY and should only display values that are calculated in OnBarUpdate.

        OnRender and custom rendering with SharpDX work can be very complex. I would very much discourage it for anyone who is struggling with compile errors.

        I have been told by the team of NT that i can use base.OnRender(chartControl, chartScale); and than use AddPlot in OBU to retreive the data from the list. Unless i misinterpreted.
        base.OnRender would be used in OnRender to your plots are visible. Plotting is done in the indicator base class, and if you override OnRender, you will not see any plots unless you call base.OnRender inside of OnRender. AddPlot also would not be called in OnBarUpdate. If someone has told you otherwise, please let me know so I can have a look and make sure our team is presenting accurate information.

        Now i cant use the list values in OBU unless its declared from outside OR. So i am trying to find out a way to do it.
        It sounds like you are having difficulty with variable scope. You can reference publicly available resources on C# to learn more about variable scope, however I must be very clear that the input I am providing in this post is not to be ignored.

        Comment


          #5
          Jim,

          I dont want to complain, you guys do your best to help us in the limit you are imposed by the NT policies, but i feel i get contradictory informations sometimes.

          About base.OR:
          Here's the thread: post 4 its possible i missunderstood what he replied.
          Drawing Addplot in OR e.g - NinjaTrader Support Forum

          I have been told many times in this forum it is not good or possible to use and loop throught ChartBars.FromIndex and ChartBars.ToIndex in OBU. In fact some tech said it is and other tech say its not.

          I tried looping with ChartBars.FromIndex to CurrentBar and other ways but my algo is crashing evey time i transfer calculation from OR to OBU. Its clearly an issue with for looping throught ChartBars.FromIndex and ChartBars.ToIndex in OBU.

          If i want the lowest or highest value in the visible bars of the chart i need to loop from ? to ?. Then if i want to loop back from the lowest value to the past. Well i need to loop from lowvalue to ? ChartBars.FromIndex?

          1. Use OnRender to look loop between visible bars, and draw what I need to draw, and only what I need to draw.
          This is exactly what i did in OR!

          Brandon suggested to use DrawGeometry to draw my line. I just wish i had a good example to reproduce in OR.

          SharpDX ill give you that is not easy to code.

          It sounds like you are having difficulty with variable scope.
          I did ask on many forums how to declare a list outside OR and OBU to access them and other programmers told me to ask NT.

          I will keep investigating and learning about this and soon or later i will find a solution. I always do anyway.

          Thank you

          Comment


            #6
            Hello Frank,

            I think interpretation from post #4 of Brandon's is just a misunderstanding. The takeaway that Brandon is communicating there is that:
            1. To draw standard plots when overriding OnRender, you need to call base.OnRender in OnRender.
            2. Standard plots are still added in OnStateChange under State.SetDefaults or State.Configure
            3. Standard plots still would have their plot values assigned in OnBarUpdate.
            You can reference AddPlot for examples on adding plots and assigning values to a plot.

            AddPlot - https://ninjatrader.com/support/help...t8/addplot.htm

            At the most basic level, plots are just Series<double>'s that are drawn by the indicator's base class. Essentially, Value or Values[] is the Series<double> we populate for a plot's data. The indicator base class then draws those series values by converting the Series<double> values to chart XY coordinates and using SharpDX to draw what we want using those values. (Series<double>'s hold double values for each bar on the chart.)

            This would be the approach for using custom rendering that should be followed. We process data in OnBarUpdate to model our data, and then we draw that data in OnRender. (For example, develop a moving average of price levels, or in other words, a Series of double values that we would eventually want to draw on the chart.) OnBarUpdate should be used to calculate the price levels that should be drawn, OnRender should draw those levels when they are visible (by looping through ChartBars.FromIndex and ChartBars.ToIndex.)

            The main point here is that OnRender is called each time the chart needs to render, and it should only draw what is visible between Chart Bars.FromIndex and ChartBars.ToIndex. OnBarUpdate is called each time there is a data update. We need to think of these as separate concepts as they serve very different purposes.

            ChartBars.FromIndex and ChartBars.ToIndex change with each render pass, and not each bar update. Therefore, it does not make sense to use these in OnBarUpdate.

            Similar to the above, trying to feed OnBarUpdate (the data driven method) something that changes based on visibility of the chart (from OnRender) would also be bad practice and should not be done.

            To answer on using DrawGeometry to draw a line, please have a look at my example here. I essentially recreate plotting behaviors with my own OnRender code. Instead of creating plots in OnStateChange and assigning values to Values[][] like a standard plot, I create Series<double>'s in State.DataLoaded, assign values in OnBarUpdate, then loop through ChartBars.FromIndex and ChartBars.ToIndex in OnRender, and inside that loop I use the Series.GetValueAt to get the Series value at the bar index of that loop. I then convert those to XY coordinates, add them to a list of points, convert those points to a "figure", and then draw the figure using RenderTarget.DrawGeometry.

            The example attached can be ignored if you maintain focus to:
            1. Create plots in OnStateChange
            2. Assign the values that you want to display in OnBarUpdate
            You would not even have to worry about custom rendering. I HIGHLY recommend taking a step back and just making plots and assigning values to the plots in OnBarUpdate. Do not use ChartBars.FromIndex or ChartBars.ToIndex in OnBarUpdate, they would not be used there. Instead. try to model your data (plots) based on OnBarUpdate ONLY and let NinjaTrader draw your plots without overriding OnRender. Take this approach to Keep It Simple and let us know if you have trouble there.

            Any approach that would require feeding information from OnRender to OnBarUpdate would simply not work and you will always hit road blocks trying to get it to work. We wouldn't support it.

            I hope this helps!
            Attached Files
            Last edited by NinjaTrader_Jim; 09-03-2021, 12:54 PM.

            Comment


              #7
              Jim,

              Is it good practice to do it this way:

              Code:
              protected override void OnBarUpdate()
              {
              int tot = ChartBars.ToIndex - ChartBars.FromIndex;
              
              for (int barIndex = 0; barIndex <= tot; barIndex++)
              {
              if (Bars.GetLow(barIndex) < lowPrice0)
              {
              lowPrice0 = Bars.GetLow(barIndex);
              index = barIndex;
              
              
              }
              }
              
              
              Print("tot" + tot);
              Print("lp" + lowPrice0);
              
              double sum = 0;
              for (int barIndex = index; barIndex <= tot; barIndex++)
              {
              
              double vols = Bars.GetVolume(barIndex);
              
              
              sum += vols;
              
              }
              
              
              Print("sum " +sum);
              
              
              }
              Unfortunately i still have an error saying: Indicator 'NEWSDBAobu': 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.

              Cant figure out why it is so complicated to make it work in OBU.

              Frank
              TY

              Comment


                #8
                Hello Frank,

                Please heed my warning from the last post:
                ChartBars.FromIndex and ChartBars.ToIndex change with each render pass, and not each bar update. Therefore, it does not make sense to use these in OnBarUpdate.
                Do not use ChartBars.FromIndex and ChartBars.ToIndex in OnBarUpdate. ChartBars.FromIndex and ChartBars.ToIndex are relative to what is currently visible, and have no relevance in OnBarUpdate.

                Recall that OnBarUpdate starts processing from bar index 0 (the very first bar on the chart, when the chart is scrolled all the way to the left,) and processes bar by bar to CurrentBar, which is the the very last bar on the right, when we have scrolled the chart all the way to the right.

                When working in OnBarUpdate, we would use BarsAgo references. Which are essentially the opposite of bar indexes. For example, Close[0] reflects the close of the bar that OnBarUpdate is currently processing, Close[1] represents the close of the last bar that OnBarUpdate processed.

                Working with Price Series - https://ninjatrader.com/support/help...ice_series.htm

                We also adapted some indicator tutorials to the NinjaTrader 8 Help Guide recently. It will be very beneficial to pause on your venture and complete these tutorials as they will likely help get the OnBarUpdate fundamentals down to help you move forward.

                https://ninjatrader.com/support/help...indicators.htm

                Comment


                  #9
                  Jim,

                  I have been reading this stuff over and over again and i dont think OnBarUpdate is suitable for what i want to do.

                  I replaced ChartBars.FromIndex and ChartBars.ToIndex for Count and barIndex for BarsAgo. Still cant make it work.

                  Code:
                  int tot = Count;
                  
                  for (int barsAgo = 0; barsAgo >= tot; barsAgo++)
                  {
                  if (Low[barsAgo] < lowPrice0)
                  {
                  lowPrice0 = Low[barsAgo];
                  index = barsAgo;
                  }
                  }
                  This return 2147483647, at least with barIndex it retuns the low. I copy paste from OnRender to OnbarUpdate and changed all for loop for barsAgo or barIndex and it wont work.

                  Frank

                  TY

                  Comment


                    #10
                    Apparently the problem is coming from Close.GetValueAt(CurrentBar) its printing the first bar close on the left of the chart instead of the first bar on the right. Recurent problem i dont know how to solve.

                    Comment


                      #11
                      Hello Frank,

                      A plot line will comprise of data points for each bar on the chart. Those data points are assigned to the Values[PlotNumber] Series associated with the plot, and NinjaTrader does all of the work to draw the line.

                      OnBarUpdate is first called for bar 0, then called for bar 1, then called for bar 2 for each bar on the chart, as new bars form. This is where we should assign values to our plot line. Whenever there is a new bar, update the Values[PlotNumber][0] associated with that plot as it will always be the current bar's value in OnBarUpdate.

                      You do not have to use a loop for this. Close[0] will always represent the Close of the current bar that is processing in OnBarUpdate, Close[1] will always represent the Close of the previous bar.

                      Going through the tutorials would be my recommendation to understand BarsAgo references and how you can use them in an indicator. You do not need to use Close.GetValueAt(CurrentBar) as these use bar indexes. Instead, use BarsAgo references as they are demonstrated in the tutorials linked. Completing these tutorials is going to be paramount to understanding how you can build a plot line by updating Values[PlotNumber][0] and get the basics down.

                      I really cannot comment further here outside of reading the AddPlot documentation, going through all of the indicator tutorials, referencing basic indicators like SMA, and abandoning any thought process to update things in OnBarUpdate that are based on OnRender.

                      If we can't move forward from there, I would really be left to suggest having a consultant build your custom scripts, and to return to the tutorials after developing a greater familiarity with programming in C#.

                      Comment


                        #12
                        Jim,

                        Just by doing:

                        private double lowPrice0 = double.MaxValue;

                        Code:
                        if (Low[0] < lowPrice0)
                        {
                        lowPrice0 = Low[0];
                        }
                        It should return the lowest price in the series? I get the wrong answer. I dont get it.

                        TY

                        Comment


                          #13
                          Hello Frank,

                          Please see the video I have linked which tests that code and explains the result:

                          Comment


                            #14
                            Good morning Jim,

                            Thank you for your patience and the video. I have already tried 2 out of 3 of your suggestions before you came with the video. I did try this morning the 3 of them again and its all returning the wrong price or errors such as :

                            1) Value of property 'Period' of NinjaScript 'MIN' is 0 and not in valid range between 1 and 2147483647.
                            2)Indicator 'NEWSDBAobu': Error on calling 'OnBarUpdate' method on bar 0: Object reference not set to an instance of an object.

                            I did try them on a brand new indicator and it is working fine. But i cant make it fit in my indicator. Some concept in OBU i cant grasp seems to prevent me from succeeding.

                            As you probably understand my goal is to get in this example the lowest price of the chart, get its index and than sum the volume or prices from index to a certain point (ChartBars.ToIndex in OR) of course we cant do that in OBU, i get it!

                            What is strange, is that, if i do this:

                            Code:
                            int tot = Bars.Count;
                            
                            for (int barIndex = 0; barIndex <= tot; barIndex++)
                            {
                            if (Bars.GetLow(barIndex) < lowPrice0)
                            {
                            lowPrice0 = Bars.GetLow(barIndex);
                            index = barIndex;
                            }
                            }
                            It will return the lowest price in the chart but Close.GetValueAt(CurrentBar) in my formula wont return the latest price traded. It returns Print() the close price of the first bar at the left side of the chart. Same for Close[0].

                            Frank
                            TY


                            Comment


                              #15
                              Hello Frank,

                              1) Value of property 'Period' of NinjaScript 'MIN' is 0 and not in valid range between 1 and 2147483647.
                              2)Indicator 'NEWSDBAobu': Error on calling 'OnBarUpdate' method on bar 0: Object reference not set to an instance of an object.
                              1) would mean the value given to the Period of MIN is 0. We are using CurrentBar as the period, which increments with each new bar. When the script processes the first bar, bar 0, CurrentBar is 0, and thus the given Period is 0. I use a CurrentBar check to make sure we do not calculate this on the first bar when CurrentBar is less than 1.

                              2) would mean an object on on the line that throws the error is null. You can check the individual items on the line to see which is null, and then see how that object is implemented in a working script to see where you went wrong.

                              As you probably understand my goal is to get in this example the lowest price of the chart, get its index and than sum the volume or prices from index to a certain point (ChartBars.ToIndex in OR) of course we cant do that in OBU, i get it!
                              Ok, so we can point out a few ways to calculate the lowest low. Since OnBarUpdate processes bar by bar from bar 0 and forward, I would suggest tracking when the lowest low changes, and then to mark the index in a private int variable, so we can keep track of when the lowest low changes, and then accumulate the volume from that lowest low bar to the current bar to create our plot line values.

                              I went as far as putting the code together and writing a full script to demonstrate the path, with comments added. I also compare implementations for: 1. Creating a plot line in OnBarUpdate, 2. Drawing a line in OnRender from the bars that are currently visible.

                              We should understand that #1 is a standard plot line, built from the underlying data, and built by assigning values per bar update in OnBarUpdate.

                              We should understand that #2 is not a plot line, but a visual tool, and since it has to do with visible bars, it involves what is seen between ChartBars.FromIndex and ChartBars.ToIndex and uses OnRender, without using OnBarUpdate.

                              We should also note that personalized examples at this level of depth extend beyond the level of support we may normally offer as it affects our ability to assist others. I chose to spend additional time here because you have been stuck for so long, and I want to make sure the concepts described here are understood so we may close this ticket and get you on the right track.

                              I have also recorded a video explaining:

                              Demo - https://drive.google.com/file/d/1cAP...w?usp=drivesdk

                              The example does not draw segmented lines in the OnRender approach (which is based solely on what is visible, using OnRender.) It draws a single line from lowest low to the right most visible bar. You can either use RenderTarget.DrawLine to create additional line segments, or consider tracking different points to make PathGeometry and draw it with RenderTarget.DrawGeometry, like is done in the example in post #2.
                              Attached Files
                              Last edited by NinjaTrader_Jim; 09-08-2021, 08:12 AM.

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by Geovanny Suaza, 02-11-2026, 06:32 PM
                              0 responses
                              579 views
                              0 likes
                              Last Post Geovanny Suaza  
                              Started by Geovanny Suaza, 02-11-2026, 05:51 PM
                              0 responses
                              334 views
                              1 like
                              Last Post Geovanny Suaza  
                              Started by Mindset, 02-09-2026, 11:44 AM
                              0 responses
                              101 views
                              0 likes
                              Last Post Mindset
                              by Mindset
                               
                              Started by Geovanny Suaza, 02-02-2026, 12:30 PM
                              0 responses
                              554 views
                              1 like
                              Last Post Geovanny Suaza  
                              Started by RFrosty, 01-28-2026, 06:49 PM
                              0 responses
                              551 views
                              1 like
                              Last Post RFrosty
                              by RFrosty
                               
                              Working...
                              X