Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Automatic update for contracts in AddDataSeries

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

    Automatic update for contracts in AddDataSeries

    Good Afternoon NT Team,

    When adding a new data series, I have noticed under the help guide that is says to include the ticker and the contract expiration month/year for the Instrument name. Is there a way to write the Instrument name so that the data series will update with the contract change?

    #2
    Hello, thanks for writing in. You can use the Instrument.FullName property in AddDataSeries() but note that this may break when using it in the strategy analyzer for optimizations, hence the warning to only use hard-coded values in AddDataSeries in the help guide page.

    Kind regards,
    -ChrisL​

    Comment


      #3
      I am using many instruments (50+) in my indicator. All its doing is calculating a weighted average of the ATR of each product and printing it in the output, so no need for any kind of optimizations.

      Every data series added is a 1Day, and the furthest back the weighted avg ATR calculation goes back is 6 months. With this purpose, would using Instrument.FullName have any issues?
      Last edited by Don22Trader1; 05-09-2023, 01:32 PM.

      Comment


        #4
        You could do what I do in some cases, which is without reference to Instrument, look up the instrument you want in the instrument list, and if it's a future, iterate through the rollovers, find the right one, then compose the instrument name including which rollover date, and AddDataSeries that. This works in Strategy Analyzer also, because you are not referencing Instrument in State.Configure.

        Note that if you are trying to add a different bar type/size of the SAME instrument you're already on, you shouldn't be doing all that - just send "null" for the instrument name. That will work in Strategy Analyzer also, and means the same instrument you're already on.
        Bruce DeVault
        QuantKey Trading Vendor Services
        NinjaTrader Ecosystem Vendor - QuantKey

        Comment


          #5
          Hi, Instrument.FullName gets the instrument that is applied on the chart. If you need to update instruments that are not the primary series, consider Bruce's suggestion. It will take some extra custom code to programmatically keep these extra series updated.

          Comment


            #6
            QuantKey_Bruce,

            Thanks for sharing some info Bruce. Could you provide an example of what the AddDataSeries() method would look like if I followed your method? Also, under what state will the reference to the Instrument be?

            Comment


              #7
              Don22Trader1 You might want to take a look at this example I made which calculates a custom index as a simple sum of several futures contracts. Note that it only adds the CURRENT contract for each so it isn't suitable to look back in the past beyond the current rollover for each but it should give you an idea how all of this works.

              Note especially that this does not violate the rules because the list is not an input parameter, nor do the contracts that are being added change in any one trading day (or even until the next rollover), and it makes no reference whatsoever to the Instrument instance object.

              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 DemonstrateDynamicRolloverLoad : Indicator
                  {
                      private string[] FuturesContractRoots = { "ES", "NQ", "RTY", "YM", "CL", "GC" };
              
                      protected override void OnStateChange()
                      {
                          if (State == State.SetDefaults)
                          {
                              Name                                        = "Demonstrate Dynamic Rollover Load";
                              Calculate                                    = Calculate.OnBarClose;
                              IsOverlay                                    = false;
              
                              AddPlot(Brushes.Blue, "Demonstration Index");
                          }
                          else if (State == State.Configure)
                          {
                              foreach (string FuturesContractRoot in FuturesContractRoots)
                              {
                                  MasterInstrument MasterInstrument = MasterInstrument.All.Where(masterInstrument => masterInstrument.Name == FuturesContractRoot && masterInstrument.InstrumentType == InstrumentType.Future).FirstOrDefault();
                                  if (MasterInstrument == null)
                                  {
                                      Print("Master instrument " + FuturesContractRoot + " not found - skipped");
                                      continue;
                                  }
              
                                  Rollover CurrentRollover = null;
                                  foreach (Rollover Rollover in MasterInstrument.RolloverCollection)
                                  {
                                      if (Rollover.Date >= DateTime.Now.Date) break;
              
                                      CurrentRollover = Rollover;
                                  }
                                  if (CurrentRollover == null)
                                  {
                                      Print("No current rollover for " + FuturesContractRoot + " - skipped");
                                      continue;
                                  }
              
                                  string CurrentContractName = FuturesContractRoot + " " + CurrentRollover.ContractMonth.ToString("MM-yy");
              
                                  AddDataSeries(CurrentContractName, BarsPeriodType.Minute, 1); // 1-minute bars of the current contract of the future in question
              
                                  Print("Added current contract : " + CurrentContractName);
                              }
                          }
                      }
              
                      protected override void OnBarUpdate()
                      {
                          if (CurrentBar < 0) return;
              
                          // calculate a custom index for demonstration purposes - simple sum of all the additional series closes (besides the one on the chart which is ignored)
                          double IndexValue = 0;
                          for (int i = 1; i < BarsArray.Length; i++)
                          {
                              IndexValue += (CurrentBars[i] >= 0) ? Closes[i][0] : 0;
                          }
              
                          if (CurrentBars[0] >= 0) Value[0] = IndexValue;
                      }
                  }
              }
              
              #region NinjaScript generated code. Neither change nor remove.
              
              namespace NinjaTrader.NinjaScript.Indicators
              {
                  public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
                  {
                      private DemonstrateDynamicRolloverLoad[] cacheDemonstrateDynamicRolloverLoad;
                      public DemonstrateDynamicRolloverLoad DemonstrateDynamicRolloverLoad()
                      {
                          return DemonstrateDynamicRolloverLoad(Input);
                      }
              
                      public DemonstrateDynamicRolloverLoad DemonstrateDynamicRolloverLoad(ISeries<double> input)
                      {
                          if (cacheDemonstrateDynamicRolloverLoad != null)
                              for (int idx = 0; idx < cacheDemonstrateDynamicRolloverLoad.Length; idx++)
                                  if (cacheDemonstrateDynamicRolloverLoad[idx] != null &&  cacheDemonstrateDynamicRolloverLoad[idx].EqualsInput(input))
                                      return cacheDemonstrateDynamicRolloverLoad[idx];
                          return CacheIndicator<DemonstrateDynamicRolloverLoad>(new DemonstrateDynamicRolloverLoad(), input, ref cacheDemonstrateDynamicRolloverLoad);
                      }
                  }
              }
              
              namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
              {
                  public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
                  {
                      public Indicators.DemonstrateDynamicRolloverLoad DemonstrateDynamicRolloverLoad()
                      {
                          return indicator.DemonstrateDynamicRolloverLoad(Input);
                      }
              
                      public Indicators.DemonstrateDynamicRolloverLoad DemonstrateDynamicRolloverLoad(ISeries<double> input )
                      {
                          return indicator.DemonstrateDynamicRolloverLoad(input);
                      }
                  }
              }
              
              namespace NinjaTrader.NinjaScript.Strategies
              {
                  public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
                  {
                      public Indicators.DemonstrateDynamicRolloverLoad DemonstrateDynamicRolloverLoad()
                      {
                          return indicator.DemonstrateDynamicRolloverLoad(Input);
                      }
              
                      public Indicators.DemonstrateDynamicRolloverLoad DemonstrateDynamicRolloverLoad(ISeries<double> input )
                      {
                          return indicator.DemonstrateDynamicRolloverLoad(input);
                      }
                  }
              }
              
              #endregion
              ​
              Click image for larger version  Name:	image.png Views:	0 Size:	7.2 KB ID:	1250773

              Click image for larger version  Name:	image.png Views:	0 Size:	92.2 KB ID:	1250772
              Last edited by QuantKey_Bruce; 05-09-2023, 05:51 PM.
              Bruce DeVault
              QuantKey Trading Vendor Services
              NinjaTrader Ecosystem Vendor - QuantKey

              Comment


                #8
                QuantKey_Bruce,

                Awesome example Bruce thanks. Utilizing indexes is a new concept for me, coming with no background in C# or any coding for that matter. I still have a few questions regarding the example you provided.

                I am using 53 instruments so subsequently I am using 53 BIP so that the weighted average ATR calculations can calculate correctly respective to their instrument. In the example you provided, will it only be necessary to have only one AddDataSeries and one BIP and have the calculations run through something like the custom index you created ("IndexValue")?


                Here is a simple summary of what my current code looks like so that maybe it can paint a clearer picture of what I am trying to achieve.

                Code:
                protected override void OnStateChange()
                {
                Name = "WA_ATR";
                Calculate = Calculate.OnBarClose;
                IsOverlay = false
                
                WeightLight = 1; ////This number / 10 is the weight in terms of percentage of 1
                WeightMid = 2; ////This number / 10 is the weight in terms of percentage of 1
                WeightHeavy = 7; ////This number / 10 is the weight in terms of percentage of 1
                }
                
                else if (State == State.Configure)
                {
                  //Primary Data Series is the ES
                  AddDataSeries("NQ "06-23", BarsPeriodType.Day, 1); <//Having 50+ contracts to manually update is tedious work
                  AddDataSeries("EMD 06-23", BarsPeriodType.Day, 1);
                  ... 50 more
                }
                
                protected override void OnBarUpdate()
                {
                  if (BarsInProgress == 0)
                  {
                    double WeightedATR_ES = Instrument.MasterInstrument.RoundToTickSize((ATR(180)[0]*(WeightLight/10)) + (ATR(30)[0]*(WeightMid/10)) +          (ATR(5)[0]*(WeightHeavy/10)));
                
                    Print ("ESWeightedAverageATR " + WeightedATR_ES)
                  }
                
                  if (BarsInProgress == 1)
                  {
                    double WeightedATR_NQ = Instrument.MasterInstrument.RoundToTickSize((ATR(180)[0]*(WeightLight/10)) + (ATR(30)[0]*(WeightMid/10)) +          (ATR(5)[0]*(WeightHeavy/10)));
                
                    Print ("NQWeightedAverageATR " + WeightedATR_NQ)
                  }
                
                  if (BarsInProgress == 2)
                  {
                    double WeightedATR_EMD= Instrument.MasterInstrument.RoundToTickSize((ATR(180)[0]*(WeightLight/10)) + (ATR(30)[0]*(WeightMid/10)) +        (ATR(5)[0]*(WeightHeavy/10)));
                
                    Print ("EMDWeightedAverageATR " + WeightedATR_EMD)
                  }
                
                  ... 50 more
                }
                Last edited by Don22Trader1; 05-10-2023, 12:53 PM.

                Comment


                  #9
                  Well, first of all, I'd probably make an array for all that or a list, if all of your calculations are the same e.g. ATR(180)*W1+ATR(30)*W2+ATR(5)*W3 just on different instruments.

                  You would end up with BIP 0 for the chart, and BIP 1 to 53 for the 53 you added (unless the chart is one of them, then it's BIP 0 to 52 for a total of 53).

                  What you're doing there coding it longhand will work, it's just a lot of copy/paste. You could structure it as a loop using an array or something pretty easily so it's more compact and maintainable.

                  You say above that all you're trying to do is an output e.g. a print or file of the 53 Weighted ATRs - if that's the case this should be pretty easy.
                  Bruce DeVault
                  QuantKey Trading Vendor Services
                  NinjaTrader Ecosystem Vendor - QuantKey

                  Comment

                  Latest Posts

                  Collapse

                  Topics Statistics Last Post
                  Started by Geovanny Suaza, 02-11-2026, 06:32 PM
                  0 responses
                  649 views
                  0 likes
                  Last Post Geovanny Suaza  
                  Started by Geovanny Suaza, 02-11-2026, 05:51 PM
                  0 responses
                  370 views
                  1 like
                  Last Post Geovanny Suaza  
                  Started by Mindset, 02-09-2026, 11:44 AM
                  0 responses
                  109 views
                  0 likes
                  Last Post Mindset
                  by Mindset
                   
                  Started by Geovanny Suaza, 02-02-2026, 12:30 PM
                  0 responses
                  573 views
                  1 like
                  Last Post Geovanny Suaza  
                  Started by RFrosty, 01-28-2026, 06:49 PM
                  0 responses
                  576 views
                  1 like
                  Last Post RFrosty
                  by RFrosty
                   
                  Working...
                  X