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

Multiple Time Frames Returning Equal Bar Close Data

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

    Multiple Time Frames Returning Equal Bar Close Data

    Pretty much like it said above. I have a large strategy that I'm working on, but attempting to clean up, and created this from the strategy builder to begin the process of making sure things are working right. In doing so I've been debugging everything to ensure calculation values are correct, making sure arrays are right, so on and so forth, and noticed that the close of the 1m bar period and the 15m bar period are always equal. The data series that each array represents appears to be separate, so I'm a little confused why the values are the same.

    Secondly when running this the 1 week 9 period ATR comes out to 184.25? Seems a bit high. I'm converting from Thinkorswim and seeing 103.5

    Lastly I noted the bar array values at the AddDataSeries, just want to verify that's the correct way to call them out? I thought they started at Array[0] being the primary data series.

    Edit: changed the value of the regression channel width to Math.SQRT(std_deviation) and the strategy won't run citing Error on calling 'OnStateChange' method: Object reference not set to an instance of an object. But I'm not seeing where something's not set?
    Commenting out the RegressionChannel1 variable then results in
    Error on calling 'OnBarUpdate' method on bar 6898: You are accessing an index with a value that is invalid since it is out-of-range. I.E. accessing a series [barsAgo] with a value of 5 when there are only 4 bars on the chart.
    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.Indicators;
    using NinjaTrader.NinjaScript.DrawingTools;
    #endregion
    
    //This namespace holds Strategies in this folder and is required. Do not change it.
    namespace NinjaTrader.NinjaScript.Strategies
    {
    public class SupportingFuzzy : Strategy
    {
    private Indicators.RegressionChannel RegressionChannel1;
    
    private ATR ATR1;
    private ATR ATR2;
    private ATR ATR3;
    private ATR ATR4;
    private ATR ATR5;
    private Indicators.VWAP8 VWAP;
    private Indicators.StdDev std_deviation;
    
    protected override void OnStateChange()
    {
    if (State == State.SetDefaults)
    {
    Description = @"SupportingFuzzy";
    Name = "SupportingFuzzy";
    Calculate = Calculate.OnBarClose;
    EntriesPerDirection = 1;
    EntryHandling = EntryHandling.AllEntries;
    IsExitOnSessionCloseStrategy = true;
    ExitOnSessionCloseSeconds = 30;
    IsFillLimitOnTouch = false;
    MaximumBarsLookBack = MaximumBarsLookBack.Infinite;
    OrderFillResolution = OrderFillResolution.Standard;
    Slippage = 0.25;
    StartBehavior = StartBehavior.WaitUntilFlat;
    TimeInForce = TimeInForce.Gtc;
    TraceOrders = false;
    RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
    StopTargetHandling = StopTargetHandling.PerEntryExecution;
    BarsRequiredToTrade = 75000;
    // Disable this property for performance gains in Strategy Analyzer optimizations
    // See the Help Guide for additional information
    IsInstantiatedOnEachOptimizationIteration = true;
    }
    else if (State == State.Configure)
    {
    AddDataSeries(Data.BarsPeriodType.Minute, 1); // Array[1]
    AddDataSeries("ES 09-21", Data.BarsPeriodType.Minute, 15, Data.MarketDataType.Last); // Array[2]
    AddDataSeries("ES 09-21", Data.BarsPeriodType.Minute, 60, Data.MarketDataType.Last); // Array[3]
    AddDataSeries("ES 09-21", Data.BarsPeriodType.Minute, 240, Data.MarketDataType.Last); // Array[4]
    AddDataSeries("ES 09-21", Data.BarsPeriodType.Week, 1, Data.MarketDataType.Last); // Array[5]
    }
    else if (State == State.DataLoaded)
    {
    int std_period = 6900;
    ATR1 = ATR(Closes[1], 9);
    ATR2 = ATR(Closes[2], 9);
    ATR3 = ATR(Closes[3], 9);
    ATR4 = ATR(Closes[4], 9);
    ATR5 = ATR(Closes[5], 9);
    VWAP =VWAP8(Closes[0]);
    std_deviation =StdDev(BarsArray[0],std_period);
    RegressionChannel1 = RegressionChannel(Closes[1], std_period, Math.Sqrt(std_deviation[0]));
    
    }
    }
    int i = 0;
    protected override void OnBarUpdate()
    {
    if (CurrentBars[0] < BarsRequiredToTrade)
    return;
    
    if (CurrentBars[0] < 1
    || CurrentBars[1] < 0
    || CurrentBars[2] < 0
    || CurrentBars[3] < 0
    || CurrentBars[4] < 0
    || CurrentBars[5] < 0)
    return;
    
    // Set 1
    i = i++;
    Print(Time[0]);
    Print("iteration: " +i);
    Print("1 min ATR: " + ATR1[0]);
    Print("15 min ATR: " + ATR2[0]);
    Print("60 min ATR: " + ATR3[0]);
    Print("4 hr ATR: " + ATR4[0]);
    Print("1 week ATR: " + ATR5[0]);
    
    Print("Close 1 bar ago - min: " + Close[1]);
    Print("Close 1 bar ago - 15m: " + Closes[1][1]);
    Print("Close 1 bar ago - hour: " + Closes[2][1]);
    Print("Close 1 bar ago - 4 hr: " + Closes[3][1]);
    Print("Close 1 bar ago - week: " + Closes[4][1]);
    
    Print("VWAP: " + VWAP[0]);
    Print("STD Dev: " +std_deviation[0]);
    Print("Regression Channel Upper: " + RegressionChannel1.Upper[0]);
    Print("Regression Channel Lower: " + RegressionChannel1.Lower[0]);
    // if ((RegressionChannel1.Lower[0] == Low[0])
    // && (ATR1[0] != Low[0])
    // && (ATR2[0] == Highs[2][0])
    // && (ATR3[0] == Closes[4][0])
    // && (ATR4[0] == Lows[3][0])
    // && (ATR5[0] == Lows[5][0]))
    // {
    // EnterLongLimit(Convert.ToInt32(DefaultQuantity), RegressionChannel1.Lower[0], "");
    // }
    
    }
    }
    }
    
    }
    Last edited by itsthefriz; 07-28-2021, 09:35 PM.

    #2
    Hello itsthefriz,

    Thanks for your post.

    A good guide to multi time frame processing can be found here: https://ninjatrader.com/support/help...nstruments.htm

    "...noticed that the close of the 1m bar period and the 15m bar period are always equal." How are you testing this? With Historical data on chart or in strategy analyzer, or with live data on a chart, or using Playback with Market replay data in a chart?

    "Secondly when running this the 1 week 9 period ATR comes out to 184.25? Seems a bit high. I'm converting from Thinkorswim and seeing 103.5" How much historical data are you setting the chart to load? If you are unsure, right mouse click on the chart and select "Data series.." and then look for "days to load".

    ​​​​​​​"I thought they started at Array[0] being the primary data series." That is correct. The chart bars are the primary series. What are the bars type and size of the chart bars?

    "Edit: changed the value of the regression channel width to Math.SQRT(std_deviation) and the strategy won't run citing Error on calling 'OnStateChange' method: Object reference not set to an instance of an object. But I'm not seeing where something's not set?" You would have had to edit the script directly to make that change as the strategy builder would not allow that. The State.Dataloaded is only called once so you are not able to access a specific bar like you are trying to with:
    Math.Sqrt(std_deviation[0])

    Paul H.NinjaTrader Customer Service

    Comment


      #3
      Thanks Paul,

      Got about 12 ninjascript tabs open, that MTF processing is one of them lol to be fair I'm somewhat new to programming/dev work and my C# time is pretty limited. Anything I write is usually accomplished by nearly endless amounts of debugging/verification and even more google searches...

      Anyways this is being ran on live data from a chart which is 1m, 10d /ES

      Chart has loaded 10 days however the strategy is saying 75,000 bars which is a little over 10 weeks worth of 1m bars. Is it possible that is causing the object reference error? Also if your script says to load 10 weeks worth of data, but the chart is only displaying 10 days, does that mean that the 10 weeks never really loaded? Or will it get the data and hold the bars in the array despite only showing 10 days worth of data within the chart?

      Primary bar type is candle/minute, and instrument is ES. Additional data series are just longer term bars from the same chart.

      I did manually edit the script. I like the strategy builder for getting items into a script but prior to getting them into a script it can be kind of difficult to work with. On the other hand not being that familiar with C# seems to cause different but similar problems...

      So all this leads me to a few questions which I'll try to sum up here.

      First is the chart bars loaded - if your script has loaded all the required BarsRequiredToTrade will that be reflected in the chart?

      Second - it seems like you're implying State.Dataloaded can be called multiple times in which case State.Dataloaded can provide access to specific bars, otherwise with it called once State.Dataloaded does not provide access to specific bars? If the [0] is removed from Math.Sqrt(std_deviation[0]) to make Math.Sqrt(std_deviation) then the script will not compile because it cannot covert from the indicator to a double. Knowing this is there a more 'proper' way to set the RegressionChannel width equal to the sqrt of the deviation?

      Thanks, I appreciate the help!

      Comment


        #4
        Hello itsthefriz,

        Thanks for your reply.

        When you add a script to a chart and the script adds further data series, they will only add as many days of data as you have specified in the data series of the chart. In this case, you advised that it is set to 10 days of data. It looks like you are saying 75,000 bars, is that base on the counter i? If so that would be of all that bars, not just the chart bars. To counnt the bars you may want to review the BarsInProgress(): https://ninjatrader.com/support/help...inprogress.htm

        With 10 days of data, you will only get 1 complete weekly bar so your 9 week ATR value would not be expected to be correct.

        As your chart bars are 1 minute, I would advise removing the added 1-minute series as that is just taking up resources.

        BarsRequiredToTrade, by default, is set to 20. It only produces an error message and prevents a trade within that period if your strategy attempts to trade within the first 20 bars (or however many have been set). Reference: https://ninjatrader.com/support/help...redtotrade.htm

        I highly recommend reviewing the help guide for multi time frame coding as there are many considerations and understanding how bars are processed is critical to understand. While it is a long read it contains all the information needed to be successful. https://ninjatrader.com/support/help...nstruments.htm

        No, State.Dataloaded is called once, so accessing a specific bar will not work.https://ninjatrader.com/support/help...tatechange.htm

        You would need to instantiate the RegressionChannel1 in OnBarUpdate() instead of State.DataLoaded because OnBarUpdate() will allow the use of the current value of the standard deviation. This regrettably will create a new indicator copy each time it is called and could eventually cause resource issues. In addition, I would suggest performing a check of Math.Sqrt(std_deviation[0]) to ensure it returns a value greater than or equal to 1 as the parameter for with requires a value greater or equal to 1.


        Paul H.NinjaTrader Customer Service

        Comment


          #5
          Thanks Paul,

          You're right about Math.Sqrt(std_deviation[0]) occasionally returning a value below 1 if the bar period is not set long enough. That's an easy enough item to check for

          So with chart bars set to one minute and the strategy calling AddDataSeries to add 1m bars it's essentially duplicating the data? Sounds like this could be the reason for the output of the 1m and 15m adding up if that's the case.

          Regarding the time series and 75k bars required, I had thought that the data series in a strategy could be loaded independent of the chart it was on. I.e. if you had a chart with 1 day worth of data you could have the script look back 3 or 4 days if you specify to load that many days worth of data but it sounds like that is not the case. I take it script/strategy data is pulled directly from the chart rather than getting OHLC from historical data? I'll update the chart so it contains enough data to process 9 weeks for the ATR

          Hate to say this but I'm 99% sure that instantiating the RegressionChannel in the OnBarUpdate is what is causing some resource issues with the larger strategy looping roughly 6 thousand times upon being enabled and it takes 45 minutes to start. Calculation time is concerning me a bit which is why the script above was written, to help simplify/change the direction without editing/breaking the overall script. Is there any chance that RegressionChannel1 could be re-written as an indicator or would you expect it to have the same behavior?

          Comment


            #6
            Hello itsthefriz,

            Thanks for your reply.

            "So with chart bars set to one minute and the strategy calling AddDataSeries to add 1m bars it's essentially duplicating the data? Sounds like this could be the reason for the output of the 1m and 15m adding up if that's the case." I wouldn't think so but adding further 1 minute bars would be a waste. It is more likely a matter of how you are using BarsInProgress and when you are printing the values. Again the Multi time frame documentation should help.

            "Regarding the time series and 75k bars required, I had thought that the data series in a strategy could be loaded independent of the chart it was on. I.e. if you had a chart with 1 day worth of data you could have the script look back 3 or 4 days if you specify to load that many days worth of data but it sounds like that is not the case. I take it script/strategy data is pulled directly from the chart rather than getting OHLC from historical data? I'll update the chart so it contains enough data to process 9 weeks for the ATR" When you add a data series, it will load the data based on the days to load of the chart by default. You can use the method overload where you can specify the "Bars To Load" parameter: https://ninjatrader.com/support/help...dataseries.htm if you want the added data series to be more or less than the chart.

            "Is there any chance that RegressionChannel1 could be re-written as an indicator " Yes you can do that and that would be the better answer. The issue here is that each time a parameter changes you need a new copy of the indicator. If instead, you write the indicator to include that calculation then you would only need one copy.
            Paul H.NinjaTrader Customer Service

            Comment


              #7
              Hi Paul,

              I re-wrote the regression channel as an indicator but doing so left me with a few questions.

              First here's the script
              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 StdRegChannel : Indicator
              {
              private Series<double> interceptSeries;
              private Series<double> slopeSeries;
              private Series<double> stdDeviationSeries;
              private Indicators.StdDev std_deviation;
              private Indicators.RegressionChannel RegressionChannel1;
              public int int ChanPeriod = 6900;
              
              
              protected override void OnStateChange()
              {
              if (State == State.SetDefaults)
              {
              Description = @"Standard Deviation Reg Channel";
              Name = "StdRegChannel";
              Calculate = Calculate.OnBarClose;
              IsOverlay = true;
              DisplayInDataBox = true;
              IsAutoScale = false;
              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)
              {
              }
              else if (State == State.DataLoaded)
              {
              //int ChanPeriod = 6900;
              //int std_period = ChanPeriod;
              //std_deviation = StdDev(6900);
              std_deviation = StdDev(ChanPeriod);
              }
              
              }
              
              protected override void OnBarUpdate()
              {
              RegressionChannel1 = RegressionChannel(Closes[0], ChanPeriod, Math.Sqrt(std_deviation[0](Closes[0])));
              }
              }
              }
              
              #region NinjaScript generated code. Neither change nor remove.
              
              namespace NinjaTrader.NinjaScript.Indicators
              {
              public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
              {
              private StdRegChannel[] cacheStdRegChannel;
              public StdRegChannel StdRegChannel()
              {
              return StdRegChannel(Input);
              }
              
              public StdRegChannel StdRegChannel(ISeries<double> input)
              {
              if (cacheStdRegChannel != null)
              for (int idx = 0; idx < cacheStdRegChannel.Length; idx++)
              if (cacheStdRegChannel[idx] != null && cacheStdRegChannel[idx].EqualsInput(input))
              return cacheStdRegChannel[idx];
              return CacheIndicator<StdRegChannel>(new StdRegChannel(), input, ref cacheStdRegChannel);
              }
              }
              }
              
              namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
              {
              public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
              {
              public Indicators.StdRegChannel StdRegChannel()
              {
              return indicator.StdRegChannel(Input);
              }
              
              public Indicators.StdRegChannel StdRegChannel(ISeries<double> input )
              {
              return indicator.StdRegChannel(input);
              }
              }
              }
              
              namespace NinjaTrader.NinjaScript.Strategies
              {
              public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
              {
              public Indicators.StdRegChannel StdRegChannel()
              {
              return indicator.StdRegChannel(Input);
              }
              
              public Indicators.StdRegChannel StdRegChannel(ISeries<double> input )
              {
              return indicator.StdRegChannel(input);
              }
              }
              }
              
              #endregion
              When it goes to compile I get a "Method name expected" error on line 66 which is RegressionChannel1 = RegressionChannel(Closes[0], 6900, Math.Sqrt(std_deviation[0](Closes[0]))); I tried to find information on this compilation error but it's pretty limited.

              Second question. Closes[0] is used when there's additional data series added and you want reference that secondary data series which is a second set of brackets on the Closes object. When running the above RegressionChannel1 line but with Close[0] instead of Closes[0] there is a compile error that says it cannot convert from double to ISeries<double>

              Third should the std_devation = StdDev(ChanPeriod) be relocated to OnBarUpdate if it is to return the standard deviation of the previous 6,900 bars? I.e. if it is in State.DataLoaded will it only be called once to return the standard deviation of the past 6,900 bars upon initialization and then never update?

              Comment


                #8
                Hello itsthefriz,

                Thanks for your reply.

                This line: public int int ChanPeriod = 6900; would need to be public int ChanPeriod = 6900; (This may be just a forum paste error but thought I should mention)

                In the case of this line: RegressionChannel1 = RegressionChannel(Closes[0], ChanPeriod, Math.Sqrt(std_deviation[0](Closes[0]))); Please try: RegressionChannel1 = RegressionChannel(Closes[0], ChanPeriod, Math.Sqrt(std_deviation[0]));

                There may be other errors but check this first and go from there. If you need to post again, I would suggest highlighting the line with the error as the message, "error on line 66" doesn't help when there are no line numbers shown in your pasted code.
                Paul H.NinjaTrader Customer Service

                Comment


                  #9
                  Thanks, that works, I don't know why I put the Closes in that line, that was silly.

                  Regarding the State.DataLoaded vs OnBarUpdate question from above I'm just curious if my understanding of that is correct?

                  Comment


                    #10
                    Hello itsthefriz,

                    Thanks for your reply.

                    To best answer your question I would advise adding a Print statement in OnBarUpdate() and print the current bar value of the std_deviation,

                    I meant to also mention that the line RegressionChannel1 = RegressionChannel(Closes[0], ChanPeriod, Math.Sqrt(std_deviation[0])); should be placed in State.DataLoaded. In OnBarUpDate() it would be creating copies just like before.
                    Paul H.NinjaTrader Customer Service

                    Comment


                      #11
                      Hello itsthefriz,

                      After my last post, I realized this puts you back in the issue of State.DataLoaded does not have access to the current bar data.

                      Rereading through the thread, I was recommending creating a new copy of the regression channel indicator itself and modifying it, not to make a copy of the existing indicator only.

                      Can you clarify what you are trying to do with the Standard deviation as the width value for the regression channel?
                      Paul H.NinjaTrader Customer Service

                      Comment


                        #12
                        So I've been copying a strategy that I used with a previous system into NT8 so that I can automate the strategy because where I was before didn't have the ability to run automated systems. As I copy the strategy over I am noticing that there are calculation differences so my goal is to replicate the previous values of indicators as accurately as possible since they were part of a profitable system.

                        The regression channel appears to be the only one that's giving me a hard time as it's the most prone to calculation differences. Currently with the standard deviation set to 1 I am seeing the upper and lower lines in NT8 at 4406.6 and 4397.3. The Thinkorswim calculation is returning upper and lower lines at 4414.5 and 4391.4.

                        At the minute the difference isn't bad because ES has been range bound for the last few weeks but when ES tends to be trending in a direction the standard deviation gets larger and the upper/lower line tended to be closer when I took the square root of the deviation. At the time when I was comparing values Thinkorswim was registering a standard deviation of approximately 20 and I noticed if you took the square root of the the standard deviation and used that as the input to the regression channel it tended to reflect the values a little closer. Unfortunately that is not the case today as taking the sqrt of 11.6 and using that as the input causes the bands to be much larger.

                        Fortunately your question made me go look at the values since my solution to the calculation differences appears to be more coincidental than an actual solution to the calculation difference. As of right now it appears I'll need to reconsider how much the difference matters. Sorry that the answer had to end up this way.

                        Comment


                          #13
                          Hello itsthefriz,

                          Thanks for your reply.

                          I agree that reconsideration may be the best answer.

                          I cannot answer why there would be such differences between our Regression Chanel and someone elses but our source code is open for inspection/modification. I would tend to look at the indicators parameters to make sure that the regression channel is set up the same on both sides. I believe (I may be incorrect) that TOS allows a selection of either Standard Deviation OR standard Error and that may be one difference as ours from a Ninjascript perspective is only standard deviation based.

                          Paul H.NinjaTrader Customer Service

                          Comment

                          Latest Posts

                          Collapse

                          Topics Statistics Last Post
                          Started by RaddiFX, Today, 07:48 PM
                          0 responses
                          1 view
                          0 likes
                          Last Post RaddiFX
                          by RaddiFX
                           
                          Started by smcllr, Today, 05:41 PM
                          0 responses
                          19 views
                          0 likes
                          Last Post smcllr
                          by smcllr
                           
                          Started by focus333, Today, 05:34 PM
                          0 responses
                          18 views
                          0 likes
                          Last Post focus333  
                          Started by trader3000a, Today, 02:28 PM
                          1 response
                          22 views
                          0 likes
                          Last Post NinjaTrader_Kate  
                          Started by mcosta72, Today, 02:25 PM
                          0 responses
                          19 views
                          0 likes
                          Last Post mcosta72  
                          Working...
                          X