Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Future expiry / rollover date and backtesting

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

    Future expiry / rollover date and backtesting

    Hi,
    I am trading futures and my merge policy is "Merge non back adjusted".
    I am aware that NT does not hold the information of the real expiration of a future contract but something which NT calls "rollover date".
    I found a attribute of the instrument object which is called "expiry" but it actually holds the rollover date. Maybe the name can be changed to "rolloverDate" or something?
    Is NT somewhere holding the real expiration?

    Another question is:
    I have a back testing period of lets say 2 years. I experience that during the back-test of the 2 years the instrument always holds the "expiration" of the future contract which I am back-testing with. Is there a way to get the "expiry" of the future 2 years ago?

    Example:
    I am back-testing with the contract "FGBL 06-21". The instrument object always returns the "expiry" of 01.06.2021 no matter if the back-test is currently 2 years ago or now.
    Is there a way to change that?

    Thanks,
    Klaus

    #2
    Just found the Rollover Collection. Sorry for bothering!

    Comment


      #3
      Hello Klaus,

      Are you wanting the <rolloverobject>.Date?


      You may find the RolloverIndications indicator helpful.
      Shows a button on the chart to roll the expiry to the next available contract month. Option to hide button until a number of days before or on roll date. Another option to confirm by opening the instrument overlay selector or automatically rollover without confirmation. (Update June 27th, 2019 &#8211; Added an option to show [&#8230;]
      Chelsea B.NinjaTrader Customer Service

      Comment


        #4
        Hi Chelsea,
        yes, that's been the information I was looking for. Thanks so much.
        Klaus

        Comment


          #5
          Hello Chelsea,

          I tried to get the rollover date with

          Print(Bars.Instrument.MasterInstrument.RolloverCol lection.rollover.ContractMonth); but this seems not to work.

          What can I do?

          Kind regards
          Gerik

          Comment


            #6
            Hello Gerik,

            RolloverCollection is a collection. You will need to choose a specific rollover in this collection.

            Have a look at the example in the help guide which loops through rollover collection and prints each rollover element in the collection.
            Chelsea B.NinjaTrader Customer Service

            Comment


              #7
              Hello Chelsea,

              how can I retrieve the rolloverdate from the current instrument?

              I assume, I have to loop through the rollovercollection and match it with the current instrument.

              Is there any example how to achieve that?

              The objective is to identify in advance when the expiry of the current instrument will be to avoid a settlement.

              Kind regards
              Gerik

              Comment


                #8
                Hello Gerik,

                On lines 186 - 188, in the RolloverIndications_NT8 linked in post# 3, the current rollover (activeExpiry) is found by looping through the Instrument.MasterInstrument.RolloverCollection. This is used on line 212.

                Below is a link to the help guide on the RolloverCollection.
                Chelsea B.NinjaTrader Customer Service

                Comment


                  #9
                  Hello Chelsea,

                  using the indicator, for MESZ21 or MES 12-21 I receive 07 December 2021 as the rollover date although the settlement is 17 December 2021.

                  How can I retrieve the settlement date, which would be 17 December 2021?

                  Kind regards
                  Gerik

                  Comment


                    #10
                    Hello Gerik,

                    NinjaTrader does not store the settlement date. Only the rollover.Date as it would be shown in the Instrument -> Contract months window.
                    Chelsea B.NinjaTrader Customer Service

                    Comment


                      #11
                      Hello Chelsea,

                      thank you for your answer. May I ask the following in addition?
                      1. The rollover.Date would be the first date when the rollover can be initiated until the settlement date, right?
                      2. The period where the rollover is possible is the rollover.date + 10 days. Is it true?
                      Kind regards
                      Gerik

                      Comment


                        #12
                        Hello Gerik,

                        The rollover date is generally about a week before the last trading day, however this is not always the case.

                        The rollover date is used for NinjaTrader to merge historical data on the chart. It is also used for the Tools -> Database management -> Rollover button. These dates can be modified and typically a product can be traded before the rollover date.

                        Below is a link to a page that includes a link to the trading calendar for you to compare.
                        Chelsea B.NinjaTrader Customer Service

                        Comment


                          #13
                          Hi Chelsea, I've looked at your Rollover indications script. I'd like to use the rollover part only without any display and anything else that's not necessary for the following AddDataSeries method purpose.
                          There's a serious lack/flaw in the instrument reference of the AddDataSeries currently only accepting hardcoded string expiry reference (with disadvantage to non Kinetic subscribers Multi-brokers licence owners as a result).
                          The problem details
                          How to Add A New Instrument Series without the Expiry date?

                          and
                          I'm trying to add a new instrument series with AddDataSeries() (https://ninjatrader.com/support/helpGuides/nt8/NT%20HelpGuide%20English.html?adddataseries.htm) I see on the example page we specify the expiration date as for example &quot;ES 09-16&quot; protected override void OnStateChange() { if (State ==


                          How to strip your code to the bare minimum needed to add the dynamic expiry reference to the AddDataSeries method? Thanks!
                          Last edited by PaulMohn; 03-24-2022, 05:14 PM.

                          Comment


                            #14
                            Chelsea, i found a partial solution from the MasterInstrument.GetNextExpiry() doc

                            For example, that works on a CL 05-22 1 Minute Chart

                            PHP Code:
                            AddDataSeries("CL "+Bars.Instrument.MasterInstrument.GetNextExpiry(DateTime.Now).ToString("MM-yy"), BarsPeriodType.Day, 1); 
                            

                            How do I do the same but with a "GC " AddDataSeries() added on a CL 05-22 1 min Chart?

                            I tested that but it doesn't work
                            PHP Code:
                            AddDataSeries("GC "+Bars.Instrument.MasterInstrument.GetNextExpiry(DateTime.Now).ToString("MM-yy"), BarsPeriodType.Day, 1); 
                            

                            I suspect it is because the reference is to the MasterInstrument and i think that is CL / the instrument of the series of the chart the AddDataSeries() is added to.

                            Is there something like Bars.Instrument.<GOLD>.GetNextExpiry() ?
                            PHP Code:
                            AddDataSeries("GC "+Bars.Instrument.<GOLD>.GetNextExpiry(DateTime.Now).ToString("MM-yy"), BarsPeriodType.Day, 1); 
                            

                            Thanks!


                            I've checked the Instrument.GetInstrument() doc

                            and got to this working syntax
                            PHP Code:
                            
                            else if (State == State.Configure)
                            {
                               Instrument Gold = Instrument.GetInstrument("GC");
                               AddDataSeries("GC "+Gold.MasterInstrument.GetNextExpiry(DateTime.Now).ToString("MM-yy"), BarsPeriodType.Day, 1);
                            } 
                            

                            But somehow it doesn't return the correct NextExpiry Month string value for GC (it returns 03-22 instead of the correct GC next expiry Month from now which is 04-22)
                            Indicator 'DailyRanges': Error on calling 'OnStateChange' method: 'AddDataSeries' method only accepts valid instrument names. Either 'GC 03-22' does not exist in the Instrument Manager or the specified exchange has not been configured.
                            How to get it to return the correct next expiry month? Thanks!


                            I did further tests on a GC 04-22 1 min chart with this script
                            PHP 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;
                            #endregion
                            
                            //This namespace holds Indicators in this folder and is required. Do not change it.
                            namespace NinjaTrader.NinjaScript.Indicators
                            {
                              public class DailyRanges : Indicator
                              {
                                private Series<double> CLSeries;
                                private Series<double> ESSeries;
                            
                                protected override void OnStateChange()
                                {
                                  if (State == State.SetDefaults)
                                  {
                                    Description                 = @"Enter the description for your new custom Indicator here.";
                                    Name                     = "DailyRanges";
                                    Calculate                 = Calculate.OnBarClose;
                                    IsOverlay                 = true;
                                    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;
                                  }
                                  else if (State == State.Configure)
                                  {
                            //       Instrument Gold = Instrument.GetInstrument("GC");
                            //       AddDataSeries("GC "+Gold.MasterInstrument.GetNextExpiry(DateTime.Now ).ToString("MM-yy"), BarsPeriodType.Day, 1);
                                    AddDataSeries("CL 05-22", BarsPeriodType.Day, 1);
                                    AddDataSeries("ES 06-22", BarsPeriodType.Day, 1);
                                  }
                                  else if (State == State.DataLoaded)
                                  {
                                    CLSeries = new Series<double>(this, MaximumBarsLookBack.Infinite);
                                    ESSeries = new Series<double>(this, MaximumBarsLookBack.Infinite);
                                  }
                                }
                            
                                protected override void OnBarUpdate()
                                {
                            
                                  if (CurrentBars[0] < 55 || CurrentBars[1] < 4) return;
                            
                                  Draw.TextFixed(this, "tag1", "The current expiry is " + Bars.Instrument.MasterInstrument.GetNextExpiry(Dat eTime.Now).ToString("MM-yy"), TextPosition.BottomRight);
                            
                                  NinjaTrader.Gui.Tools.SimpleFont myFont = new NinjaTrader.Gui.Tools.SimpleFont("Courier New", 12) { Size = 12, Bold = true };
                            
                                  if (BarsInProgress == 0)
                                  {
                                    CLSeries[0] = Highs[1][0]-Lows[1][0];
                            
                                    Draw.TextFixed(
                                      this,
                                      "GCSeries",
                                      "GC DRange: "+CLSeries[0],
                                      TextPosition.TopRight,
                                      Brushes.White,
                                      myFont,
                                      Brushes.Transparent,
                                      Brushes.Transparent,
                                      0);
                            
                                    ESSeries[0] = Highs[2][0]-Lows[2][0];
                            
                                    Draw.TextFixed(
                                      this,
                                      "ESSeries",
                                      new String('\n', 1)+"ES DRange: "+Instrument.MasterInstrument.RoundToTickSize(ESSeries[0] / TickSize),
                                      TextPosition.TopRight,
                                      Brushes.White,
                                      myFont,
                                      Brushes.Transparent,
                                      Brushes.Transparent,
                                      0);
                                  }
                                }
                              }
                            }
                            
                            #region NinjaScript generated code. Neither change nor remove.
                            
                            namespace NinjaTrader.NinjaScript.Indicators
                            {
                              public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
                              {
                                private DailyRanges[] cacheDailyRanges;
                                public DailyRanges DailyRanges()
                                {
                                  return DailyRanges(Input);
                                }
                            
                                public DailyRanges DailyRanges(ISeries<double> input)
                                {
                                  if (cacheDailyRanges != null)
                                    for (int idx = 0; idx < cacheDailyRanges.Length; idx++)
                                      if (cacheDailyRanges[idx] != null && cacheDailyRanges[idx].EqualsInput(input))
                                        return cacheDailyRanges[idx];
                                  return CacheIndicator<DailyRanges>(new DailyRanges(), input, ref cacheDailyRanges);
                                }
                              }
                            }
                            
                            namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
                            {
                              public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
                              {
                                public Indicators.DailyRanges DailyRanges()
                                {
                                  return indicator.DailyRanges(Input);
                                }
                            
                                public Indicators.DailyRanges DailyRanges(ISeries<double> input )
                                {
                                  return indicator.DailyRanges(input);
                                }
                              }
                            }
                            
                            namespace NinjaTrader.NinjaScript.Strategies
                            {
                              public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
                              {
                                public Indicators.DailyRanges DailyRanges()
                                {
                                  return indicator.DailyRanges(Input);
                                }
                            
                                public Indicators.DailyRanges DailyRanges(ISeries<double> input )
                                {
                                  return indicator.DailyRanges(input);
                                }
                              }
                            }
                            
                            #endregion 
                            

                            I noticed the Draw.TextFixed line

                            PHP Code:
                            Draw.TextFixed(this, "tag1", "The current expiry is " + Bars.Instrument.MasterInstrument.GetNextExpiry(Dat eTime.Now).ToString("MM-yy"), TextPosition.BottomRight); 
                            

                            Displays changing values

                            it displays
                            04-22
                            05-22
                            and
                            06-22

                            It seems to change every 2 minutes or so, to the the CL and ES expiries.

                            Why doesn't it remain 04-22? How to make it remain 04-22 (ON GC Chart)? Thanks!
                            Last edited by PaulMohn; 03-24-2022, 07:37 PM.

                            Comment


                              #15


                              Ok, I've placed the Draw.TextFixed line inside the BarsInProgress == 0 scope and now the Expiry month remains stable at 04-22.

                              PHP Code:
                              Draw.TextFixed(this, "tag1", "The current expiry is " + Bars.Instrument.MasterInstrument.GetNextExpiry(Dat eTime.Now).ToString("MM-yy"), TextPosition.BottomRight); 
                              
                              PHP 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;
                              #endregion
                              
                              //This namespace holds Indicators in this folder and is required. Do not change it.
                              namespace NinjaTrader.NinjaScript.Indicators
                              {
                                public class DailyRanges : Indicator
                                {
                                  private Series<double> CLSeries;
                                  private Series<double> ESSeries;
                              
                                  protected override void OnStateChange()
                                  {
                                    if (State == State.SetDefaults)
                                    {
                                      Description                 = @"Enter the description for your new custom Indicator here.";
                                      Name                     = "DailyRanges";
                                      Calculate                 = Calculate.OnBarClose;
                                      IsOverlay                 = true;
                                      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;
                                    }
                                    else if (State == State.Configure)
                                    {
                              //       Instrument Gold = Instrument.GetInstrument("GC");
                              //       AddDataSeries("GC "+Gold.MasterInstrument.GetNextExpiry(DateTime.Now ).ToString("MM-yy"), BarsPeriodType.Day, 1);
                                      AddDataSeries("CL 05-22", BarsPeriodType.Day, 1);
                                      AddDataSeries("ES 06-22", BarsPeriodType.Day, 1);
                                    }
                                    else if (State == State.DataLoaded)
                                    {
                                      CLSeries = new Series<double>(this, MaximumBarsLookBack.Infinite);
                                      ESSeries = new Series<double>(this, MaximumBarsLookBack.Infinite);
                                    }
                                  }
                              
                                  protected override void OnBarUpdate()
                                  {
                              
                                    if (CurrentBars[0] < 55 || CurrentBars[1] < 4) return;
                              
                              
                              
                                    NinjaTrader.Gui.Tools.SimpleFont myFont = new NinjaTrader.Gui.Tools.SimpleFont("Courier New", 12) { Size = 12, Bold = true };
                              
                                    if (BarsInProgress == 0)
                                    {
                                      Draw.TextFixed(this, "tag1", "The current expiry is " + Bars.Instrument.MasterInstrument.GetNextExpiry(Dat eTime.Now).ToString("MM-yy"), TextPosition.BottomRight);
                              
                                      CLSeries[0] = Highs[1][0]-Lows[1][0];
                              
                                      Draw.TextFixed(
                                        this,
                                        "GCSeries",
                                        "GC DRange: "+CLSeries[0],
                                        TextPosition.TopRight,
                                        Brushes.White,
                                        myFont,
                                        Brushes.Transparent,
                                        Brushes.Transparent,
                                        0);
                              
                                      ESSeries[0] = Highs[2][0]-Lows[2][0];
                              
                                      Draw.TextFixed(
                                        this,
                                        "ESSeries",
                                        new String('\n', 1)+"ES DRange: "+Instrument.MasterInstrument.RoundToTickSize(ESSe ries[0] / TickSize),
                                        TextPosition.TopRight,
                                        Brushes.White,
                                        myFont,
                                        Brushes.Transparent,
                                        Brushes.Transparent,
                                        0);
                                    }
                                  }
                                }
                              }
                              
                              #region NinjaScript generated code. Neither change nor remove.
                              
                              namespace NinjaTrader.NinjaScript.Indicators
                              {
                                public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
                                {
                                  private DailyRanges[] cacheDailyRanges;
                                  public DailyRanges DailyRanges()
                                  {
                                    return DailyRanges(Input);
                                  }
                              
                                  public DailyRanges DailyRanges(ISeries<double> input)
                                  {
                                    if (cacheDailyRanges != null)
                                      for (int idx = 0; idx < cacheDailyRanges.Length; idx++)
                                        if (cacheDailyRanges[idx] != null && cacheDailyRanges[idx].EqualsInput(input))
                                          return cacheDailyRanges[idx];
                                    return CacheIndicator<DailyRanges>(new DailyRanges(), input, ref cacheDailyRanges);
                                  }
                                }
                              }
                              
                              namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
                              {
                                public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
                                {
                                  public Indicators.DailyRanges DailyRanges()
                                  {
                                    return indicator.DailyRanges(Input);
                                  }
                              
                                  public Indicators.DailyRanges DailyRanges(ISeries<double> input )
                                  {
                                    return indicator.DailyRanges(input);
                                  }
                                }
                              }
                              
                              namespace NinjaTrader.NinjaScript.Strategies
                              {
                                public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
                                {
                                  public Indicators.DailyRanges DailyRanges()
                                  {
                                    return indicator.DailyRanges(Input);
                                  }
                              
                                  public Indicators.DailyRanges DailyRanges(ISeries<double> input )
                                  {
                                    return indicator.DailyRanges(input);
                                  }
                                }
                              }
                              
                              #endregion 
                              

                              That suggests it must be within a BarsInProgress corresponding instrument Check to return the correct Month expiry value.
                              If that is so, how to do so within the AddDataSeries? Thanks!

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by HGTrader, Today, 09:31 AM
                              0 responses
                              1 view
                              0 likes
                              Last Post HGTrader  
                              Started by Gibranes, 10-12-2024, 04:02 AM
                              2 responses
                              13 views
                              0 likes
                              Last Post Gibranes  
                              Started by mirandacoman, Today, 09:23 AM
                              0 responses
                              2 views
                              0 likes
                              Last Post mirandacoman  
                              Started by dbennett3, Today, 09:18 AM
                              0 responses
                              4 views
                              0 likes
                              Last Post dbennett3  
                              Started by luxurious_04, Today, 07:27 AM
                              1 response
                              6 views
                              0 likes
                              Last Post NinjaTrader_Jesse  
                              Working...
                              X