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

BarsRequst - OnBarUpdate Stops Triggering

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

    BarsRequst - OnBarUpdate Stops Triggering

    Long story short.I have very resource intensive indicator that uses several Instruments that is common across several strategies. Instead of calculating the indicator and the market data for each strategy on each tick, I would like to make a singleton addon on with public properties that I can access from any indicator or strategy. The singleton is working perfectly but I believe there is something wrong with the BarsRequest/OnBarUpdate.

    I made a test example below to show you. You can take a look at the Print output.

    Firstly,

    The OnBarUpdate doesn't understand whether it is real time or not.

    Secondly,

    As you can see from the print outs. It prints out fine at first then it just stops processing on OnBarUpdate().

    You call it as so.
    Code:
    private UEJ uej = UEJ.Instance;
    Code:
    #region Using declarations
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Xml.Serialization;
    using NinjaTrader.Cbi;
    using NinjaTrader.Gui;
    using NinjaTrader.Gui.Chart;
    using NinjaTrader.Gui.SuperDom;
    using NinjaTrader.Gui.Tools;
    using NinjaTrader.Data;
    using NinjaTrader.NinjaScript;
    using NinjaTrader.Core.FloatingPoint;
    using NinjaTrader.NinjaScript.DrawingTools;
    using System.Windows.Threading;
    using NinjaTrader.Cbi;
    using NinjaTrader.Core;
    #endregion
    
    //This namespace holds Add ons in this folder and is required. Do not change it. 
    namespace NinjaTrader.NinjaScript.AddOns
    {
        public sealed class UEJ : NinjaTrader.NinjaScript.AddOnBase
        {
    
            public double UEJ_Value { get; private set; }
            public double UEJ_Inverted { get; private set; }
            public double Trend { get; private set; }
    
            private BarsRequest barsRequest1;
            private BarsRequest barsRequest2;
            private BarsRequest barsRequest3;
    
            private double bars1Close;
            private double bars2Close;
            private double bars3Close;
    
            private int daysBack = 1;
    
            //Singleton code -----------------------------------------------------------------------------------------------------
            static int instanceCounter = 0;
            private static UEJ singleInstance = null;
            private static readonly object lockObject = new object();
    
            public static UEJ Instance
            {
                get 
                {
                    if(singleInstance == null)
                    {
                            lock(lockObject)
                            {
                                if(singleInstance == null)
                                {
                                    singleInstance = new UEJ();
                                }
                            }
                    }
                    else
                    {
                        NinjaTrader.Code.Output.Process("Instance of UEJ already created",PrintTo.OutputTab1);        
                    }
    
                    return singleInstance;
                    }
            }
    
            private UEJ() 
            {    
                Print("UEJ Started. Instances created " + instanceCounter + 1);
    
                NinjaTrader.Data.BarsRequest barsRequest1 = _BarsRequest("EURUSD", daysBack);
                NinjaTrader.Data.BarsRequest barsRequest2 = _BarsRequest("USDJPY", daysBack);
                NinjaTrader.Data.BarsRequest barsRequest3 = _BarsRequest("EURJPY", daysBack);
            }
    
        //------------------------------------------------------------------------------------------------------------------------------------
    
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                    Description                                    = @"Tet Example Singleton Addon.";
                    Name                                        = "UEJ";
    
                }
                else if (State == State.Configure)
                {
    
                }
                else if (State == State.Terminated)
                {
                    NinjaTrader.Code.Output.Process("UEJ stopped" , PrintTo.OutputTab1);    
                    Cleanup();
    
                }
                else if (State == State.Historical)
                {
                }
            }
    
    
            private NinjaTrader.Data.BarsRequest _BarsRequest(string symbol, int lookBackPeriod)    
            {
                Cbi.Instrument instrument = Cbi.Instrument.GetInstrument(symbol);
    
                // Declare a BarsRequest object
              NinjaTrader.Data.BarsRequest barsRequest;    
    
              // Request x number of days back of data.
              barsRequest = new NinjaTrader.Data.BarsRequest(instrument, DateTime.Now.AddDays(-lookBackPeriod), DateTime.Now);
    
              // Parameterize the request
              barsRequest.BarsPeriod = new NinjaTrader.Data.BarsPeriod { BarsPeriodType = BarsPeriodType.Tick, Value = 1 };
              barsRequest.TradingHours    = NinjaTrader.Data.TradingHours.Get("Default 24 x 7");
    
              // Attach event handler for real-time events if you want to process real-time data
              barsRequest.Update     += OnBarUpdate;
    
              // Call the Request method on the BarsRequest object to request the bars
              barsRequest.Request(new Action<NinjaTrader.Data.BarsRequest, ErrorCode, string>((bars, errorCode, errorMessage) =>
              {
    
                  if (errorCode != ErrorCode.NoError)
                  {
                      // Handle any errors in requesting bars here
                      Print(string.Format("Error on requesting bars: {0}, {1}", errorCode, errorMessage));
                      return;
                  }
    
              }));
    
                      // Return the Bars Request to any callers of this method
                      return barsRequest;
            }
    
    
    
    
            private void OnBarUpdate(object sender, NinjaTrader.Data.BarsUpdateEventArgs e)
            {
                Print("I am alive " + DateTime.Now.ToShortTimeString());
    
            if(State == State.Historical)
            {
                Print("HISTORICAL - Symbol " + e.BarsSeries.Instrument.ToString() + " Close: " + e.BarsSeries.GetClose(e.MaxIndex) + " Index: " + e.BarsSeries.TotalTicks + " Count " + 
                e.BarsSeries.Count + " LastBarTime " + e.BarsSeries.LastBarTime);    
            }
            else if (State == State.Realtime)
            {
                 Print("REALTIME - Symbol " + e.BarsSeries.Instrument.ToString() + " Close: " + e.BarsSeries.GetClose(e.MaxIndex) + " Index: " + e.BarsSeries.TotalTicks + " Count " + 
                e.BarsSeries.Count + " LastBarTime " + e.BarsSeries.LastBarTime);    
            }
            else
            {
                Print("Symbol " + e.BarsSeries.Instrument.ToString() + " Close: " + e.BarsSeries.GetClose(e.MaxIndex) + " Index: " + e.BarsSeries.TotalTicks + " Count " + 
                e.BarsSeries.Count + " LastBarTime " + e.BarsSeries.LastBarTime);        
            }
    
    
              // Process updated bars on each tick
              for (int i = e.MinIndex; i <= e.MaxIndex; i++)
              {
    
                 //Processing every single realtime tick
    
                     Print(string.Format("i = " + i + "  "  + "REALTIME BARS Time: {1} Close: {5} Symbol: {6}",
                      Environment.NewLine,
                      e.BarsSeries.GetTime(i),
                      e.BarsSeries.GetOpen(i),
                      e.BarsSeries.GetHigh(i),
                      e.BarsSeries.GetLow(i),
                      e.BarsSeries.GetClose(i),
                      e.BarsSeries.Instrument.ToString())
                      );      
              }
    
              //if(something) Calculate()
            }
    
            public void Calculate()
            {
                //Just placeholder code
                UEJ_Value = bars1Close/bars2Close;
                UEJ_Inverted = bars2Close*bars3Close; 
                Trend  = 1;
            }
    
    
            public void Cleanup()
            {
    
              // Make sure to unsubscribe to the bars request subscription
              Print("Cleaning up Subscriptions");
              barsRequest1.Update -= OnBarUpdate;
              barsRequest1.Dispose();
              barsRequest1 = null;
    
              barsRequest2.Update -= OnBarUpdate;
              barsRequest2.Dispose();
              barsRequest2 = null;
    
              barsRequest3.Update -= OnBarUpdate;
              barsRequest3.Dispose();
              barsRequest3 = null;
    
            }
    
        }
    }

    #2
    Hello cutzpr,

    Thank you for the post.

    Do you see the same problem happening if you test the sample addon?
    https://ninjatrader.com/support/help...t_overview.htm

    I am not aware of any existing sample that uses static or a singleton pattern to provide any context on why that may be happening. If we can see the same in the existing working sample addon we can likely find a solution or provide a sample to development for review. If you otherwise want to provide an exported sample showing where in the other scripts you used this that would be helpful for testing what you provided.

    I would also suggest to simplify this down to a single bars request for the purpose of highlighting the issue more clearly. It looks like we would just need the "I am alive" print to confirm OBU is being called, you can omit all other logic that is not required to see the issue.

    JesseNinjaTrader Customer Service

    Comment


      #3
      Jesse,

      Attached is a test strategy. You can see from the print outs that the OnMarketData is not triggering also, the OnBarUpdate triggers eventually but then eventually stops.

      Attached Files

      Comment


        #4
        Hello cutzpr,

        I tried the sample and I do see that the event stops triggering however I am not certain what part would cause that with the given syntax. I would still suggest to make a more simple test if you would like to find what creates the situation specifically. You have a lot going on in this sample that can be removed or reduced to locate the problem. While I cannot suggest a specific coding structure like what you have presented I can suggest to avoid using static, volatile gc.SuppressFinalize or other garbage collection manipulation along with Dispose on the addon class its self. The BarsRequest is designed to be part of the instance that calls it and then managed by that instance with its life cycle, that would be items like a tab page or a script with its states.


        I did try a more simple test using the help guide sample from both a strategy and an addon and see those both working as expected.



        Attached Files
        JesseNinjaTrader Customer Service

        Comment

        Latest Posts

        Collapse

        Topics Statistics Last Post
        Started by Perr0Grande, Today, 08:16 PM
        0 responses
        2 views
        0 likes
        Last Post Perr0Grande  
        Started by elderan, Today, 08:03 PM
        0 responses
        4 views
        0 likes
        Last Post elderan
        by elderan
         
        Started by algospoke, Today, 06:40 PM
        0 responses
        10 views
        0 likes
        Last Post algospoke  
        Started by maybeimnotrader, Today, 05:46 PM
        0 responses
        9 views
        0 likes
        Last Post maybeimnotrader  
        Started by quantismo, Today, 05:13 PM
        0 responses
        7 views
        0 likes
        Last Post quantismo  
        Working...
        X