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(100000.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'
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
-
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 !