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



  • 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:



  • 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!




Log in to reply
 

});