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 alifarahani, Today, 09:40 AM
      4 responses
      20 views
      0 likes
      Last Post alifarahani  
      Started by gentlebenthebear, Today, 01:30 AM
      3 responses
      16 views
      0 likes
      Last Post NinjaTrader_Jesse  
      Started by PhillT, Today, 02:16 PM
      2 responses
      7 views
      0 likes
      Last Post PhillT
      by PhillT
       
      Started by Kaledus, Today, 01:29 PM
      3 responses
      11 views
      0 likes
      Last Post NinjaTrader_Jesse  
      Started by frankthearm, Yesterday, 09:08 AM
      14 responses
      47 views
      0 likes
      Last Post NinjaTrader_Clayton  
      Working...
      X