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

Synchronization problems in indicator with multiple data called from other indicator

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

    Synchronization problems in indicator with multiple data called from other indicator

    I've created an indicator that calculates it's values based on a secondary 1 tick data series which works ok. But during real time calculations in a second indicator that uses the data of the first the values become inaccurate because the tick data set is not properly synced.
    Example:
    Code:
        public class SupportingIndicator : Indicator
        {
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                    Description                                    = @"SupportingIndicator";
                    Name                                        = "SupportingIndicator";
                    Calculate                                    = Calculate.OnBarClose;
                    IsOverlay                                    = false;
                    DisplayInDataBox                            = true;
                    DrawOnPricePanel                            = false;
                    DrawHorizontalGridLines                        = true;
                    DrawVerticalGridLines                        = true;
                    PaintPriceMarkers                            = true;
                    ScaleJustification                            = NinjaTrader.Gui.Chart.ScaleJustification.Right;
                    //Disable this property if your indicator requires custom values that cumulate with each new market data event.
                    //See Help Guide for additional information.
                    IsSuspendedWhileInactive                    = true;
                    AddPlot(Brushes.Red, "SupportingPlot");
                }
                else if (State == State.Configure)
                {
                    AddDataSeries(Data.BarsPeriodType.Tick, 1);
                }
            }
    
            protected override void OnBarUpdate()
            {
                if(BarsInProgress != 0 || State != State.Realtime) return;
                Value[0] = Close[0];
                Print("Sup Last bar: " + CurrentBars[1] + " Time: " + Time[0]);
            }
    Code:
        public class PrimaryIndicator : Indicator
        {
            private SupportingIndicator supportingIndicator;
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                    Description                                    = @"";
                    Name                                        = "PrimaryIndicator";
                    Calculate                                    = Calculate.OnBarClose;
                    IsOverlay                                    = false;
                    DisplayInDataBox                            = true;
                    DrawOnPricePanel                            = true;
                    DrawHorizontalGridLines                        = true;
                    DrawVerticalGridLines                        = true;
                    PaintPriceMarkers                            = true;
                    ScaleJustification                            = NinjaTrader.Gui.Chart.ScaleJustification.Right;
                    //Disable this property if your indicator requires custom values that cumulate with each new market data event.
                    //See Help Guide for additional information.
                    IsSuspendedWhileInactive                    = true;
                    AddPlot(Brushes.Red, "PrimaryPlot");
                }
                else if (State == State.Configure)
                {
                    AddDataSeries(Data.BarsPeriodType.Tick, 1);
                } else if(State == State.DataLoaded) {
                    supportingIndicator = SupportingIndicator();
                }
            }
    
            protected override void OnBarUpdate()
            {
                if(BarsInProgress != 0 || State != State.Realtime) return;
                Value[0] = supportingIndicator[0];
                Print("Pri Last bar: " + CurrentBars[1] + " Time: " + Time[0]);
            }
    On my volume based chart this produces following output:

    Code:
    Sup Last bar: 1226965 Time: 19/02/2020 11:23:28
    Pri Last bar: 1227331 Time: 19/02/2020 11:23:28
    Sup Last bar: 1227332 Time: 19/02/2020 11:23:37
    Pri Last bar: 1227593 Time: 19/02/2020 11:23:37
    Sup Last bar: 1227594 Time: 19/02/2020 11:23:59
    Pri Last bar: 1227938 Time: 19/02/2020 11:23:59
    Sup Last bar: 1227939 Time: 19/02/2020 11:24:36
    Pri Last bar: 1228297 Time: 19/02/2020 11:24:36
    Sup Last bar: 1228298 Time: 19/02/2020 11:25:06
    Pri Last bar: 1228635 Time: 19/02/2020 11:25:06
    The tick data series in the supporting indicator is running one bar behind.

    My solution is to use a helper class instead and use it to calculate the data without calling a secondary indicator;

    Example:
    Code:
    namespace NinjaTrader.NinjaScript.Indicators.Helper
    {
            public class CalculationHelper {
                private TimeSeries[] Times;
                private int[] CurrentBars;
                private int SeriesIndex;
                private int MasterIndex;
                private Bars Bars;
                private Series<double> OutputSeries;
    
                public CalculationHelper(
                   Bars bars
                , TimeSeries[] times
                , Series<double> outputSeries
                , int[] currentBars
                , int seriesIndex
                , int masterIndex
                    ) {
                this.Bars = bars;
                this.Times = times;
                this.OutputSeries = outputSeries;
                this.CurrentBars = currentBars;
                this.SeriesIndex = seriesIndex;
                this.MasterIndex = masterIndex;
            }
            public void OnBarUpdate() {
                //do something
                OutputSeries[0] = whatever
            }
    }
    Code:
        public class PrimaryIndicator : Indicator
        {
            private Series<double> supportingSeries;
            private NinjaTrader.NinjaScript.Indicators.Helper.CalculationHelper calculationHelper = null;
    
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                    Description                                    = @"";
                    Name                                        = "PrimaryIndicator";
                    Calculate                                    = Calculate.OnBarClose;
                    IsOverlay                                    = false;
                    DisplayInDataBox                            = true;
                    DrawOnPricePanel                            = true;
                    DrawHorizontalGridLines                        = true;
                    DrawVerticalGridLines                        = true;
                    PaintPriceMarkers                            = true;
                    ScaleJustification                            = NinjaTrader.Gui.Chart.ScaleJustification.Right;
                    //Disable this property if your indicator requires custom values that cumulate with each new market data event.
                    //See Help Guide for additional information.
                    IsSuspendedWhileInactive                    = true;
                    AddPlot(Brushes.Red, "PrimaryPlot");
                }
                else if (State == State.Configure)
                {
                    AddDataSeries(Data.BarsPeriodType.Tick, 1);
                } else if(State == State.DataLoaded) {
                    supportingSeries = new Series<double>(this, MaximumBarsLookBack.TwoHundredFiftySix);
                    calculationHelper = new NinjaTrader.NinjaScript.Indicators.Helper.CalculationHelper(BarsArray[1], Times, supportingSeries, CurrentBars, 1, 0);
                }
            }
    
            protected override void OnBarUpdate()
            {
                if(BarsInProgress != 0 || State != State.Realtime) return;
                calculationHelper.OnBarUpdate();
                Value[0] = supportingSeries[0];
            }
    Is this a well known problem, or is there a proper way to deal with synchronization?
    Unfortunately I'm not well versed in NinjaScript but I'd like to at least save time for other people facing the same issue.
    Last edited by MojoJojo; 02-19-2020, 10:59 AM.

    #2
    Hello MojoJojo,

    Thanks for your post.

    Our OrderFlowCumulativeDelta HelpGuide documentation gives a hint for how this case can be handled.

    OrderFlowCumulativeDelta NinjaScript reference - https://ninjatrader.com/support/help...ive_delta2.htm

    When I test the following, I get CurrentBar indexes in alignment.

    Code:
    protected override void OnBarUpdate()
    {
        if (BarsInProgress == 1)
        {
            supportingIndicator.Update(supportingIndicator.BarsArray[1].Count - 1, 1);
        }
    
        if(BarsInProgress != 0 || State != State.Realtime) return;
        Value[0] = supportingIndicator[0];
        Print("Pri Last bar: " + CurrentBars[1] + " Time: " + Time[0]);
    }
    Pri Last bar: 1183616 Time: 2/19/2020 12:53:33 PM
    Sup Last bar: 1183617 Time: 2/19/2020 12:53:36 PM
    Pri Last bar: 1183617 Time: 2/19/2020 12:53:36 PM
    Sup Last bar: 1183620 Time: 2/19/2020 12:53:39 PM
    Pri Last bar: 1183620 Time: 2/19/2020 12:53:39 PM
    Sup Last bar: 1183621 Time: 2/19/2020 12:53:42 PM
    Pri Last bar: 1183621 Time: 2/19/2020 12:53:42 PM
    Sup Last bar: 1183759 Time: 2/19/2020 12:53:45 PM
    Pri Last bar: 1183759 Time: 2/19/2020 12:53:45 PM
    Sup Last bar: 1183761 Time: 2/19/2020 12:53:51 PM
    Pri Last bar: 1183761 Time: 2/19/2020 12:53:51 PM
    Please let us know if we can be of further assistance.
    JimNinjaTrader Customer Service

    Comment


      #3
      Hello Jim,

      thanks for quick and excellent solution!
      I tried Update() before, too bad that I didn't read the reference more carefully.

      Comment

      Latest Posts

      Collapse

      Topics Statistics Last Post
      Started by algospoke, Yesterday, 06:40 PM
      2 responses
      19 views
      0 likes
      Last Post algospoke  
      Started by ghoul, Today, 06:02 PM
      3 responses
      14 views
      0 likes
      Last Post NinjaTrader_Manfred  
      Started by jeronymite, 04-12-2024, 04:26 PM
      3 responses
      45 views
      0 likes
      Last Post jeronymite  
      Started by Barry Milan, Yesterday, 10:35 PM
      7 responses
      21 views
      0 likes
      Last Post NinjaTrader_Manfred  
      Started by AttiM, 02-14-2024, 05:20 PM
      10 responses
      181 views
      0 likes
      Last Post jeronymite  
      Working...
      X