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/

    Datafeed with only Close data

    General Code/Help
    1
    3
    172
    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.
    • Casper889
      Casper889 last edited by

      Hi All,

      I have a dataset with only closing prices and a few fundamental variables.

      Data looks something like this:

        Date   Close  quality  momentum  value  growth
      0    2010-02-01   19.19       19         2     17      50
      1    2010-03-01   21.14       24         4     20      55
      2    2010-04-01   22.76       25         1     19      59
      3    2010-05-03   24.22       24         6     17      63
      4    2010-06-01   20.73       21         7     19      60
      
      

      I've created my own CSV class as such:

      class customCSV(bt.feeds.GenericCSVData):
          linesoverride = True  # discard usual OHLC structure
          # datetime must be present and last
          lines = ('close','quality', 'momentum', 'value', 'growth', 'datetime',)
          # datetime (always 1st) and then the desired order for
          params = dict(
              datetime=0,
              close = 1,  # default field pos 1
              quality = 2,  # default field pos 2
              momentum = 3,  # default field pos 3
              value= 4,  # default field pos 4
              growth = 5,  # default field pos 5
              dtformat = '%Y-%m-%d',
              timeframe=bt.TimeFrame.Months,  # fixed the timeframe
              openinterest=-1,)
      

      I create the strategy below, which I basically copied from this article but changed self.ranks to work with my data.

          def log(self, arg):
              print('{} {}'.format(self.datetime.date(), arg))
      
          def __init__(self):
              # calculate 1st the amount of stocks that will be selected
              self.selnum = int(len(self.datas) * self.p.selcperc)
      
              # allocation perc per stock
              # reserve kept to make sure orders are not rejected due to
              # margin. Prices are calculated when known (close), but orders can only
              # be executed next day (opening price). Price can gap upwards
              self.perctarget = (1.0 - self.p.reserve) / self.selnum
      
              # simple rank formula: Quality * a + Momentum * b + Value * c + Growth * d with a + b + c + d = 100 (no short)
              # the highest ranked: high value, high momentum, high quality and high growth
              self.ranks = {d: d.quality*0.25 + d.momentum*0.25 + d.value*0.25 + d.growth*0.25 for d in self.datas}
      
          def next(self):
              # sort data and current rank
              ranks = sorted(
                  self.ranks.items(),  # get the (d, rank), pair
                  key=lambda x: x[1][0],  # use rank (elem 1) and current time "0"
                  reverse=True,  # highest ranked 1st ... please
              )
      
              # put top ranked in dict with data as key to test for presence
              rtop = dict(ranks[:self.selnum])
      
              # For logging purposes of stocks leaving the portfolio
              rbot = dict(ranks[self.selnum:])
      
              # prepare quick lookup list of stocks currently holding a position
              posdata = [d for d, pos in self.getpositions().items() if pos]
      
              # remove those no longer top ranked
              # do this first to issue sell orders and free cash
              for d in (d for d in posdata if d not in rtop):
                  self.log('Leave {} - Rank {:.2f}'.format(d._name, rbot[d][0]))
                  self.order_target_percent(d, target=0.0)
      
              # rebalance those already top ranked and still there
              for d in (d for d in posdata if d in rtop):
                  self.log('Rebal {} - Rank {:.2f}'.format(d._name, rtop[d][0]))
                  self.order_target_percent(d, target=self.perctarget)
                  del rtop[d]  # remove it, to simplify next iteration
      
              # issue a target order for the newly top ranked stocks
              # do this last, as this will generate buy orders consuming cash
              for d in rtop:
                  self.log('Enter {} - Rank {:.2f}'.format(d._name, rtop[d][0]))
                  self.order_target_percent(d, target=self.perctarget)
      
      

      When I run this however, I get the following error:

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

        AttributeError: 'Lines_LineSeries_DataSeries_OHLC_OHLCDateTime_Abst' object has no attribute 'open'

        I've tried cheat_on_close=True but this didn't work. Anyone have any advice on how to work with only Close data?

        Thank you!

        1 Reply Last reply Reply Quote 0
        • Casper889
          Casper889 @Casper889 last edited by

          @Casper889

          Sorry, link is broken. https://community.backtrader.com/topic/2952/datafeed-with-only-close-data/[article](https://www.backtrader.com/blog/2019-07-19-rebalancing-conservative/rebalancing-conservative/)

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