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

Checking for null reference on BarsArray[1]

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

    Checking for null reference on BarsArray[1]

    On a 1 minute chart, my primary bars instrument is very liquid but my secondary is not. I would like to use a unique timestamp of the primary to check if the secondary has a valid close for that timestamp. Here is what I have in my OnRender():

    Code:
    //This is above in State.Configure
    AddDataSeries("XLRE",BarsPeriodType.Minute,BarsPeriod.Value);
    
    protected override void OnRender(ChartControl chartControl, ChartScale chartScale) {			
    	if (ChartBars.Bars == null || Bars.Instrument == null)return;
    	base.OnRender(chartControl, chartScale);
    	for (int idx = ChartBars.FromIndex; idx <= ChartBars.ToIndex; idx++){
    		
    		//Is this a way to get a unique timestamp from the primary bars object?
    		DateTime slotTime = chartControl.GetTimeBySlotIndex(idx);
    		int subIdx = BarsArray[0].GetBar(slotTime);
    		
    		//pass the time to the second bars array object to see if there is a bar there
    		if(BarsArray[1].GetClose(subIdx) == null){
    			Print("XLRE has no data at bar number: " + BarsArray[0].GetTime(subIdx));	
    		}else{
    		    Print(String.Format("XLRE Close is: {0} at time: {1}.", BarsArray[1].GetClose(subIdx), BarsArray[1].GetTime(subIdx)));	
    		}
    	}
    
    }
    This is the error I am getting:
    Code:
    Indicator 'CustomRenderTc': Error on calling 'OnRender' method on bar 418: Object reference not set to an instance of an object.
    Last edited by swcooke; 09-25-2018, 08:45 AM.

    #2
    Hello swooke,

    Thanks for your post.

    ChartControl.GetTimeBySlotIndex will get the time value for a slot for the entire chart from ChartControl. Other data series added to a chart will cause a difference in bar slots on the chart, so I would typically advise against using GetTimeBySlotIndex. Instead, I would recommend to use ChartBars.GetTimeByBarIdx() which will be relative to the charted primary data series.

    ChartBars.GetTimeByBarIdx() - https://ninjatrader.com/support/help...mebybaridx.htm

    You are making references to absolute indexes in your rendering code which is good practice, but I may wish to point out the Series.GetValueAt() and Series.IsValidDataPointAt() methods which you may wish to use to accomplish your goal. As an example, you could use a check like the following to see if a secondary series has a valid data point before referencing that value:
    Code:
    if(Closes[1].IsValidDataPointAt(barIndex))
    	Closes[1].GetValueAt(barIndex);
    Series.GetValueAt() - https://ninjatrader.com/support/help...getvalueat.htm

    Series.IsValidDataPointAt() - https://ninjatrader.com/support/help...atapointat.htm

    Please let us know if we can be of further assistance.
    JimNinjaTrader Customer Service

    Comment


      #3
      Jim,

      Is there any way you could give a more complete example of an OnRender() that would do what I am trying to do? This is not my first ticket on this topic and the last reply seemed to take me around the block a little. I am just looking for an example that would work.

      Comment


        #4
        Here is a simpler way to ask the same question. If I add XLRE as a second symbol in my chart so I can see XLRE under SPY, I can see that at 14:47 New York Time, there was no bar printed for XLRE. Here is a screenshot:

        Free online storage and sharing with Screencast.com. 2 GB of storage and 2 GB of bandwidth per month for free. We won't compress, alter or take ownership of your content.


        However, if I execute this OnRender, on a 1 minute chart that is only loading 1 day's worth of bars, I get nothing printed to the Log. Shouldn't this script print that the 14:47 bar of XLRE is not valid?

        Code:
        protected override void OnRender(ChartControl chartControl, ChartScale chartScale) {			
        	if (ChartBars.Bars == null || Bars.Instrument == null)return;
        	base.OnRender(chartControl, chartScale);
        	for (int idx = ChartBars.FromIndex; idx <= ChartBars.ToIndex; idx++){
        		
        		//Is this a way to get a unique timestamp from the primary bars object?
        		DateTime slotTime = ChartBars.GetTimeByBarIdx(ChartControl,idx);
        		
        		//get the bar index of the secondary bar using the slotTime
        		int subIdx = BarsArray[1].GetBar(slotTime);
        		
        		//pass the time to the second bars array object to see if there is a bar there
        		if(!Closes[1].IsValidDataPointAt(subIdx)){
        			Print(String.Format("XLRE has no data at: " + BarsArray[1].GetTime(subIdx)));				
        		}
        	}
        
        }
        Last edited by swcooke; 09-25-2018, 10:37 AM.

        Comment


          #5
          Hello swooke,

          I'd recommend comparing timestamps since GetBar() will give a timestamp for the current bar or the timestamp for first bar if the timestamp is before the first bar or after the last bar.

          Here is a modification of your snippet showing how you can get the primary data series' timestamp from ChartBars, use that timestamp to get an index on the secondary series, and to use the index on the secondary series to compare timestamps. If timestamps match, then we have a corresponding bar on the other instrument.

          Code:
          protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
          {
          	ClearOutputWindow();
          	if (ChartBars.Bars == null || Bars.Instrument == null)
          	return;
          	base.OnRender(chartControl, chartScale);
          	for (int idx = ChartBars.FromIndex; idx <= ChartBars.ToIndex; idx++)
          	{
          		//Get Timestamp from primary bars object
          		DateTime barTime = ChartBars.GetTimeByBarIdx(ChartControl, idx);
          		
          		// Get barIndex for that time or CurrentBar if that time is greater than the last bar.
          		int subIdx = BarsArray[1].GetBar(barTime);
          		
          		// Only proceed if valid, however, GetBar() will still give us a valid index if we are referencing a bar before the first bar or after the last bar
          		if (Times[1].IsValidDataPointAt(subIdx))
          		{
          			// Check the time of the bars to see if we have a match.
          			if (Times[1].GetValueAt(subIdx) == barTime)
          				Print(String.Format("Mathcing Bar at index: {0} subIdx: {1} Time: {2} Close: {3}", idx,  subIdx, Times[1].GetValueAt(subIdx), Closes[1].GetValueAt(subIdx)));
          			else 
          				Print("No matching bar");
          		}
          	}
          }
          Please let us know if we can be of further assistance.
          Attached Files
          JimNinjaTrader Customer Service

          Comment


            #6
            Thank you for taking the time to do this. It is very helpful. One last question is in my comments of this code:

            Code:
            	protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
            {
            	ClearOutputWindow();
            	if (ChartBars.Bars == null || Bars.Instrument == null)
            	return;
            	base.OnRender(chartControl, chartScale);
            	for (int idx = ChartBars.FromIndex; idx <= ChartBars.ToIndex; idx++)
            	{
            		//Get Timestamp from primary bars object
            		DateTime barTime = ChartBars.GetTimeByBarIdx(ChartControl, idx);
            		
            		// Get barIndex for that time or CurrentBar if that time is greater than the last bar.
            		int subIdx = BarsArray[1].GetBar(barTime);
            		
            		// Jim, seems like subIdx will always be valid so why use this if statement at all?
            		if (!Times[1].IsValidDataPointAt(subIdx))
            		{
            			Print("Will this ever print? I don't think it will");
            		}
            	}
            }

            Comment


              #7
              Hello swooke,

              Yes, in the case of using GetBar(), you will get valid data points. I included that line simply to show how IsValidDataPointAt() would be used.

              If you were to use the barIndex relative to the primary data series (idx) instead of the index returned by ChartBars, then this would be a case where GetValueAt may give the object reference not set to an instance of an object error.

              For example:
              Code:
              // If we use idx instead of the index returned from GetBar(), there would be a chance to hit an Object reference not set to an instance of an object error. Using IsValidDataPointAt() would void the error in that context.
              if (Times[1].IsValidDataPointAt([B]idx[/B])) // Comment this line to see hit a runtime error.
              {
              	// Check the time of the bars to see if we have a match.
              	if (Times[1].GetValueAt([B]idx[/B]) == barTime)
              		Print(String.Format("Mathcing Bar at index: {0} subIdx: {1} Time: {2} Close: {3}", idx,  subIdx, Times[1].GetValueAt(subIdx), Closes[1].GetValueAt(subIdx)));
              	else 
              		Print("No matching bar");
              }
              Please note that this example is only meant to show how an error can be encountered. It does not serve any practical function.

              Please let us know if we can be of further assistance.
              JimNinjaTrader Customer Service

              Comment

              Latest Posts

              Collapse

              Topics Statistics Last Post
              Started by RookieTrader, Today, 07:41 AM
              1 response
              4 views
              0 likes
              Last Post NinjaTrader_ChelseaB  
              Started by kujista, Today, 05:44 AM
              1 response
              9 views
              0 likes
              Last Post NinjaTrader_ChelseaB  
              Started by elderan, Yesterday, 08:03 PM
              1 response
              12 views
              0 likes
              Last Post NinjaTrader_BrandonH  
              Started by samish18, Yesterday, 08:57 AM
              8 responses
              25 views
              0 likes
              Last Post samish18  
              Started by DJ888, 04-16-2024, 06:09 PM
              3 responses
              10 views
              0 likes
              Last Post NinjaTrader_Erick  
              Working...
              X