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?
Announcement
Collapse
No announcement yet.
Partner 728x90
Collapse
NinjaTrader
Automatic update for contracts in AddDataSeries
Collapse
X
-
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?Tags: None
-
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
- Likes 1
-
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
-
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.
- Likes 1
Comment
-
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
-
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
Last edited by QuantKey_Bruce; 05-09-2023, 05:51 PM.
- Likes 1
Comment
-
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
-
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.
- Likes 1
Comment
Latest Posts
Collapse
| Topics | Statistics | Last Post | ||
|---|---|---|---|---|
|
Started by Geovanny Suaza, 02-11-2026, 06:32 PM
|
0 responses
647 views
0 likes
|
Last Post
|
||
|
Started by Geovanny Suaza, 02-11-2026, 05:51 PM
|
0 responses
368 views
1 like
|
Last Post
|
||
|
Started by Mindset, 02-09-2026, 11:44 AM
|
0 responses
108 views
0 likes
|
Last Post
by Mindset
02-09-2026, 11:44 AM
|
||
|
Started by Geovanny Suaza, 02-02-2026, 12:30 PM
|
0 responses
571 views
1 like
|
Last Post
|
||
|
Started by RFrosty, 01-28-2026, 06:49 PM
|
0 responses
573 views
1 like
|
Last Post
by RFrosty
01-28-2026, 06:49 PM
|

Comment