• If this is your first visit, you will have to register before you can post. To view messages, please scroll below and select the forum that you would like to visits. Questions? Be sure to check out the Forum FAQ.

Announcement

Collapse
No announcement yet.

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 - http://www.ninjatrader.com/support/h...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().
            Patrick H.NinjaTrader Customer Service

            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]);
                			}
                Patrick H.NinjaTrader Customer Service

                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 thecashguys, Today, 10:18 AM
                        0 responses
                        0 views
                        0 likes
                        Last Post thecashguys  
                        Started by pjsmith, Today, 09:58 AM
                        0 responses
                        6 views
                        0 likes
                        Last Post pjsmith
                        by pjsmith
                         
                        Started by bebbus, Today, 09:13 AM
                        0 responses
                        5 views
                        0 likes
                        Last Post bebbus
                        by bebbus
                         
                        Started by roblogic, Today, 08:04 AM
                        0 responses
                        7 views
                        0 likes
                        Last Post roblogic  
                        Started by williamzz, Yesterday, 04:18 PM
                        2 responses
                        10 views
                        0 likes
                        Last Post williamzz  
                        Working...
                        X