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

Future expiry / rollover date and backtesting

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

    #16
    I've just tested with
    PHP Code:
        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 12Bold true };

          if (
    BarsInProgress == 0)
          {
    //       Draw.TextFixed(this, "tag1", "The current expiry is " + Bars.Instrument.MasterInstrument.GetNextExpiry(Dat eTime.Now).ToString("MM-yy"), TextPosition.BottomRight);

            
    Instrument Gold Instrument.GetInstrument("GC");
            
    string goldExpiry Gold.MasterInstrument.GetNextExpiry(DateTime.Now). ToString("MM-yy");

            
    Draw.TextFixed(this"tag1""The current expiry is1 " goldExpiryTextPosition.BottomLeft); 

    in
    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<doubleCLSeries;
        private 
    Series<doubleESSeries;

        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.Day1);
            
    AddDataSeries("ES 06-22"BarsPeriodType.Day1);
          }
          else if (
    State == State.DataLoaded)
          {
            
    CLSeries = new Series<double>(thisMaximumBarsLookBack.Infinite);
            
    ESSeries = new Series<double>(thisMaximumBarsLookBack.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 12Bold true };

          if (
    BarsInProgress == 0)
          {
    //       Draw.TextFixed(this, "tag1", "The current expiry is " + Bars.Instrument.MasterInstrument.GetNextExpiry(Dat eTime.Now).ToString("MM-yy"), TextPosition.BottomRight);

            
    Instrument Gold Instrument.GetInstrument("GC");
            
    string goldExpiry Gold.MasterInstrument.GetNextExpiry(DateTime.Now). ToString("MM-yy");

            
    Draw.TextFixed(this"tag1""The current expiry is1 " goldExpiryTextPosition.BottomLeft);

            
    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<doubleinput)
        {
          if (
    cacheDailyRanges != null)
            for (
    int idx 0idx cacheDailyRanges.Lengthidx++)
              if (
    cacheDailyRanges[idx] != null && cacheDailyRanges[idx].EqualsInput(input))
                return 
    cacheDailyRanges[idx];
          return 
    CacheIndicator<DailyRanges>(new DailyRanges(), inputref cacheDailyRanges);
        }
      }
    }

    namespace 
    NinjaTrader.NinjaScript.MarketAnalyzerColumns
    {
      public 
    partial class MarketAnalyzerColumn MarketAnalyzerColumnBase
      
    {
        public 
    Indicators.DailyRanges DailyRanges()
        {
          return 
    indicator.DailyRanges(Input);
        }

        public 
    Indicators.DailyRanges DailyRanges(ISeries<doubleinput )
        {
          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<doubleinput )
        {
          return 
    indicator.DailyRanges(input);
        }
      }
    }

    #endregion 

    and it still return 03-22 instead of 04-22 (on GC 04-22 1 min chart) on the BottomLeft Chart corner.
    How to make it return the correct 04-22 value? Thanks!

    Comment


      #17
      Hello PaulMohn,

      When posting on the forums, please do not create multiple posts. Instead, please edit your post so the last post is concise and only contains relevant information to your question.

      Multiple posts with large amounts of text make it more difficult to understand your exact issue, and makes it difficult for our support staff and for community members to help.

      I recently posted a method that could be used to fetch the symbol name including the next expiry in a separate thread yesterday, that may be helpful for your need. Please see below.

      https://ninjatrader.com/support/foru...83#post1195083
      JimNinjaTrader Customer Service

      Comment


        #18
        Hello Jim and thanks for the reply. I document each step of my solution so I can refer to the exact process later so i just have to remember the logic and not the syntax (when the syntax is absent from the doc or unclear in the doc). I also post the complete code so others can test it before their potentially improved solution-s. The less steps/the more effective/efficient the help the shorter/more concise the questions/solutions.

        Thank you for the method.

        It seems the
        PHP Code:
        Instrument Gold Instrument.GetInstrument("GC");
        string goldExpiry Gold.MasterInstrumentGetNextExpiry(DateTime.Now). ToString("MM-yy"); 
        /
        PHP Code:
        else if (State == State.Configure)
        {
           
        Instrument Gold Instrument.GetInstrument("GC" );
           
        AddDataSeries("GC "+Gold.MasterInstrument.GetNextExpiry(DateTime.Now).ToString("MM-yy"), BarsPeriodType.Day1);


        approach would be shorter and simpler, potentially better to implement for many instuments.

        Why doesn't it return the correct expiry month (03-22 instead of 04-22 on a GC 04-22 1 min chart). How to make it return the correct expiry month? (I ask again because I haven't received answers to those questions and because it seems it would be more beneficial to get answers/solutions to those questions than using your method in case of use with a large number of instruments)


        I'm not sure how to use your method for my case.

        PHP Code:
        private string GetCurrentFuture(string name)
        {
          foreach (
        Instrument inst in Instrument.All)
          {
            if (
        inst.MasterInstrument.Name == name && inst.MasterInstrument.InstrumentType == InstrumentType.Future)
            {
              
        string instFullName String.Format("{0} {1}-{2}",
                      
        name,
                      
        inst.MasterInstrument.GetNextExpiry(Core.Globals.N ow).Month.ToString("D2"),
                      
        inst.MasterInstrument.GetNextExpiry(Core.Globals.N ow).ToString("yy"));
              return 
        instFullName;
            }
          }
          return 
        name;


        In post#4 you say just giving the instrument name value to the method parameter with a string format

        Is that the correct use

        PHP Code:
        private string GetCurrentFuture(string "CL")
        {
          foreach (
        Instrument inst in Instrument.All)
          {
            if (
        inst.MasterInstrument.Name == name && inst.MasterInstrument.InstrumentType == InstrumentType.Future)
            {
              
        string instFullName String.Format("{0} {1}-{2}",
                      
        name,
                      
        inst.MasterInstrument.GetNextExpiry(Core.Globals.N ow).Month.ToString("D2"),
                      
        inst.MasterInstrument.GetNextExpiry(Core.Globals.N ow).ToString("yy"));
              return 
        instFullName;
            }
          }
          return 
        name;


        If that's not correct would you please correct.

        If that's correct, is that how you intended to use it for my case?

        PHP Code:
        else if (State == State.Configure)
        {
           
        AddDataSeries(GetCurrentFuture(string "CL"), BarsPeriodType.Day1);


        If that is so, that means we need n number of GetCurrentFuture() method per n number of instrument, and the GetCurrentFuture() + it's needed AddDataSeries() corresponding line make for significantly longer (2/15 more lines) and less efficient (n use of loops) script than the

        PHP Code:
        else if (State == State.Configure)
        {
           
        Instrument Gold Instrument.GetInstrument("GC" );
           
        AddDataSeries("GC "+Gold.MasterInstrument.GetNextExpiry(DateTime.Now).ToString("MM-yy"), BarsPeriodType.Day1);


        approach.

        Would you please have a fix for the
        PHP Code:
        else if (State == State.Configure)
        {
           
        Instrument Gold Instrument.GetInstrument("GC" );
           
        AddDataSeries("GC "+Gold.MasterInstrument.GetNextExpiry(DateTime.Now).ToString("MM-yy"), BarsPeriodType.Day1);


        approach so it return the correct month expiry value? Thanks!


        I've tested your method correcting my previous syntax errors and ended up with the attached code
        using it in the AddDataSeries() method as
        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);
                
        AddDataSeries(GetCurrentFuture("CL"), BarsPeriodType.Day1);
                
        AddDataSeries(GetCurrentFuture("ES"), BarsPeriodType.Day1);
              }
              else if (
        State == State.DataLoaded)
              {
                
        CLSeries = new Series<double>(thisMaximumBarsLookBack.Infinite);
                
        ESSeries = new Series<double>(thisMaximumBarsLookBack.Infinite);
              }
            }

            private 
        string GetCurrentFuture(string name)
            {
            foreach (
        Instrument inst in Instrument.All)
            {
              if (
        inst.MasterInstrument.Name == name && inst.MasterInstrument.InstrumentType == InstrumentType.Future)
              {
              
        string instFullName String.Format("{0} {1}-{2}",
                  
        name,
                  
        inst.MasterInstrument.GetNextExpiry(Core.Globals.N ow).Month.ToString("D2"),
                  
        inst.MasterInstrument.GetNextExpiry(Core.Globals.N ow).ToString("yy"));
              return 
        instFullName;
              }
            }
            return 
        name;
            } 

        but it doesn't display anything on the TopRight corner of the chart.

        Why isn't it working? Did you test it for my case to check if it worked? If not can you please check it on your end? Thanks!
        Attached Files
        Last edited by PaulMohn; 03-25-2022, 08:15 AM.

        Comment


          #19
          Hello Paul,

          There is a lot of information here that is a bit overwhelming. Please keep questions small and concise so we can better assist.

          When you are working with unlocked code, you will need to be familiar with C# and C# syntax.

          If you are struggling to write correct syntax using custom methods, I suggest getting more familiar with C# through some publicly available resources. Our support staff does not provide C# education, so I have included some links below that can help you get more familiar with C# and using custom methods.

          https://www.tutorialspoint.com/cshar...rp_methods.htm

          Learn Microsoft's popular C# programming language, used to make websites, mobile apps, video games, VR, and more.


          I also suggest keeping matters simple. I.E. focus on one question at a time. In this case, just focus on using the method in a separate script.

          First review the items above, and then implement the custom method I gave into a test script. Use a print to see what is coming out of the method so you can better understand how it would be used with other methods.

          After you are familiar using the method where you can provide "CL" and get "CL 05-22" it will be much clearer how to use that with AddDataSeries.
          JimNinjaTrader Customer Service

          Comment


            #20
            Hello Jim and thanks for the references. The issue here seems to be the calling of your custom method in the AddDataSeries() method, which I've never needed to do before and is not covered in the NT doc or the references you shared by an explicit example.

            I've tested printing as

            PHP Code:
                    AddDataSeries(GetCurrentFuture("CL"), BarsPeriodType.Day1);
                    
            AddDataSeries(GetCurrentFuture("ES"), BarsPeriodType.Day1);
                  }
                  else if (
            State == State.DataLoaded)
                  {
                    
            CLSeries = new Series<double>(thisMaximumBarsLookBack.Infinite);
                    
            ESSeries = new Series<double>(thisMaximumBarsLookBack.Infinite);
                  }
                }

                private 
            string GetCurrentFuture(string name)
                {
                  foreach (
            Instrument inst in Instrument.All)
                  {
                    if (
            inst.MasterInstrument.Name == name && inst.MasterInstrument.InstrumentType == InstrumentType.Future)
                    {
                      
            string instFullName String.Format("{0} {1}-{2}",
                              
            name,
                              
            inst.MasterInstrument.GetNextExpiry(Core.Globals.N ow).Month.ToString("D2"),
                              
            inst.MasterInstrument.GetNextExpiry(Core.Globals.N ow).ToString("yy"));
                      return 
            instFullName;
                    }
                  }
                  return 
            name;
                }


                protected 
            override void OnBarUpdate()
                {

                  if (
            CurrentBars[0] < 55 || CurrentBars[1] < 4) return;


                  Print(
            "GetCurrentFuture(string name) " GetCurrentFuture("CL")); 

            But nothing Prints.

            Please see attached the exported script.
            Please see attached the screenshot.


            The references you shared

            Passing Parameters to a Method
            https://www.tutorialspoint.com/cshar...parameters.htm
            https://www.tutorialspoint.com/cshar...parameters.htm
            https://www.tutorialspoint.com/cshar...parameters.htm


            Thanks for those references.

            it seems for my use case the relevant one is
            C# - Passing Parameters by Value
            https://www.tutorialspoint.com/cshar...parameters.htm

            But the example given calls a class not a method, and assigns new values to the arguments of the method embedded in the called class, and does not use the arguments of its parameters as is, which would be the relevant use for my case. Therefore I cannot learn the relevant use from that reference.

            PHP Code:
            using System;

            namespace 
            CalculatorApplication {
              class 
            NumberManipulator {
                  public 
            void swap(int xint y) {
                    
            int temp;

                    
            temp x/* save the value of x */
                    
            y;     /* put y into x */
                    
            temp/* put temp into y */
                  
            }
                  static 
            void Main(string[] args) {
                    
            NumberManipulator n = new NumberManipulator();

                    
            /* local variable definition */
                    
            int a 100;
                    
            int b 200;

                    
            Console.WriteLine("Before swap, value of a : {0}"a);
                    
            Console.WriteLine("Before swap, value of b : {0}"b);

                    
            /* calling a function to swap the values */
                    
            n.swap(ab);

                    
            Console.WriteLine("After swap, value of a : {0}"a);
                    
            Console.WriteLine("After swap, value of b : {0}"b);

                    
            Console.ReadLine();
                  }
              }


            C# - Methods
            https://www.tutorialspoint.com/cshar...rp_methods.htm
            • Parameter list − Enclosed between parentheses, the parameters are used to pass and receive data from a method. The parameter list refers to the type, order, and number of the parameters of a method. Parameters are optional; that is, a method may contain no parameters.
            Thanks for this reference.
            It seems my use of the string parameter is correct as "CL" when calling the GetCurrentFuture("CL") method in the AddDataSeries. Is it? If it is why doesn't it print/display on the chart? How to make it print/display on the chart? Thanks!
            Attached Files
            Last edited by PaulMohn; 03-25-2022, 10:20 AM.

            Comment


              #21
              Hello Paul,

              This is a custom method I wrote, and is not out-of-the-box NinjaScript. Being familiar enough with C# to test this out in it's simplest form will be the best way for you to move forward.

              Please just focus on using the method with a print without involving your current script.

              Confirm that when you provide "CL" that you get "CL 05-22"

              After confirming that, make a new script that uses the AddDataSeries overload that just takes an instrument name, and plug in my GetCurrentFuture() method.

              Add another print in OnBarUpdate for the instrument: Print(Instrument.FullName);

              Test the script on another symbol like MES 06-22.

              Observe the prints for MES 06-22 and CL 05-22 in the output window.
              JimNinjaTrader Customer Service

              Comment


                #22
                Many thanks for the steps Jim. Now it's working.

                However it wasn't working with the same code with my DailyRanges script.
                I notices the parentheses scopes were "less" spaces on my DailyRanges.cs script than with my new started from scratch jimExpirymethod.cs script.
                Would the less spaced scopes be the reason for not working (without any log tab nor compile error notice) in spite of correct syntax?
                I've added images of the process and the less spaced scope DailyRanges.cs script.

                Attached Files

                Comment


                  #23
                  Multiple Instruments working (added ES)
                  Attached Files

                  Comment


                    #24
                    Hello Paul,

                    Here is a publicly available resource on whitespace with C#:

                    https://www.oreilly.com/library/view...3%20statements.

                    I do not have enough information to know what is wrong. We see the prints and the text drawn. The script is working. If you are not getting a result you expect, the next steps are to better understand why you are getting the result you are. What you expect to see, and what you see that is not expected.

                    I have put some information below to help guide you:

                    "Defining the problem" is an important step in the debugging process to better understand your code.

                    I suggest to better describe what is not working so it is something specific that can be analyzed:
                    • What specifically isn't working? How can I test that repeatedly to see what is going on?
                    • If I add prints throughout the script, do I see any of them? By checking the prints: where does the execution stop?
                    A script must compile and be without runtime errors in order to see your prints. If your code hits a runtime error when you start to use it, adding prints to see where the code stops can help to move forward.

                    If the script is working and you see prints, and you do not see the results you expect, you will need to:
                    1. Identify specifically what is unexpected, and what you expect to see
                    2. Identify a procedure that can reproduce the symptom
                    3. Identify the code related to producing that result
                    4. Add prints to trace back how that result was calculated
                    Some things to think about since you are operating a Multi Time Frame script:
                    • What data series is OnBarUpdate processing on when I see the result I do not expect?
                    • What data series is being referenced when the symptom comes up?
                    • If I am working with Series objects, what data series are these synchronized to. What data series do I want them synchronized to?
                    • Are there enough bars in the specific data series I am referencing?
                    See below for working with Multi Time Frame scripts:

                    https://ninjatrader.com/support/help...nstruments.htm

                    Also see the Series documentation to better understand how to synchronize a Series object with an added data series.

                    Series - https://ninjatrader.com/support/help...ml?seriest.htm

                    Please consider the above as you are working on this over the weekend. If you need additional help:

                    Work up from the script that you put together that simply adds the data series, and step by step add the next piece of functionality until you see something you do not expect.

                    Since you are working with a Multi Time Frame script, also test implementing just on the primary series. (Are your issues related to using multiple data series?)

                    What do you add that causes the behavior to be unexpected?

                    What do you expect?

                    What do you see instead?
                    JimNinjaTrader Customer Service

                    Comment


                      #25
                      Thanks a lot for the investigation template process Jim. I'll try and use it over the weekend and for future projects as first resource.

                      Have a good Weekend!
                      Last edited by PaulMohn; 03-25-2022, 03:43 PM.

                      Comment


                        #26
                        Originally posted by NinjaTrader_ChelseaB View Post
                        Hello Klaus,

                        Are you wanting the <rolloverobject>.Date?
                        https://ninjatrader.com/support/help...collection.htm

                        You may find the RolloverIndications indicator helpful.
                        https://ninjatraderecosystem.com/use...indications-2/
                        NinjaTrader_ChelseaB, when time permits, there is a bug in the RolloverIndications script, which is otherwise quite the tour de force.

                        What appears to happen is, in OnBarUpdate, it calls InsertWPFControls(). In InsertWPFControls, it manipulates the chart window toolbar.

                        However, the indicator calculation thread pool threads that call OnBarUpdate are not UI threads, so a cross-thread exception can be generated under some conditions, which looks like this:

                        2023-03-29 18:05:01:977 ERROR: Indicator 'RolloverIndications': Error on calling 'OnBarUpdate' method on bar 1104: The calling thread cannot access this object because a different thread owns it.

                        To resolve this you could invoke over to the chart control's thread, or just restructure it so that these things don't happen in OnBarUpdate but in something like a dispatchertimer built from the chart control's thread.

                        It's a great indicator. The error I'm listing doesn't happen all the time. But, it does happen some of the time. Hope this helps.
                        Last edited by QuantKey_Bruce; 03-30-2023, 09:43 AM.
                        Bruce DeVault
                        QuantKey Trading Vendor Services
                        NinjaTrader Ecosystem Vendor - QuantKey

                        Comment


                          #27
                          Hello Bruce,

                          Thanks for reporting this!
                          I definitely overlooked those lines in OnBarUpdate().

                          I've got a dispatcher in there now which should resolve.
                          Chelsea B.NinjaTrader Customer Service

                          Comment

                          Latest Posts

                          Collapse

                          Topics Statistics Last Post
                          Started by lightsun47, Today, 03:51 PM
                          0 responses
                          5 views
                          0 likes
                          Last Post lightsun47  
                          Started by 00nevest, Today, 02:27 PM
                          1 response
                          10 views
                          0 likes
                          Last Post 00nevest  
                          Started by futtrader, 04-21-2024, 01:50 AM
                          4 responses
                          46 views
                          0 likes
                          Last Post futtrader  
                          Started by Option Whisperer, Today, 09:55 AM
                          1 response
                          14 views
                          0 likes
                          Last Post bltdavid  
                          Started by port119, Today, 02:43 PM
                          0 responses
                          10 views
                          0 likes
                          Last Post port119
                          by port119
                           
                          Working...
                          X