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

Error evaluating IsValidPlot() in IDataSeries

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

    Error evaluating IsValidPlot() in IDataSeries

    Hello

    I want to iterate all available values of a DataSeries:

    Code:
    			
    IDataSeries series = Close;
    int n = series.Count;
    for(int i = 0; i < n; i++)
    {
    	int idx = (n - 1) - i;
    	if(series.IsValidPlot(idx))
    	{
    		Print("Value: " + series[idx].ToString());
    	}
    }
    Strangely, i get the error:

    Error on calling 'OnBarUpdate' method for indicator '...': You are accessing an index with a value that is invalid since its out of range. I.E. accessing a series [barsAgo] with a value of 5 when there are only 4 bars on the chart.
    What is wrong here? How to enumerate values in IDataSeries correctly?

    #2
    bzinchenko, you likely run into that as you try to reference to far back in your series too early - as the bar updates are processed sequentially from the left to the right of the chart you cannot reference .Count back as you're for example on bar 10 when your full chart and therefore count would hold 300 bars. So you would need to be more mindful when doing that.
    BertrandNinjaTrader Customer Service

    Comment


      #3
      Thank you for the reply.

      Unfortunately, it seems not relevant. Given a time series IDataSeries, I want to know how to correctly reference its points. As such, it looks very misguiding that IDataSeries has "Count" property, which does not reflect the actual number of points available for a user. According to documentation, IsValidPlot() is supposed to indicate availability of the point. If it does not, which alternative method of control should be used instead?

      Comment


        #4
        bzinchenko, the data series objects will always be in sync with the primary bars series per default, as such the count would be expected to match the Bars.Count - with the check you have in your script you can check you have explicitly .Set a valid plot value for a custom series. The .ContainsValue would also be available - https://www.ninjatrader.com/support/...ries_class.htm

        With my prior comment what I meant was you can try something like this to ensure you request that much back only if valid (i..e on your last bar [assumes CalculateOnBarClose = true])

        if (CurrentBar == Bars.Count -2)
        {
        BarColor = Color.Blue;

        for(int i = 0; i < n; i++)
        {
        int idx = (n - 2) - i;
        if(series.IsValidPlot(idx))
        {
        Print("Value: " + series[idx].ToString());
        }
        }
        }
        BertrandNinjaTrader Customer Service

        Comment


          #5
          Thank you for the reply.

          1. Is it correct that IDataSeries for an indicator with one instrument always contains exactly "CurrentBar" number of valid points?

          2. What is the intended use of IsValidPlot(), if it cannot report availability of a given point in the series?

          3. Why ContainsValue() is available in class DataSeries but not available in its interface IDataSeries?

          Comment


            #6
            Hello bzinchenko,

            Thank you for your response.

            1. Any Data Series synced to the primary series will contain the same number of current bars.

            2. IsValidPlot() will check that the value referenced is a valid value and not a placeholder value in the Data Series.

            3. Before calling a Data Series object to be used in calculations you can use ContainsValue() to ensure it is a valid value to be used. If we are assigning values to the IDataSeries we need to ensure they are valid with IsValidPlot().

            Comment


              #7
              Thank you for the reply. It is useful but, in my view, incorrect.

              After spending a lot of time trying to figure out the real situation, i can sum up as follows:

              1. IDataSeries contains a useless and misguiding property "Count", which does not correspond to the number of points accessible in series on every given bar.

              2. IDataSeries contains a useless and misguiding function IsValidPlot(), which does not guarantee that the point, which positively passes this check can be really accessed.

              3. The only way finding out the real amount of currently accessible points is using the external property "CurrentBar" belonging to Indicator class.

              In all my tests i was able to access exactly "CurrentBar" points back in IDataSeries synced with the primary series.

              By any normal logic, IDataSeries.Count should be always equal to CurrentBar on every given bar in a call to OnBarUpdate().

              Right now, it seems that IDataSeries attaches to a chart and then IDataSeries.Count always contains a total number of points on the chart, while OnBarUpdate() is iteratively called for every chart bar using CurrentBar as a reference of its current position in the attached data series.

              Comment


                #8
                Hello ,

                Thank you for your response.

                Right now, it seems that IDataSeries attaches to a chart and then IDataSeries.Count always contains a total number of points on the chart, while OnBarUpdate() is iteratively called for every chart bar using CurrentBar as a reference of its current position in the attached data series.
                This is correct, IsValidPlot() returns true when the barsIndex pass through is greater than zero or less than the Bars.Count. IDataSeries.Count and Bars.Count will be the same.
                So the Count, as you said, is the number of bars. CurrentBar is the bar number being calculated on.
                IsValidPlot() will check that valid inputs are passed, such as High, Low, Close, etc. If an object passed is not valid then this would return false.

                You could use the following code to iterate the bars and pull th value:
                Code:
                			IDataSeries series = Close;
                			foreach(Data.Bars bars in BarsArray)
                			{
                				DateTime time = bars.GetTime(bars.CurrentBar);
                				Print(time);
                				Print(bars.CurrentBar);
                				Print(series[0]);
                			}

                Comment


                  #9
                  Thank you very much.

                  I believe that the last reply by 'NinjaTrader_PatrickH' consistently and profoundly describes the situation. Personally, I have no further questions or comments on this point.

                  In my opinion, NinjaTrader documentation deserves a paragraph in a reference on IDataSeries to shed a light on this subtle matter.

                  Comment


                    #10
                    Originally posted by bzinchenko View Post
                    ... By any normal logic, IDataSeries.Count should be always equal to CurrentBar on every given bar in a call to OnBarUpdate().
                    That statement is not correct. The relationship between IDataSeries.Count and CurrentBar depends on The value of the CalculateOnBarClose property in one instance. There is also an absolute difference in value because IDataSeries.Count starts counting from "1" whereas CurrentBar start counting from "0".

                    For these reasons, the net result is that at the terminal bar:
                    if CalculateOnBarClose is false, CurrentBar = Count -1;
                    if CalculateOnBarClose is true, CurrentBar = Count -2.

                    Comment


                      #11
                      Thanks to 'koganam' for this valuable note. Definitely, I am aware of this additional complication with CurrentBar = Count -2 (or Count - 1) depending on CalculateOnBarClose value. It is another patch everybody programming for NinjaTrader should be aware of! I omitted mentioning it, not to complicate this thread even more.

                      What I mean, from a generic programming viewpoint, it is very misguiding when an interface of collection, such as IDataSeries, contains a property 'Count', which every programmer would normally expect meaning an upper limit of an enumerator for this collection, but which in practice is not useable for this purpose.

                      Moreover, IDataSeries itself does NOT contain a property allowing its correct enumeration and it can be only achieved by using external properties, such as CurrentBar with additional conditional behavior on CalculateOnBarClose value!

                      Of course, we all know that it is not possible to change now without impacting all existing code. But from OO viewpoint, it is quite an awful situation. Maybe in future versions we might hope for an extension of IDataSeries to be more consistent.

                      Comment


                        #12
                        Originally posted by bzinchenko View Post
                        Thanks to 'koganam' for this valuable note. Definitely, I am aware of this additional complication with CurrentBar = Count -2 (or Count - 1) depending on CalculateOnBarClose value. It is another patch everybody programming for NinjaTrader should be aware of! I omitted mentioning it, not to complicate this thread even more.

                        What I mean, from a generic programming viewpoint, it is very misguiding when an interface of collection, such as IDataSeries, contains a property 'Count', which every programmer would normally expect meaning an upper limit of an enumerator for this collection, but which in practice is not useable for this purpose.

                        Moreover, IDataSeries itself does NOT contain a property allowing its correct enumeration and it can be only achieved by using external properties, such as CurrentBar with additional conditional behavior on CalculateOnBarClose value!

                        Of course, we all know that it is not possible to change now without impacting all existing code. But from OO viewpoint, it is quite an awful situation. Maybe in future versions we might hope for an extension of IDataSeries to be more consistent.
                        I am inclined to agree with you that there seem to be some "side-effects" dependencies: something that is generally considered undesirable in OOP. But, hey, we still have a pretty powerful platform for a retail-trading oriented platform.

                        Comment

                        Latest Posts

                        Collapse

                        Topics Statistics Last Post
                        Started by trilliantrader, 04-10-2024, 09:33 PM
                        6 responses
                        23 views
                        0 likes
                        Last Post trilliantrader  
                        Started by traderqz, Today, 12:06 AM
                        5 responses
                        9 views
                        0 likes
                        Last Post NinjaTrader_Gaby  
                        Started by Mongo, Today, 11:05 AM
                        2 responses
                        7 views
                        0 likes
                        Last Post Mongo
                        by Mongo
                         
                        Started by guillembm, Today, 11:25 AM
                        0 responses
                        3 views
                        0 likes
                        Last Post guillembm  
                        Started by Tim-c, Today, 10:58 AM
                        1 response
                        3 views
                        0 likes
                        Last Post NinjaTrader_Jesse  
                        Working...
                        X