Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    1. Home
    2. livecat
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/
    L
    • Profile
    • Following 0
    • Followers 0
    • Topics 4
    • Posts 7
    • Best 1
    • Groups 0

    livecat

    @livecat

    1
    Reputation
    140
    Profile views
    7
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    livecat Unfollow Follow

    Best posts made by livecat

    • Multiple stocks

      Apologies in advance if this is covered elsewhere. I have looked but haven't been able to find a satisfying answer.

      To keep things as simple as possible, I have a test strategy that merely prints out the date and name of each instrument and the length of the corresponding data line for each period (days in this case). Using this post as a starting point: https://www.backtrader.com/blog/2019-05-20-momentum-strategy/momentum-strategy/

      class TestStrategy(bt.Strategy):

         def __init__(self):
             # Keep a reference to the "close" line in the data[0] dataseries
             # self.dataclose = self.datas[0].close
             self.d_with_len = []
      
         def prenext(self):
             self.data_list = [d for d in self.datas if len(d)]
             self.next()
      
         def nextstart(self):
             # This is called exactly ONCE, when next is 1st called and defaults to
             # call `next`
             self.data_list = self.datas  # all data sets fulfill the guarantees now
      
         def next(self):
             # Evetually do something cool. But for now show us what you've got.
             for d in self.data_list:
                 print('%s  %s  %d' % (d.datetime.date(0), d._name, len(d)))
      

      On the assumption that we are trying to model real market conditions as a closely as possible; it seems fair to assume that if an instrument isn't being traded, it shouldn't be visible to us. At the same time we do want to see data for instruments that are being traded.

      For test purposes here are two small, overlapping samples:

      0d668be6-0f6f-4590-b335-e6825ad7935f-image.png

      e6298d75-ec76-4752-903b-7bb3188cb52a-image.png

      Given this data and the assumption above, the expect output would be this:

      Starting Portfolio Value: 100000.00
      2017-03-31 LLOY 1
      2017-04-03 LLOY 2
      2017-04-04 TSCO 1
      2017-04-04 LLOY 3
      2017-04-05 TSCO 2
      2017-04-05 LLOY 4
      2017-04-06 TSCO 3
      2017-04-06 LLOY 5
      2017-04-07 TSCO 4
      2017-04-10 TSCO 5
      Final Portfolio Value: 100000.00

      But what is actually output is this:

      2017-03-31 LLOY 1
      2017-04-03 LLOY 2
      2017-04-05 TSCO 2
      2017-04-05 LLOY 4
      2017-04-06 TSCO 3
      2017-04-06 LLOY 5
      2017-04-07 TSCO 4
      2017-04-06 LLOY 5
      2017-04-10 TSCO 5
      2017-04-06 LLOY 5

      It seems to work as expected for the first section. But at the tail the LLOY data is still being displayed. Even after the feed is exhausted.

      How is possible to prevent this occurring? And as a wider question is there an established pattern for working with multiple instruments?

      Thanks

      posted in General Code/Help
      L
      livecat

    Latest posts made by livecat

    • Dividends

      Hi,

      Is there a recomended BT method for dealing with dividends?

      For example if dealing with a portfolio of share, dividends paid on a certain date are added to the portfolio balance.

      Thx

      posted in Indicators/Strategies/Analyzers
      L
      livecat
    • RE: dates

      Thanks. Perfect

      posted in General Code/Help
      L
      livecat
    • dates

      print(d.datetime.get(0, size=3))

      outputs something like this:

      array('d', [736422.9999999999, 736423.9999999999, 736424.9999999999])

      The part of the number before the decimal point seems to be an ordinal date representation. But i'm not sure about the part after the decimal point.

      How would one convert this back into a datetime?

      Thanks.

      posted in General Code/Help
      L
      livecat
    • RE: Multiple stocks

      @ab_trader Thanks for answering.

      Here is the solution I came up with, in case it's useful to someone in the future.

      If anyone knows of a better solution I'd love to hear about it.

      from collections import defaultdict
      
      import backtrader as bt
      
      
      class MultiDataFeedStrategy(bt.Strategy):
          """
          A base class for stratagies that use multiple data feeds
          It allows iteration over only those data lines that have
          valid data.
      
          usage:
      
          from MultiDataFeedStrategy import MultiDataFeedStrategy
      
          class TestStrategy(MultiDataFeedStrategy):
      
              def __init__(self):
                  super().__init__()
      
              def next(self):
                  for d in self.valid_datas():
                      print('%s  %s  %d' % (d.datetime.date(0), d._name, len(d)))
          """
          # params = ()
      
          def __init__(self):
              super().__init__()
              # Define a dict that stores the previous len(d)
              # off all the datalines.
              self.previous_len_d = defaultdict(lambda: 0)
              self.max_param = self.get_max_numeric_param()
      
          def prenext(self):
              self.next()
      
          def next(self):
              # Overide me
              pass
      
          def valid_datas(self):
              feeds = [d for d in self.datas if self.feed_available(d) and len(d) >= self.max_param]
              return feeds
      
          def feed_available(self, d):
              # if the previous len(d) equals the current len(d)
              # it means either the data hasn't started yet or it has ended
              if self.previous_len_d[d._name] == len(d):
                  return False
              else:
                  self.previous_len_d[d._name] = len(d)
                  return True
      
          def get_max_numeric_param(self):
              numeric_params = []
              for param in self.params._getvalues():
                  # just in case a param can't convert to a number.
                  try:
                      numeric_params.append(float(param))
                  except ValueError:
                      pass
              return round(max(numeric_params))
      

      Then:

      from MultiDataFeedStrategy import MultiDataFeedStrategy
      
      class TestStrategy(MultiDataFeedStrategy):
      
          def __init__(self):
              super().__init__()
      
          def next(self):
              for d in self.valid_datas():
                  print('%s  %s  %d' % (d.datetime.date(0), d._name, len(d)))
      

      Seems to work so far.

      posted in General Code/Help
      L
      livecat
    • Multiple stocks

      Apologies in advance if this is covered elsewhere. I have looked but haven't been able to find a satisfying answer.

      To keep things as simple as possible, I have a test strategy that merely prints out the date and name of each instrument and the length of the corresponding data line for each period (days in this case). Using this post as a starting point: https://www.backtrader.com/blog/2019-05-20-momentum-strategy/momentum-strategy/

      class TestStrategy(bt.Strategy):

         def __init__(self):
             # Keep a reference to the "close" line in the data[0] dataseries
             # self.dataclose = self.datas[0].close
             self.d_with_len = []
      
         def prenext(self):
             self.data_list = [d for d in self.datas if len(d)]
             self.next()
      
         def nextstart(self):
             # This is called exactly ONCE, when next is 1st called and defaults to
             # call `next`
             self.data_list = self.datas  # all data sets fulfill the guarantees now
      
         def next(self):
             # Evetually do something cool. But for now show us what you've got.
             for d in self.data_list:
                 print('%s  %s  %d' % (d.datetime.date(0), d._name, len(d)))
      

      On the assumption that we are trying to model real market conditions as a closely as possible; it seems fair to assume that if an instrument isn't being traded, it shouldn't be visible to us. At the same time we do want to see data for instruments that are being traded.

      For test purposes here are two small, overlapping samples:

      0d668be6-0f6f-4590-b335-e6825ad7935f-image.png

      e6298d75-ec76-4752-903b-7bb3188cb52a-image.png

      Given this data and the assumption above, the expect output would be this:

      Starting Portfolio Value: 100000.00
      2017-03-31 LLOY 1
      2017-04-03 LLOY 2
      2017-04-04 TSCO 1
      2017-04-04 LLOY 3
      2017-04-05 TSCO 2
      2017-04-05 LLOY 4
      2017-04-06 TSCO 3
      2017-04-06 LLOY 5
      2017-04-07 TSCO 4
      2017-04-10 TSCO 5
      Final Portfolio Value: 100000.00

      But what is actually output is this:

      2017-03-31 LLOY 1
      2017-04-03 LLOY 2
      2017-04-05 TSCO 2
      2017-04-05 LLOY 4
      2017-04-06 TSCO 3
      2017-04-06 LLOY 5
      2017-04-07 TSCO 4
      2017-04-06 LLOY 5
      2017-04-10 TSCO 5
      2017-04-06 LLOY 5

      It seems to work as expected for the first section. But at the tail the LLOY data is still being displayed. Even after the feed is exhausted.

      How is possible to prevent this occurring? And as a wider question is there an established pattern for working with multiple instruments?

      Thanks

      posted in General Code/Help
      L
      livecat
    • RE: Accessing analysers in a strategy

      Thanks for that. I had read that but couldn't quite get to grips with the correct way of accessing an analysers' final value from within the strategy, since the stop method of the analyser needs be called before rets contains any value. eg.

      ipdb> self.analyzers.mysharpe.rets
      OrderedDict()

      ipdb> self.analyzers.mysharpe.stop()

      ipdb> self.analyzers.mysharpe.rets
      OrderedDict([('sharperatio', 0.0018162347783349845)])

      But self.analyzers.mysharpe.stop() only gets called after self.stop()

      So I guess my question is: Is there a recommended way to do what I'm trying to do that I have completely missed?
      Best.

      posted in Indicators/Strategies/Analyzers
      L
      livecat
    • Accessing analysers in a strategy

      Hi, are there any examples anywhere of using an analyser within a strategy that can reference? I'd like to print analyser results from the stratagys' stop() method when running Cerebro.optstrategy.

      Thanks

      posted in Indicators/Strategies/Analyzers
      L
      livecat