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

Calling AddDataSeries on both a hosted and hosting Indicator

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

    Calling AddDataSeries on both a hosted and hosting Indicator

    I am reviewing the page about Multi-Time Frame and Instruments. Specifically, the section that talks about making sure you call AddDataSeries in State.Configure for both a hosting indicator and the hosted indicator. Is there an Indicator somewhere that best demonstrates how to do this? I have tried and can't seem to get it to work. Here is my host Indicator which is just supposed to provide the data for a hosting Indicator. Note that my issue is not with the data this indicator puts out. That is accurate. It's about calling it from a hosting indicator:

    Code:
        public class SampleLastEveryTick : Indicator
        {
            private Series<double> sjClose;
            private double close;
            private int activeBar = 0;
    
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                    Description                = "Test Indicatro";
                    Name                    = "SampleLastEveryTick";
                    BarsRequiredToPlot        = 0;
                    Calculate                = Calculate.OnEachTick;
                    DrawOnPricePanel        = false;
                    IsOverlay                = false;
                    DisplayInDataBox        = true;
                }
                else if(State == State.Configure){
                    AddDataSeries("MSFT");
                    sjClose    = new Series<double>(this);                
                }
            }
            protected override void OnMarketData(MarketDataEventArgs e)
            {
                if(BarsInProgress == 0)return;
                if(e.MarketDataType == MarketDataType.Last)
                {
                    close = e.Price;
                }
            }
            protected override void OnBarUpdate()
            {
                if(BarsInProgress != 0)return;
                if (CurrentBar < activeBar) //CurrentBar is -1
                    return;
    
                if (CurrentBar > activeBar)
                {
                    Print(sjClose[1]);
                    activeBar = CurrentBar;
                }
                sjClose[0] = close;
            }
    
            [Browsable(false)]
            [XmlIgnore]
            public Series<double> SjClose
            {
                get {return sjClose;}
            }
        }
    And here is my attempt to call it from a hosting script:

    Code:
        public class CallBuySell : Indicator
        {
            SampleLastEveryTick GUEST = null;
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                    Description                                    = @"Enter the description for your new custom Indicator here.";
                    Name                                        = "CallBuySell";
                    Calculate                                    = Calculate.OnEachTick;
                    IsOverlay                                    = false;
                    DisplayInDataBox                            = true;
                    DrawOnPricePanel                            = true;
                    DrawHorizontalGridLines                        = true;
                    DrawVerticalGridLines                        = true;
                    PaintPriceMarkers                            = true;
                    ScaleJustification                            = NinjaTrader.Gui.Chart.ScaleJustification.Right;
                    IsSuspendedWhileInactive                    = true;
                }
                else if(State == State.Configure){
    
                    AddDataSeries("MSFT");
                }
                else if (State == State.DataLoaded)
                {
                    GUEST = SampleLastEveryTick();
                }            
            }
            protected override void OnBarUpdate()
            {
                if (CurrentBar < 0)return;
                Print(GUEST.SjClose[0]);
            }
        }
    Lastly, here is the error I get when I add the hosting Indicator to a chart:
    Code:
    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.
    Last edited by swcooke; 02-18-2020, 04:40 PM.

    #2
    Hi swcooke, thanks for your note.

    It might be coming from this print in the SampleLastEveryTick indicator:
    Print(sjClose[1]); Does the SampleLastEveryTick indicator work on its own?

    A good example would be the OrderFlow indicators. Those indicators add a 1 tick series, therefore all indicators using an OrderFlow+ indicator need to add the 1 tick series as well.

    I look forward to hearing from you.

    Chris L.NinjaTrader Customer Service

    Comment


      #3
      Yes, it plots fine. I was careful in my post to point that out. The Indicator works well. I just can't call it. I can't see why the Print Statement would cause any issue but I commented it anyway and compiled and still see the error. I will take a look at the OrderFlow Indicator however, for the sake of seeing this with a really simple example, could you run my code and see if you are able to get it to work?

      Comment


        #4
        Probably making sure that only the main data is being processed in the host is enough to get rid of the error.
        Code:
        if(BarsInProgress != 0)return;
        You can also check if the Guest indicator has enough data.
        Code:
        if (GUEST.CurrentBars[0] < 0)return;
        Maybe there is a proper way to ensure that data series are synchronized but after hours of debugging and finding out that in my case during State == State.Realtime the lower timeframe data series was lagging one bar behind on the OnBarUpdate event, I've given up on using multi timeframe guest indicators.

        As long as the logic isn't too complicated and you want to have both the host and the guest indicator, it is in my opinion best to move the logic to a helper class and use it instead of the guest indicator.
        Last edited by MojoJojo; 02-19-2020, 08:46 AM.

        Comment


          #5
          Thanks MojoJojo,

          One follow up question. Is there any way to only process updates from my GUEST? Conceptually, something like this:

          Code:
          if(BarsInProgress == GUEST){
              //do stuff
          }
          In other words, how can I tell when OnBarUpdate is getting an update from GUEST and not the main bars array?

          Comment


            #6
            OnBarUpdate() in the HOST is only invoked when HOST changes occur. Behind the scenes NT makes sure that the GUEST indicator is synchronized and processed first. So checking for GUEST updates should not be needed.

            With a second data input series there manual syncrhonization might be necessary, which was discussed here https://ninjatrader.com/support/foru...ther-indicator.

            Synchronization is a difficult problem, if you don't want to deal with the complexity, it is easier to duplicate the GUEST code in the HOST instead of using a GUEST indicator.
            Code duplication is undesirable, in case you're skilled enough you can move the logic of the GUEST to a third class and use it in the HOST and the GUEST.

            Another way would be to add a reference to the HOST to the GUEST indicator.

            Code:
            public class SampleLastEveryTick : Indicator {
                    public CallBuySell HOST = null;
                    ...
                    protected override void OnBarUpdate() {
                    ...
                    if(HOST != null) HOST.process();

            Code:
                public class CallBuySell : Indicator {
                ...  
                else if (State == State.DataLoaded) {
                    GUEST = SampleLastEveryTick();
                    GUEST.HOST = this;
                }
                ...
                public void process() {
                }
            I don't know how that would turn out, but most likely it's more trouble than it is worth.
            Last edited by MojoJojo; 02-20-2020, 02:20 AM.

            Comment


              #7
              Hi swcooke thanks for your reply.

              I was able to get this to work. You're never filling your public series so the indicator calling it can not see the series.

              Code:
              public class SampleLastEveryTick : Indicator
                  {
                      //public Series<double> sjClose;
                      private double close;
                      private int activeBar = 0;
              
                      protected override void OnStateChange()
                      {
                          if (State == State.SetDefaults)
                          {
                              Description                = "Test Indicatro";
                              Name                    = "SampleLastEveryTick";
                              BarsRequiredToPlot        = 0;
                              Calculate                = Calculate.OnEachTick;
                              DrawOnPricePanel        = false;
                              IsOverlay                = false;
                              DisplayInDataBox        = true;
                          }
                          else if(State == State.Configure){
                              AddDataSeries("MSFT");
                              sjClose    = new Series<double>(this);                
                          }
                      }
                      protected override void OnMarketData(MarketDataEventArgs e)
                      {
              
                          if(BarsInProgress == 0)return;
                          if(e.MarketDataType == MarketDataType.Last)
                          {
                              close = e.Price;
                          }
                      }
                      protected override void OnBarUpdate()
                      {
                          if(BarsInProgress != 0)return;
                          if (CurrentBar < activeBar) //CurrentBar is -1
                              return;
              
                          if (CurrentBar > activeBar)
                          {
                              activeBar = CurrentBar;
                          }
                          sjClose[0] = close;
              
                      }
              
                      [Browsable(false)]
                      [XmlIgnore]
                      public Series<double> sjClose;
                  }
              Also make sure your data feed is pulling in MSFT, pull up a MSFT chart and confirm you get historical and real time data.

              Please let me know if I can assist any further.
              Chris L.NinjaTrader Customer Service

              Comment


                #8
                Thank you both so much. I was able to get it to work by using the tips given here in conjunction with making sure the GUEST Indicator explicitly returned a 0 when the GUEST was not set with some data yet.

                Comment

                Latest Posts

                Collapse

                Topics Statistics Last Post
                Started by RubenCazorla, Today, 09:07 AM
                0 responses
                1 view
                0 likes
                Last Post RubenCazorla  
                Started by BarzTrading, Today, 07:25 AM
                2 responses
                28 views
                1 like
                Last Post BarzTrading  
                Started by devatechnologies, 04-14-2024, 02:58 PM
                3 responses
                20 views
                0 likes
                Last Post NinjaTrader_BrandonH  
                Started by tkaboris, Today, 08:01 AM
                0 responses
                6 views
                0 likes
                Last Post tkaboris  
                Started by EB Worx, 04-04-2023, 02:34 AM
                7 responses
                165 views
                0 likes
                Last Post VFI26
                by VFI26
                 
                Working...
                X