For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

Pandas data feed extension issue



  • Hi all, I am new to use BT. I hope to ask a question related to pandas data feed extension. I was hoping to add a column called "delta" into my data feed but after I run the codes, it always generates the AttributeError: 'Lines_LineSeries_DataSeries_OHLC_OHLCDateTime_Abst' object has no attribute 'delta'.

    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    
    import datetime  # For datetime objects
    import backtrader as bt
    import pandas as pd
    import numpy as np
    
    %matplotlib inline
    
    
    
    
    
    
    class PandasData_delta(bt.feeds.PandasData):
        Lines = ('delta',)
        params = (('delta',7),)
    
        
    
        
    
    
    
    class MyStrategy(bt.Strategy):
    
        def __init__(self):
            self.delta = self.datas[0].delta
            if (self.delta > self.datas.high and self.delta != 0):
                self.buy_signal = 1
                
            elif (self.delta < self.datas.low and self.delta != 0):
                self.sell_signal = -1
    
        def next(self):
            if not self.position and self.buy_signal[0] == 1:
                self.order = self.buy()
    
            if self.getposition().size < 0 and self.buy_signal[0] == 1:
                self.order = self.close()
                self.order = self.buy()
    
            if not self.position and self.sell_signal[0] == 1:
                self.order =self.sell()
    
            if self.getposition().size > 0 and self.sell_signal[0] == 1:
                self.order = self.close()
                self.order = self.sell()
    
    
    
    if __name__ == '__main__':
        # 1. Create a cerebro
        cerebro = bt.Cerebro(stdstats=True)
    
        # 2. Add data feed
        # 2.1 Creat a data feed
        
        # load dataframe
    
        data = pd.read_csv('futures.csv')
        data['datetime'] = pd.to_datetime(data['datetime'])
        data.set_index('datetime', inplace=True)
        data = PandasData_delta(dataname=data,
                                        fromdate=datetime.datetime(2017, 8, 1),
                                        todate=datetime.datetime(2017, 8, 10)
                                        )
        
        # 2.2Add the Data Feed to Cerebro
        cerebro.adddata(data, name='data')
        # 3 Add strategy
        cerebro.addstrategy(MyStrategy)
    
    
        # broker setting
        cerebro.broker.setcash(1![alt text](image url)00000.0)
        cerebro.addobserver(bt.observers.Benchmark, data=data)
    
    
        # 4. Run
        cerebro.run()
    
        pos = cerebro.broker.getposition(data)
        print('size:', pos.size)
        print('price:', pos.price)
    
        print('value:', cerebro.broker.get_value())
        print('cash:', cerebro.broker.get_cash())
    
        # 5.Plot result
        cerebro.plot(style='candle')
    
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-23-28e9b1b66044> in <module>
         82 
         83     # 4. Run
    ---> 84     cerebro.run()
         85 
         86     pos = cerebro.broker.getposition(data)
    
    ~\Anaconda3\lib\site-packages\backtrader\cerebro.py in run(self, **kwargs)
       1125             # let's skip process "spawning"
       1126             for iterstrat in iterstrats:
    -> 1127                 runstrat = self.runstrategies(iterstrat)
       1128                 self.runstrats.append(runstrat)
       1129                 if self._dooptimize:
    
    ~\Anaconda3\lib\site-packages\backtrader\cerebro.py in runstrategies(self, iterstrat, predata)
       1215             sargs = self.datas + list(sargs)
       1216             try:
    -> 1217                 strat = stratcls(*sargs, **skwargs)
       1218             except bt.errors.StrategySkipError:
       1219                 continue  # do not add strategy to the mix
    
    ~\Anaconda3\lib\site-packages\backtrader\metabase.py in __call__(cls, *args, **kwargs)
         86         _obj, args, kwargs = cls.donew(*args, **kwargs)
         87         _obj, args, kwargs = cls.dopreinit(_obj, *args, **kwargs)
    ---> 88         _obj, args, kwargs = cls.doinit(_obj, *args, **kwargs)
         89         _obj, args, kwargs = cls.dopostinit(_obj, *args, **kwargs)
         90         return _obj
    
    ~\Anaconda3\lib\site-packages\backtrader\metabase.py in doinit(cls, _obj, *args, **kwargs)
         76 
         77     def doinit(cls, _obj, *args, **kwargs):
    ---> 78         _obj.__init__(*args, **kwargs)
         79         return _obj, args, kwargs
         80 
    
    <ipython-input-23-28e9b1b66044> in __init__(self)
         27 
         28     def __init__(self):
    ---> 29         self.delta = self.datas[0].delta
         30         if (self.delta > self.datas.high and self.delta != 0):
         31             self.buy_signal = 1
    
    ~\Anaconda3\lib\site-packages\backtrader\lineseries.py in __getattr__(self, name)
        459         # in this object if we set an attribute in this object it will be
        460         # found before we end up here
    --> 461         return getattr(self.lines, name)
        462 
        463     def __len__(self):
    
    AttributeError: 'Lines_LineSeries_DataSeries_OHLC_OHLCDateTime_Abst' object has no attribute 'delta'
    

    excel.png

    I could not figure out the reason why and I tried to follow answers from previous posts but I am still stuck. Please help if possible. Thank you very much.



  • @Tsz-Chun-Leung said in Pandas data feed extension issue:

    I think your index number is wrong. datetime goes into the index, so then with zero base your index should be 5...

    open 0
    high 1
    low 2
    close 3
    volume 4
    delta 5
    


  • @run-out

    Do you mean I should change to this?

    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    
    import datetime  # For datetime objects
    import backtrader as bt
    import pandas as pd
    import numpy as np
    
    %matplotlib inline
    
    
    
    
    
    
    class PandasData_delta(bt.feeds.PandasData):
        Lines = ('delta',)
        params = (('open', 0),
            ('high', 1),
            ('low', 2),
            ('close', 3),
            ('volume', 4),
            ('delta', 5),      
        )
        
      
    
        
    
        
    
    
    
    class MyStrategy(bt.Strategy):
    
        def __init__(self):
            self.delta = self.datas[0].delta
            if (self.delta > self.datas.high and self.delta != 0):
                self.buy_signal = 1
                
            elif (self.delta < self.datas.low and self.delta != 0):
                self.sell_signal = -1
    
        def next(self):
            if not self.position and self.buy_signal[0] == 1:
                self.order = self.buy()
    
            if self.getposition().size < 0 and self.buy_signal[0] == 1:
                self.order = self.close()
                self.order = self.buy()
    
            if not self.position and self.sell_signal[0] == 1:
                self.order =self.sell()
    
            if self.getposition().size > 0 and self.sell_signal[0] == 1:
                self.order = self.close()
                self.order = self.sell()
    
    
    
    if __name__ == '__main__':
        # 1. Create a cerebro
        cerebro = bt.Cerebro(stdstats=True)
    
        # 2. Add data feed
        # 2.1 Creat a data feed
        
        # load dataframe
    
        data = pd.read_csv('hs_day.csv')
        data['datetime'] = pd.to_datetime(data['datetime'])
        data.set_index('datetime', inplace=True)
        data = PandasData_delta(dataname=data,
                                        fromdate=datetime.datetime(2017, 8, 1),
                                        todate=datetime.datetime(2017, 8, 10)
                                        )
        
        # 2.2Add the Data Feed to Cerebro
        cerebro.adddata(data, name='data')
        # 3 Add strategy
        cerebro.addstrategy(MyStrategy)
    
    
        # broker setting
        cerebro.broker.setcash(200000.0)
        cerebro.broker.setcommission(commission=50,margin=130000,mult=50)
        cerebro.broker.set_slippage_fixed(fixed=3)
        cerebro.addobserver(bt.observers.Benchmark, data=data)
    
    
        # 4. Run
        cerebro.run()
    
        pos = cerebro.broker.getposition(data)
        print('size:', pos.size)
        print('price:', pos.price)
    
        print('value:', cerebro.broker.get_value())
        print('cash:', cerebro.broker.get_cash())
    
        # 5.Plot result
        cerebro.plot(style='candle')
    

    But still this generates the same error...



  • Have a look at the following. Your init criteria is wrong because you are treating a line object like a scalar. The following if statement won't work the way you intend because self.delta, self.datas.low, are line objects, and you are returnint self.buy_signal = 1, which is a scalar result. You probably want bt.If and bt.And combined. See my solution below.

    if (self.delta > self.datas.high and self.delta != 0):
                self.buy_signal = 1
    

    Full running code

    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    
    import datetime  # For datetime objects
    import backtrader as bt
    import pandas as pd
    
    
    class PandasData_delta(bt.feeds.PandasData):
        lines = ('delta',)
        params = (('delta', 5),)
    
    
    class MyStrategy(bt.Strategy):
    
        def __init__(self):
            self.delta = self.datas[0].delta
            self.buy_signal = bt.If(bt.And(self.delta > self.datas[0].high, self.delta != 0), 1, 0)
            self.sell_signal = bt.If(bt.And(self.delta < self.datas[0].low, self.delta != 0), -1, 0)
    
        def log(self, txt, dt=None):
            """ Logging function for this strategy"""
    
            dt = dt or self.datas[0].datetime.datetime(0)
            print("%s, %s" % (dt, txt))
    
    
        def print_signal(self):
            """Print to termianl ohlcv and the buy/sell signals."""
            self.log(
                "o {:.2f} \th {:.2f} \tl {:.2f} \tc {:.2f}\tv {:9.0f}\t  delta {:.2f}".format(  # \tbuy {}\tsell{}".format(
                    self.data.open[0],
                    self.data.high[0],
                    self.data.low[0],
                    self.data.close[0],
                    self.data.volume[0],
                    self.delta[0],
                )
            )
    
        def next(self):
            self.print_signal()
    
            if not self.position and self.buy_signal[0] == 1:
                self.order = self.buy()
    
            if self.getposition().size < 0 and self.buy_signal[0] == 1:
                self.order = self.close()
                self.order = self.buy()
    
            if not self.position and self.sell_signal[0] == 1:
                self.order = self.sell()
    
            if self.getposition().size > 0 and self.sell_signal[0] == 1:
                self.order = self.close()
                self.order = self.sell()
    
    if __name__ == '__main__':
        # 1. Create a cerebro
        cerebro = bt.Cerebro(stdstats=True)
    
        # 2. Add data feed
        # 2.1 Creat a data feed
    
        # load dataframe
    
        data = pd.read_csv('data/futures.csv')
        data['datetime'] = pd.to_datetime(data['datetime'])
        data.set_index('datetime', inplace=True)
        data = PandasData_delta(dataname=data,
                                fromdate=datetime.datetime(1990, 1, 1),
                                todate=datetime.datetime(1990, 8, 10)
                                )
    
        # 2.2Add the Data Feed to Cerebro
        cerebro.adddata(data, name='data')
        # 3 Add strategy
        cerebro.addstrategy(MyStrategy)
    
        # broker setting
        cerebro.broker.setcash(100000)
        cerebro.addobserver(bt.observers.Benchmark, data=data)
    
        # 4. Run
        cerebro.run()
    
        pos = cerebro.broker.getposition(data)
        print('size:', pos.size)
        print('price:', pos.price)
    
        print('value:', cerebro.broker.get_value())
        print('cash:', cerebro.broker.get_cash())
    
        # 5.Plot result
        cerebro.plot(style='candle')
    


  • Thank you so much run-out. This works!! I need sometime to review the documentation to fully understand but thank you so much !


Log in to reply
 

});