Creating Bid/Ask pandas datafeed error
-
Hi,
I'm quite new to backtrader framework and trying to figure out how to create pandas bid/ask datafeed. Below is my data frame.
print(df.head())RateBid RateAsk RateDateTime 2018-12-03 00:00:00.340 1.13501 1.13503 2018-12-03 00:00:00.590 1.13499 1.13503 2018-12-03 00:00:00.857 1.13498 1.13502 2018-12-03 00:00:01.107 1.13498 1.13503 2018-12-03 00:00:01.340 1.13499 1.13503
Implementation:
import backtrader as bt import backtrader.feeds as btfeeds import backtrader.indicators as btind class BidAskDF(btfeeds.PandasData): linesoverride = True # discard usual OHLC structure # datetime must be present and last lines = ('RateBid', 'RateAsk', 'datetime') # datetime (always 1st) and then the desired order for params = ( #('datetime', 0), # inherited from parent class ('RateBid', 1), # default field pos 1 ('RateAsk', 2), # default field pos 2 ) class St(bt.Strategy): def next(self): print('hello') #dtstr = self.data.datetime.datetime().isoformat() #txt = '%4d: %s - Bid %.4f - %.4f Ask' % ( # (len(self), dtstr, self.data.bid[0], self.data.ask[0])) #if self.p.sma: # txt += ' - SMA: %.4f' % self.sma[0] #print(txt) cerebro = bt.Cerebro() data = BidAskDF(dataname = df, timeframe=bt.TimeFrame.Ticks, datetime='RateDateTime') cerebro.adddata(data) # Add the 1st data to cerebro # Add the strategy to cerebro cerebro.addstrategy(St) cerebro.run()
Im getting following error ,
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Users\admin\AppData\Local\Programs\Python\Python36-32\lib\threading.py", line 916, in _bootstrap_inner
self.run()
File "C:\Users\admin\AppData\Local\Programs\Python\Python36-32\lib\threading.py", line 864, in run
self._target(*self._args, **self._kwargs)
File "E:\Projects\Learning\Backtester\price_handler.py", line 59, in create_df
self.ready_cb()
File "E:\Projects\Learning\Backtester\gui.3.py", line 88, in cb_df_ready
data = BidAskDF(dataname = df, timeframe=bt.TimeFrame.Ticks, datetime='RateDateTime')
File "E:\Projects\Learning\Backtester\backtrader\metabase.py", line 88, in call
_obj, args, kwargs = cls.doinit(_obj, *args, **kwargs)
File "E:\Projects\Learning\Backtester\backtrader\metabase.py", line 78, in doinit
_obj.init(*args, **kwargs)
File "E:\Projects\Learning\Backtester\backtrader\feeds\pandafeed.py", line 181, in init
defmapping = getattr(self.params, datafield)
AttributeError: 'AutoInfoClass_LineRoot_LineMultiple_LineSeries_Dat' object has no attributecould someone please point out what caused the error?
-
@gaya0007 said in Creating Bid/Ask pandas datafeed error:
AttributeError: 'AutoInfoClass_LineRoot_LineMultiple_LineSeries_Dat' object has no attribute
Part of the error message is clearly missing.
On the other hand, what you are trying to do was only done with the
GenericCSVData
feed. The implementation ofPandasData
may have problems as it heavily depends on the correspondence of the defined lines and the parameters and the parameters from the base class cannot be nullified. -
@backtrader Thank you for that information. I will try to use the csv to create the datafeed instead of pandas df.
-
I've been reading the forum and I realised I could import the 'RateBid', 'RateAsk', 'RateDateTime' as seperate lines in the padas DF and use them. If someone is looking for similar method this might be useful.
class PandasData_Extend(btfeeds.PandasData): lines = ('RateDateTime','RateBid','RateAsk') params = ( ('datetime', None), ('RateDateTime', -1), ('RateBid', -1), ('RateAsk', -1) ) btfeeds.PandasData.datafields = btfeeds.PandasData.datafields + [u'RateDateTime', u'RateBid', u'RateAsk'] class Ticker(bt.Strategy): def __init__(self): self.tick_ength = 0 self.order = None self.first_tick = True 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 enough cash if order.status in [order.Completed]: if order.isbuy(): self.log('BUY EXECUTED, %.2f' % order.executed.price) elif order.issell(): self.log('SELL EXECUTED, %.2f' % order.executed.price) 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 next(self): if self.tick_ength != len(self.datas[0]): self.tick_ength = len(self.datas[0]) print(self.data.datetime.datetime(), self.data.RateBid[0], self.data.RateAsk[0]) tick_data = PandasData_Extend(dataname = tick_df) self.cerebro.adddata(tick_data) # Add the 1st data to cerebro
-
@gaya0007 said in Creating Bid/Ask pandas datafeed error:
btfeeds.PandasData.datafields = btfeeds.PandasData.datafields + [u'RateDateTime', u'RateBid', u'RateAsk']
As pointed out many times before, this is no longer needed. Don't use it.
The rest is simply the standard extension mechanism.
-
Thank you for that, removed it!
-
@backtrader This is a common requirement. I don't understand why PandasData doesn't add a custom_ fields parameter to meet this feature.