Data feed error



  • Hello,

    I'm trying to implement a custom csv file but i get an error when using it

    my data is like this

    alt text

    so my class for data is the following (hourly)

    class dataFeed(btfeed.GenericCSVData):
        params = (
            ('dtformat', '%Y%m%d %H:%M:%S'),
            ('datetime', 0),
            ('open', 1),
            ('high', 2),
            ('low', 3),
            ('close', 4),
            ('timeframe', bt.TimeFrame.Minutes),
            ('compression', 1)
        )
    

    and then i call it here like that:

    data = dataFeed(dataname='C:/Users/mm/Desktop/GLD.csv')
    

    and i get the error:

    Traceback (most recent call last):
      File "C:/Users/mm/PycharmProjects/AlgoTrading/Algo09.py", line 143, in <module>
        cerebro.run()
      File "C:\Users\mm\AppData\Local\Programs\Python\Python36-32\lib\site-packages\backtrader\cerebro.py", line 1127, in run
        runstrat = self.runstrategies(iterstrat)
      File "C:\Users\mm\AppData\Local\Programs\Python\Python36-32\lib\site-packages\backtrader\cerebro.py", line 1209, in runstrategies
        data.preload()
      File "C:\Users\mm\AppData\Local\Programs\Python\Python36-32\lib\site-packages\backtrader\feed.py", line 685, in preload
        while self.load():
      File "C:\Users\mm\AppData\Local\Programs\Python\Python36-32\lib\site-packages\backtrader\feed.py", line 476, in load
        _loadret = self._load()
      File "C:\Users\mm\AppData\Local\Programs\Python\Python36-32\lib\site-packages\backtrader\feed.py", line 707, in _load
        return self._loadline(linetokens)
      File "C:\Users\mm\AppData\Local\Programs\Python\Python36-32\lib\site-packages\backtrader\feeds\csvgeneric.py", line 148, in _loadline
        csvfield = linetokens[csvidx]
    IndexError: list index out of range
    

    And my whole code is the following:

    import backtrader as bt
    import backtrader.feeds as btfeed
    from datetime import datetime
    
    class dataFeed(btfeed.GenericCSVData):
        params = (
            ('dtformat', '%Y%m%d %H:%M:%S'),
            ('datetime', 0),
            ('open', 1),
            ('high', 2),
            ('low', 3),
            ('close', 4),
            ('timeframe', bt.TimeFrame.Minutes),
            ('compression', 60)
        )
    
    class ADXDIPlus3(bt.Indicator):
    
        lines = ('high', 'low', 'close')
    
        params = (('period', 14),)
    
        def __init__(self):
    
            self.ADX = bt.indicators.DirectionalMovementIndex(period=self.p.period)
    
            self.lines.high = self.ADX.DIplus
            self.lines.low = self.ADX.DIplus
            self.lines.close = self.ADX.DIplus
    
    class ADXDIMinus3(bt.Indicator):
    
        lines = ('high', 'low', 'close')
    
        params = (('period', 14),)
    
        def __init__(self):
    
            self.ADX = bt.indicators.DirectionalMovementIndex(period=self.p.period)
    
            self.lines.high = self.ADX.DIminus
            self.lines.low = self.ADX.DIminus
            self.lines.close = self.ADX.DIminus
    
    class firstStrategy(bt.Strategy):
    
        def log(self, txt, dt=None):
            ''' Logging function fot this strategy'''
            dt = dt or self.datas[0].datetime.date(0)
            print('%s, %s' % (dt.isoformat(), txt))
    
        def __init__(self):
            self.dataclose = self.datas[0].close
            self.order = None
    
            self.stoch = bt.talib.STOCH(self.data.high, self.data.low, self.data.close, fastk_period=14, slowk_period=3, slowd_period=3)
    
            self.ADXPlus3 = ADXDIPlus3(period=14)
            self.ADXMinus3 = ADXDIMinus3(period=14)
    
            self.CCI_ADXPlus = bt.indicators.CommodityChannelIndex(self.ADXPlus3, period=20)
            self.CCI_ADXMinus = bt.indicators.CommodityChannelIndex(self.ADXMinus3, period=20)
    
    
        def notify_order(self, order):
            if order.status in [order.Submitted, order.Accepted]:
                # Buy/Sell order submitted/accepted to/by broker - Nothing to do
                return
    
            # Check if an order has been completed
            # Attention: broker could reject order if not enougth cash
            if order.status in [order.Completed]:
                if order.isbuy():
                    self.log(
                        'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                        (order.executed.price,
                         order.executed.value,
                         order.executed.comm))
    
                    self.buyprice = order.executed.price
                    self.buycomm = order.executed.comm
                else:  # Sell
                    self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                             (order.executed.price,
                              order.executed.value,
                              order.executed.comm))
    
                self.bar_executed = len(self)
    
            elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                self.log('Order Canceled/Margin/Rejected')
    
            # Write down: no pending order
            self.order = None
    
        def notify_trade(self, trade):
            if not trade.isclosed:
                return
    
            self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                     (trade.pnl, trade.pnlcomm))
    
        def next(self):
            self.log('Close, %.2f' % self.dataclose[0])
    
            if self.order:
                return
    
            # Check if we are in the market
            if not self.position:
    
                # Not yet ... we MIGHT BUY if ...
                if self.stoch[-1] < 20 and self.CCI_ADXPlus[0] > 100:
                    self.log('BUY CREATE, %.2f' % self.dataclose[0])
                    self.order = self.buy(exectype=bt.Order.StopTrail, trailpercent=0.05)
    
            else:
    
                if self.stoch[-1] > 80 and self.CCI_ADXMinus[0] > 100:
                    self.log('SELL CREATE, %.2f' % self.dataclose[0])
                    self.order = self.sell(exectype=bt.Order.StopTrail, trailpercent=0.05)
    
    
    if __name__ == '__main__':
        # Create a cerebro entity
        cerebro = bt.Cerebro()
        startcash = 10000
    
        # Add a strategy
        cerebro.addstrategy(firstStrategy)
    
        # Create a Data Feed
        data = dataFeed(dataname='C:/Users/mm/Desktop/GLD.csv')
        # Add the Data Feed to Cerebro
        cerebro.adddata(data)
    
        # Set our desired cash start
        cerebro.broker.setcash(startcash)
    
        # Set the commission
        cerebro.broker.setcommission(commission=0.0005)
    
        # Add a sizer
        cerebro.addsizer(bt.sizers.PercentSizer, percents=50)
    
        cerebro.run()
        # Print out the starting conditions
        print('Starting Portfolio Value: %.2f' % startcash)
    
        # Get final portfolio Value
        portvalue = cerebro.broker.getvalue()
        pnl = portvalue - startcash
    
        # Print out the final result
        print('Final Portfolio Value: ${}'.format(portvalue))
        print('P/L: ${}'.format(pnl))
    
        # Finally plot the end results
        cerebro.plot()
    


  • Data feed class need to be re-written as follows:

    class dataFeed(btfeed.GenericCSVData):
        params = (
            ('dtformat', '%Y%m%d %H:%M:%S'),
            ('datetime', 0),
            ('open', 1),
            ('high', 2),
            ('low', 3),
            ('close', 4),
            ('volume', -1),
            ('openinterest', -1)
        )
    

    and then data initiated as follows:

        data = dataFeed(dataname=path_to_file_with_quotes, timeframe=bt.TimeFrame.Minutes, compression=60)
    


  • @ab_trader said in Data feed error:

            ('volume', -1),
            ('openinterest', -1)
    

    Just wanted to point that out from the excellent and spot on answer by @ab_trader, that is probably the key part, i.e.: telling the feed which fields are actually not present.



  • @ab_trader @Paska-Houso

    Thanks a lot guys, it works :)


Log in to reply
 

Looks like your connection to Backtrader Community was lost, please wait while we try to reconnect.