Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

    Is there a way to differentiate 2 streams of sampled data in the next function ?

    General Discussion
    3
    13
    380
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • J
      joeyy last edited by

      Hello All,

      Imagine you have something that looks like that:

      import backtrader as bt
      import backtrader.feeds as btfeeds
      import backtrader.indicators as btind
      
      
      class TimeFrameStrategy(bt.Strategy):
          def __init__(self):
              self.sma_small_tf = btind.SMA(self.data, period=10)
              self.sma_large_tf = btind.SMA(self.data1, period=30)
      
          def next(self):
              print("{}, sma small {:.2f},  sma large {:.2f}".format(self.data.datetime.datetime(), self.sma_small_tf[0], self.sma_large_tf[0]))
      
      def runstrat():
      
          cerebro = bt.Cerebro()
      
          cerebro.addstrategy(TimeFrameStrategy)
      
          datapath = "data/dev.csv"
          data = btfeeds.GenericCSVData(
              dataname=datapath,
              timeframe=bt.TimeFrame.Minutes,
              compression=1,
              format="%Y-%m-%d %H:%M:%S",
          )
      
          cerebro.resampledata(data, timeframe=bt.TimeFrame.Minutes, compression=5)
          cerebro.resampledata(data, timeframe=bt.TimeFrame.Minutes, compression=60)
      
          cerebro.run()
      
      if __name__ == "__main__":
          runstrat()
      

      How can one handle the data differently based on the sampled compression ?
      For instance, I might want to use the 60min for executing trades and the 5min candle for stoploss.

      Any help would be appreciated!

      1 Reply Last reply Reply Quote 0
      • J
        joeyy last edited by

        A more concrete example is having 1 SMA and needing to write logic that's different based on the compression you're viewing

        1 Reply Last reply Reply Quote 0
        • vladisld
          vladisld last edited by

          You may examine the self.data.p.compression and base your logic accordingly.

          1 Reply Last reply Reply Quote 0
          • J
            joeyy last edited by

            thanks for the reply! unfortunately self.data.p.compression always returns the shorter timeframe

            2017-08-18 00:00:00, EMA PRICE 4357.05,  CLOSE PRICE 4286.53, TIME FRAME : 60
            2017-08-18 01:00:00, EMA PRICE 4346.73,  CLOSE PRICE 4243.59, TIME FRAME : 60
            2017-08-18 02:00:00, EMA PRICE 4339.54,  CLOSE PRICE 4267.59, TIME FRAME : 60
            2017-08-18 03:00:00, EMA PRICE 4335.25,  CLOSE PRICE 4292.39, TIME FRAME : 60
            2017-08-18 04:00:00, EMA PRICE 4330.95,  CLOSE PRICE 4287.92, TIME FRAME : 60
            2017-08-18 05:00:00, EMA PRICE 4329.37,  CLOSE PRICE 4313.56, TIME FRAME : 60
            2017-08-18 06:00:00, EMA PRICE 4324.83,  CLOSE PRICE 4279.46, TIME FRAME : 60
            2017-08-18 07:00:00, EMA PRICE 4322.60,  CLOSE PRICE 4300.25, TIME FRAME : 60
            2017-08-18 08:00:00, EMA PRICE 4318.97,  CLOSE PRICE 4282.73, TIME FRAME : 60
            2017-08-18 09:00:00, EMA PRICE 4317.62,  CLOSE PRICE 4304.15, TIME FRAME : 60
            2017-08-18 10:00:00, EMA PRICE 4321.14,  CLOSE PRICE 4356.31, TIME FRAME : 60
            2017-08-18 11:00:00, EMA PRICE 4322.88,  CLOSE PRICE 4340.31, TIME FRAME : 60
            2017-08-18 12:00:00, EMA PRICE 4323.69,  CLOSE PRICE 4331.71, TIME FRAME : 60
            2017-08-18 13:00:00, EMA PRICE 4320.90,  CLOSE PRICE 4293.09, TIME FRAME : 60
            2017-08-18 14:00:00, EMA PRICE 4315.31,  CLOSE PRICE 4259.40, TIME FRAME : 60
            2017-08-18 15:00:00, EMA PRICE 4308.18,  CLOSE PRICE 4236.89, TIME FRAME : 60
            2017-08-18 16:00:00, EMA PRICE 4302.93,  CLOSE PRICE 4250.34, TIME FRAME : 60
            2017-08-18 17:00:00, EMA PRICE 4292.96,  CLOSE PRICE 4193.35, TIME FRAME : 60
            2017-08-18 18:00:00, EMA PRICE 4277.00,  CLOSE PRICE 4117.41, TIME FRAME : 60
            2017-08-18 19:00:00, EMA PRICE 4264.21,  CLOSE PRICE 4136.28, TIME FRAME : 60
            2017-08-18 20:00:00, EMA PRICE 4242.11,  CLOSE PRICE 4021.11, TIME FRAME : 60
            2017-08-18 21:00:00, EMA PRICE 4217.89,  CLOSE PRICE 3975.69, TIME FRAME : 60
            2017-08-18 22:00:00, EMA PRICE 4208.42,  CLOSE PRICE 4113.75, TIME FRAME : 60
            2017-08-18 23:00:00, EMA PRICE 4199.33,  CLOSE PRICE 4108.37, TIME FRAME : 60
            2017-08-19 00:00:00, EMA PRICE 4196.07,  CLOSE PRICE 4163.49, TIME FRAME : 60
            2017-08-19 01:00:00, EMA PRICE 4191.75,  CLOSE PRICE 4148.53, TIME FRAME : 60
            2017-08-19 02:00:00, EMA PRICE 4188.53,  CLOSE PRICE 4156.39, TIME FRAME : 60
            
            1 Reply Last reply Reply Quote 0
            • J
              joeyy last edited by

              correction: the longer timeframe

              1 Reply Last reply Reply Quote 0
              • vladisld
                vladisld last edited by

                In case you have multiple data feeds (not indicators) - you may examine each one: self.datas[0].p.compresson,self.datas[1].p.compression ....

                In case of indicator, examining the compression of the underlying data feed could be more involved, since indicator may use another indicator as it underlying data.

                1 Reply Last reply Reply Quote 0
                • J
                  joeyy last edited by

                  this doesn't work, won't tell you anything about the current tick compression

                  1 Reply Last reply Reply Quote 0
                  • A
                    ab_trader last edited by

                    after you add datas to cerebro they are accessible in the strategy in the same sequence.

                    say, you added non-resampled data, then added data resampled to compression_1, then added data resampled to compression_2. in the strategy self.datas[0] will be non-resampled data, self.datas[1] will be the data resampled to compression_1, and self.datas[2] will be the data resampled to compression_2.

                    @joeyy said in Is there a way to differentiate 2 streams of sampled data in the next function ?:

                    For instance, I might want to use the 60min for executing trades and the 5min candle for stoploss.

                    bt treats all datafeeds separately even they can be for the same ticker. so if you want to open the trade on one data feed, than stop loss or closing order should be applied on the same data feed. otherwise you will have bunch of open trades on both data feeds.

                    • If my answer helped, hit reputation up arrow at lower right corner of the post.
                    • Python Debugging With Pdb
                    • New to python and bt - check this out
                    1 Reply Last reply Reply Quote 1
                    • J
                      joeyy last edited by

                      thank you ab_trader!
                      your answer got me most of the way. I can split the logic in my next function based on the index of the self.datas object.
                      There is one caveat though. If I want to compare the indicator's value to one of the timeframe, it will get evaluated for every tick, and might satisfy a greater than / less than condition in the wrong tick. In other words, if I have an SMA, and 2 candles: one is 5min, the other 60min, and I want to buy based on the SMA cross with the 60min candle, it will still get checked every 5min and the SMA will change in every iteration. Therefore I might be making trades without waiting for the 60min tick.

                      I solved it by adding a flag that checks if the slow indicator value has changed, which stays the same for every fast tick, i.e -

                      if(self.last_candle_ref_price != self.data1.lines.close[0]):
                         if self.sma.lines.sma[0] < self.data1.lines.close[0]:
                            <do something>
                      
                      self.last_candle_ref_price = self.data1.lines.close[0]
                      
                      1 Reply Last reply Reply Quote 0
                      • A
                        ab_trader last edited by

                        next() is called on both timeframes, so at certain point you have two next() calls at the same time - one for 5 min and one for 60 min data feed. i believe bt author proposed to compare length of the strategy and length of the data feeds in order to define what time frame next() is called. i am not able to find the link, but t was somewhere in the docs or in the blog posts.

                        yiour approach can be broken in rare cases when the indicator doesn't changes the value due to prices go steady, for example. approach using lengths seems to me more reliable.

                        • If my answer helped, hit reputation up arrow at lower right corner of the post.
                        • Python Debugging With Pdb
                        • New to python and bt - check this out
                        1 Reply Last reply Reply Quote 1
                        • J
                          joeyy last edited by

                          That makes sense, I do wish to replace my hack with something more sustainable. Perhaps the link you were looking for was this one -
                          https://community.backtrader.com/topic/1329/how-to-determine-if-the-data-is-being-replayed-in-strategy

                          1 Reply Last reply Reply Quote 0
                          • A
                            ab_trader last edited by

                            i didn't find the link, but the idea is to track length of the 60 min data feed. when it changes, it means that one hour bar completed and next bar started. try to do the following in the next() and you will see the pattern:

                            print(len(self.data0), self.data0.close[0], len(self.data1), self.data1.close[0])
                            

                            where data0 id 5 min data and data1 is min data.

                            • If my answer helped, hit reputation up arrow at lower right corner of the post.
                            • Python Debugging With Pdb
                            • New to python and bt - check this out
                            1 Reply Last reply Reply Quote 1
                            • J
                              joeyy last edited by

                              this is def. better, thanks!

                              1 Reply Last reply Reply Quote 0
                              • 1 / 1
                              • First post
                                Last post
                              Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors