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

How to structure Multi-Time Frame Strategy

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

    How to structure Multi-Time Frame Strategy

    NT Forum,

    Please confirm / correct my understanding, in the situation where:
    - you have a single time frame single instrument strategy,
    - the strategy is applied to multiple time frames on a single instrument (e.g. CL 09-17 15min, 30min, and 60min), and
    - you want each time frame strategy to operate independently of other time frames.

    Where the strategy is applied as three separate strategies in the Strategies Tab (Running a NinjaScriptStrategy from the Strategies Tab), you will run into issues Syncing Account Positions under the default setting "Wait until flat". For example, where the 60min strategy is long one contract in Account Position and Strategy Position and both 30min and 15min Strategy Positions are flat, the 30min and 15min strategies will not execute trades until the 60min Strategy Position (and thus Account Position) are flat.

    To combat this issue, one option is to relax the Strategy StartBehavior. However, I would prefer not to relax this setting.

    I believe, another option is to combine (and hard-code) the three time frames into one strategy (Multi-Time Frame & Instruments). That is, a multi time frame single instrument strategy. In this situation, the combined Strategy Position of the three time frames would match the Account Position.
    Please confirm / correct.

    As a second question, in creating a multi time frame single instrument strategy, is it better to have BarsArray[0] = 60min, BarsArray[1] = 15min, and BarsArray[2] = 5min. Or alternatively, in reverse order, BarsArray[0] = 5min, BarsArray[1] = 15min, and BarsArray[2] = 60min? What are the pros / cons?

    Thanks
    Shannon

    #2
    Hello,

    Thank you for the post.

    For your first question, it is advisable to combine the 3 strategies into a single script so they all have the same information to work from. Being that you are using NT8, you do have a few other options as well. If you really want to run multiple instances of a script you can change the start behavior as you noted to make the scripts assume an account position as an example. This is only for the start of the scripts though, to have them be aware of the account and not a virtual position later you could use PositionAccount:



    For the second question, this really depends on how you want the script to perform according to your goals.
    In the case where you have BarsArray[0] = 60min, BarsArray[1] = 15min, and BarsArray[2] = 5min,
    This would not be much different than BarsArray[0] = 5min, BarsArray[1] = 15min, and BarsArray[2] = 60min.

    In the first case, your chart will update at a rate of 60 minutes, and then BarsInProgress would be called in the order of 2, 1, 0 in most cases as the more granular series will be called more frequently. The opposite is true of the second case, your chart will update at a rate of 5 minutes and then BIP will be called in the reverse order.

    It would also depend if you are using Calculate OnBarClose or OnEachTick. If you are doing tick by tick, the chart updates won't matter so much because it would be updated frequently. If you are using OnBarClose with the 60 minute as the primary, it would take 60 minutes to complete bars and perform some updates. These are items to consider on how it would influence your goals.

    You can use Print statements to see each of these situations in more detail from your end. I would suggest creating the script as you noted, and then just add a Print to OnBarUpdate like the following:

    Print(CurrentBar + " " + BarsInProgress);

    There is also a good description relating to how bars are built in the platform which outlines multi-instrument scripts:




    I look forward to being of further assistance.
    JesseNinjaTrader Customer Service

    Comment


      #3
      Jesse,

      Thank you for your response.

      As I understand it, under Calculate OnBarClose, regardless of the order of BarsArrays (ie. [0] = 5min, [1] = 15min and [2] = 60min, or conversely [0] = 60min, [1] = 15min and [2] = 5min), the currently developing 60min bar, and indictors based off it, will be "inaccessible" until bar close. For example, when evaluating at 11:25am, code would evaluate the 5min bar ended 11:25am, the 15min bar ended 11:15am and the 60min bar ended 11am, thus ignoring the partial 15min bar (11:15-11:25am) and partial 60min bar (11:00-11:25am).

      As I understand it, to evaluate the 5min bar, partial 15min bar, and partial 60min bar all as at 11:25am would require Calculate OnEachTick.

      As I would like evaluate only at or near the end of the 5min bar and whatever partial 15min and 60min bars, I believe I require an Indicator (or similar) to gauge when a bar is at or near it's end. Please find attached such an Indicator, BarTime. BarTime returns true when the DataSeries is seconds from bar close (and always true for historical Series). However, BarTime fails to return true where no BarUpdate occurs in the closing seconds of a bar. With this failing, this Indicator is not suitable for my purposes. As I understand, any indicator dependant on OnBarUpdate will have this failing.

      As such, a Strategy would require a TriggerCustomEvent or preferably access to such an Event via an AddOn.

      I have tried, and failed, to use the logic within the NT8 Indicator @BarTimer and theme from TriggerCustomEvent to craft appropriate code.

      Is there any existing Strategy example you could point me toward?

      As always, thanks
      Shannon
      Attached Files

      Comment


        #4
        Hello,

        Thank you for the reply.

        You are correct, a bar is inaccessible until it has closed when using OnBarClose. the [0] BarsAgo would represent the last Closed bar of a series. Indicator values would only be inaccessible if they cannot be calculated due to limited data, for example, if the 60-minute series has not closed at least the minimum bars required by the indicator using that series to calculate. Otherwise, the indicator would report the calculated value including the last closed bar for that series.

        If you want to access data from series that have not yet closed the bar you want, you would need to utilize a OnEachTick in order to see data before the bar closes or the last price of that series. You can use properties like IsFirstTickOfBar to know if the series has closed a bar to simulate OnBarClose in this situation: https://ninjatrader.com/support/help...FirstTickOfBar

        If you would like to evaluate only at or near the end of the 5min bar, I would likely suggest using OnEachTick and IsFirstTickOfBar to know when the 5 minute bar closes. You could then access the other series at that point to calculate an indicator or do other actions.

        Regarding the TriggerCustomEvent comment, I am unsure what you were asking here but I would not suggest using TriggerCustomEvent for this use. This is specifically used to sync NinjaScript properties when you are using out of sync methods like a button click and event handler. This is not helpful for data series and their syncing using OnBarClose/OnEachTick.

        Please let me know if I may be of additional assistance.
        JesseNinjaTrader Customer Service

        Comment


          #5
          hey buddy,

          I honestly did not read the posted responses, so hopefully, this is not an old suggestion. However, I find my computer runs FASTER if I simply run multiple strategies of the same strategy with different time frames, and I think that would solve your issue since they run independently from each other. It requires a human interaction, but I don't have it enter/exit trades by itself, and rather use as a suggestion. If a 240-minute strategy is saying short, and I'm not a day trader, then I'm ignoring a 60-minute strategy saying long.

          However, if you want to do that test in real time within one strategy, and have larger time frame override a smaller time frame, I honestly have not sorted out that evil myself - for the simple issue: the larger timeframe strategy would not yield a result before a smaller time frame will, so can you say then "erase" what happened, and remove the previous entry.

          Didn't seem to logically make sense, so I'm running same strat on different time frames.

          Comment


            #6
            Jesse,

            Thank you for your very complete response.

            I understand combining Calculate OnEachTick and IsFirstTickOfBar (and referring to Bar[1], as opposed to Bar[0]) will behave identical to Calculate OnBarClose (and referring to Bar[0]). Noting, it is possible to evaluate all BarsArrays OnEachTick (thus removing the import of the order of BarsInProgress), and then execute on IsFristTickOfBar.

            Regarding TriggerCustomEvent, please elaborate on why this approach may not be suitable to raise an event before the close of a Bar. For example, assuming the method TimerEventProcessor is raised at an appropriate time (i.e. before close of bar), could you TriggerCustomEvent MyCustomHandler which in turn triggers OnBarUpdate() (or similar)? Would all internal indexers be up-to-date?

            Code:
            protected override void OnBarUpdate()
            {
              // OnBarUpdate() only runs as bars are processed, which is not guaranteed to occur at a specific interval
            }
             
            // This is the method to run when the timer is raised.
            private void TimerEventProcessor(Object myObject, EventArgs myEventArgs)
            {
              // Do not process your code here but instead call the TriggerCustomEvent() method
              // and process your code in the custom handler method 
              // Doing so ensures all internal indexers are up-to-date
              var barsSeriesIndex = 0;
              var state = Close[0];
              TriggerCustomEvent(MyCustomHandler, barsSeriesIndex, state);
            }
            
            private void MyCustomHandler(object state)
            {
              OnBarUpdate();
            }
            Thanks again
            Shannon
            Last edited by Shansen; 10-12-2017, 06:39 PM.

            Comment


              #7
              Hello,

              Thank you for the reply.

              In this context, this would still only allow the script to see the same data as the last time the platform had called OnBarUpdate. Only the platforms events will be able to call OnBarUpdate correctly and update all the inherited properties to the instrument that called OnBarUpdate. Calling this randomly like a void method will execute the logic you have, but would have no effect on the overall scripts state or properties. It would really only be suggested to have the platform call OnBarUpdate for bar events.

              The example in the help guide does show using a timer which then has a custom method for that timer. This is an out of sync method so it would need TriggerCustomEvent to ensure any NinjaScript properties used in that method are populated with the current value when accessed. This is similar to trying to access NinjaScript properties from OnRender.

              I look forward to being of further assistance.
              JesseNinjaTrader Customer Service

              Comment

              Latest Posts

              Collapse

              Topics Statistics Last Post
              Started by funk10101, Today, 09:43 PM
              0 responses
              6 views
              0 likes
              Last Post funk10101  
              Started by pkefal, 04-11-2024, 07:39 AM
              11 responses
              37 views
              0 likes
              Last Post jeronymite  
              Started by bill2023, Yesterday, 08:51 AM
              8 responses
              44 views
              0 likes
              Last Post bill2023  
              Started by yertle, Today, 08:38 AM
              6 responses
              26 views
              0 likes
              Last Post ryjoga
              by ryjoga
               
              Started by algospoke, Yesterday, 06:40 PM
              2 responses
              24 views
              0 likes
              Last Post algospoke  
              Working...
              X