@hexabraum I just tested it with more than 2 Stocks and it seems like only the very first stock in the ticker list gets bought or sold even though the order was created for another stock.
Posts made by HexaBraum
-
RE: Indicator for multiple Datafeeds
-
RE: Indicator for multiple Datafeeds
@run-out Thank you very much, that helps a lot. Now there is still the problem that the buy and sell signals dont really work. It seems like the order is created for stock1 but executed for stock2. When I use your code from above with my CSV Datafiles and i dont log the closing price but only the orders this is my output:
2021-02-18, BUY CREATE, 43.76
2021-02-18, BUY EXECUTED, 101.03
Starting Portfolio Value: 10000.00
Final Portfolio Value: $10001.244999999999
P/L: $1.2449999999989814Furthermore the buys and sells dont get displayed in the plot. Unfortunately I can´t find the mistake/s.
-
RE: Indicator for multiple Datafeeds
@run-out Thanks but that doesn´t really help me. My problem is that the Bollinger Bands only work for my first data feed and also only get plotted for my first datafeed. Therefore the other securities are not in consideration to be bought or sold.
-
RE: Indicator for multiple Datafeeds
@run-out 4 securities equal one backtest, however each datafeed gets a technical analysis and therefore buy or sell signals for this exact security. I want the backtrader to backtest my strategy on multiple datafeeds. I hope that i got the point :D
-
Indicator for multiple Datafeeds
The Bollinger Bands work for the first Data File, so it´s the only one where Orders are created.
Additionally the buys and sells dont get displayed, Where is the mistake?
Thanks for your help :)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), ('volume', 5), ('openinterest', -1) ) class BollingerBands(bt.Indicator): lines = ('topband', 'botband') params = (('period', 21), ('devfactor', 2.0), ('movav', bt.ind.MovAv.Simple),) plotinfo = dict(subplot=False) def _plotlabel(self): plabels = [self.p.period, self.p.devfactor] plabels += [self.p.movav] * self.p.notdefault('movav') return plabels def __init__(self): bb = bt.ind.BollingerBands( period=self.p.period, devfactor=self.p.devfactor, movav=self.p.movav) 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 bb = bt.ind.BollingerBands( period=21, devfactor=2.0, movav=bt.ind.MovAv.Simple) self.lines.topband = bb.top self.lines.botband = bb.bot 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): for d in self.datas: dt, dn = self.datetime.date(), d._name pos = self.getposition(d).size # Simply log the closing price of the series from the reference self.log('Close, %.2f' % d.close[0]) # Check if an order is pending ... if yes, we cannot send a 2nd one #if self.order: # return # Check if we are in the market if not self.position: if self.dataclose[0] < self.lines.botband[0]: # current close less than previous close # if self.dataclose[-1] < self.dataclose[-2]: # previous close less than the previous close # BUY, BUY, BUY!!! (with default parameters) self.log('BUY CREATE, %.2f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.buy() # Already in the market ... we might sell if self.dataclose[0] > self.lines.topband[0]: # SELL, SELL, SELL!!! (with all possible default parameters) self.log('SELL CREATE, %.2f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.sell() if __name__ == '__main__': # Create a cerebro entity cerebro = bt.Cerebro() startcash = 10000 # Add a strategy cerebro.addstrategy(firstStrategy) cerebro.addindicator(BollingerBands) datalist = [("AM.ATVI.csv"), ("AM.MO.csv"), ("AM.GM.csv"), ("AM.CL.csv")] """ , ("AM.FDX.csv"), ("AM.NAKD.csv"), ("AM.NVDA.csv"), ("AM.OCGN.csv"), ("AM.ON.csv") , ("AM.PDD.csv"), ("AM.PLUG.csv"), ("AM.QCOM.csv"), ("AM.MDLZ.csv"), ("AM.ADP.csv") , ("AM.C.csv"), ("AM.AZN.csv"), ("AM.PEP.csv"), ("AM.ORCL.csv"), ("AM.QTT.csv") , ("AM.RUN.csv"), ("AM.SABR.csv"), ("AM.SNDL.csv"), ("AM.TSLA.csv"), ("AM.UAL.csv") , ("AM.UXIN.csv"), ("AM.WEN.csv"), ("AM.WFC.csv"), ("AM.YY.csv"), ("AM.ZNGA.csv") , ("AM.MSFT.csv"), ("AM.AAPL.csv"), ("AM.FB.csv"), ("AM.BABA.csv"), ("AM.TSM.csv") , ("AM.V.csv"), ("AM.JPM.csv"), ("AM.JNJ.csv") , ("AM.PG.csv"), ("AM.BAC.csv"), ("AM.INTC.csv"), ("AM.VZ.csv"), ("AM.NKE.csv") , ("AM.XOM.csv"), ("AM.KO.csv"), ("AM.T.csv"), ("AM.PFE.csv") , ("AM.MRK.csv"), ("AM.MS.csv"), ("AM.AAL.csv"), ("AM.GT.csv"), ("AM.UBER.csv") , ("AM.AMD.csv"), ("AM.PDD.csv"), ("AM.CVX.csv")]""" #the files are located in my python project for i in range(len(datalist)): data = dataFeed(dataname=datalist[i], timeframe=bt.TimeFrame.Minutes, compression=60) cerebro.adddata(data, name=datalist[i]) # 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)) cerebro.plot()
-
RE: Adding Multiple CSV data feeds
@hexabraum i fixed it by deleting the for loop in the log function.
-
RE: Adding Multiple CSV data feeds
@run-out Thanks for your answer. Now each csv file is being considered but the logging output looks really weird.
[...] 2021-02-18, SELL CREATE, 102.31 2021-02-18, SELL CREATE, 102.31 2021-02-18, SELL CREATE, 102.31 2021-02-18, SELL CREATE, 102.31 2021-02-18, SELL EXECUTED, 102.30 2021-02-18, SELL EXECUTED, 102.30 2021-02-18, SELL EXECUTED, 102.30 2021-02-18, SELL EXECUTED, 102.30 2021-02-18, Close, 102.22 2021-02-18, Close, 102.22 2021-02-18, Close, 102.22 2021-02-18, Close, 102.22 2021-02-18, Close, 43.62 2021-02-18, Close, 43.62 2021-02-18, Close, 43.62 2021-02-18, Close, 43.62 2021-02-18, Close, 52.13 2021-02-18, Close, 52.13 2021-02-18, Close, 52.13 2021-02-18, Close, 52.13 2021-02-18, Close, 78.65 2021-02-18, Close, 78.65 2021-02-18, Close, 78.65 2021-02-18, Close, 78.65 2021-02-18, Close, 102.21 2021-02-18, Close, 102.21 2021-02-18, Close, 102.21 2021-02-18, Close, 102.21 2021-02-18, Close, 43.62 2021-02-18, Close, 43.62 2021-02-18, Close, 43.62 2021-02-18, Close, 43.62 2021-02-18, Close, 52.10 2021-02-18, Close, 52.10 2021-02-18, Close, 52.10 2021-02-18, Close, 52.10 2021-02-18, Close, 78.63 2021-02-18, Close, 78.63 2021-02-18, Close, 78.63 2021-02-18, Close, 78.63 2021-02-18, Close, 102.28 2021-02-18, Close, 102.28 2021-02-18, Close, 102.28 2021-02-18, Close, 102.28 2021-02-18, Close, 43.61 2021-02-18, Close, 43.61 2021-02-18, Close, 43.61 2021-02-18, Close, 43.61 2021-02-18, Close, 52.14 2021-02-18, Close, 52.14 2021-02-18, Close, 52.14 2021-02-18, Close, 52.14 2021-02-18, Close, 78.71 2021-02-18, Close, 78.71 2021-02-18, Close, 78.71 2021-02-18, Close, 78.71 Starting Portfolio Value: 10000.00 Final Portfolio Value: $9979.769999999993 P/L: $-20.23000000000684
Each closing price, selling action and buying action is getting printed 4 times when my datalist includes 4 Files, 3 times when it includes 3 files etc.
-
Adding Multiple CSV data feeds
Hello guys I am currently starting with backtrader and i am struggling to add multiple data feeds.
The following code ends with exit code 0 however does only consider the very last csv file ("AM.CVX.csv"). Thanks for your help and I know that this is a very basic question but everyone has to start somewhere.
P.S. The example in the documentation did not really help me.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), ('volume', 5), ('openinterest', -1) ) class firstStrategy(bt.Strategy): def log(self, txt, dt=None): ''' Logging function fot this strategy''' for i, d in enumerate(self.datas): dt = dt or self.datas[i].datetime.date(0) print('%s, %s' % (dt.isoformat(), txt)) def __init__(self): for i, d in enumerate(self.datas): self.dataclose = self.datas[i].close 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): for i, d in enumerate(self.datas): self.dataclose = self.datas[i].close dt, dn = self.datetime.date(), d._name pos = self.getposition(d).size # Simply log the closing price of the series from the reference self.log('Close, %.2f' % self.dataclose[0]) # Check if an order is pending ... if yes, we cannot send a 2nd one #if self.order: # return # Check if we are in the market if not self.position: # Not yet ... we MIGHT BUY if ... if self.dataclose[0] < self.dataclose[-1]: # current close less than previous close if self.dataclose[-1] < self.dataclose[-2]: # previous close less than the previous close # BUY, BUY, BUY!!! (with default parameters) self.log('BUY CREATE, %.2f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.buy() else: # Already in the market ... we might sell if len(self) >= (self.bar_executed + 5): # SELL, SELL, SELL!!! (with all possible default parameters) self.log('SELL CREATE, %.2f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.sell() if __name__ == '__main__': # Create a cerebro entity cerebro = bt.Cerebro() startcash = 10000 # Add a strategy cerebro.addstrategy(firstStrategy) datalist = [("AM.ATVI.csv"), ("AM.MO.csv"), ("AM.GM.csv"), ("AM.CL.csv") , ("AM.FDX.csv"), ("AM.NAKD.csv"), ("AM.NVDA.csv"), ("AM.OCGN.csv"), ("AM.ON.csv") , ("AM.PDD.csv"), ("AM.PLUG.csv"), ("AM.QCOM.csv"), ("AM.MDLZ.csv"), ("AM.ADP.csv") , ("AM.C.csv"), ("AM.AZN.csv"), ("AM.PEP.csv"), ("AM.ORCL.csv"), ("AM.QTT.csv") , ("AM.RUN.csv"), ("AM.SABR.csv"), ("AM.SNDL.csv"), ("AM.TSLA.csv"), ("AM.UAL.csv") , ("AM.UXIN.csv"), ("AM.WEN.csv"), ("AM.WFC.csv"), ("AM.YY.csv"), ("AM.ZNGA.csv") , ("AM.MSFT.csv"), ("AM.AAPL.csv"), ("AM.FB.csv"), ("AM.BABA.csv"), ("AM.TSM.csv") , ("AM.V.csv"), ("AM.JPM.csv"), ("AM.JNJ.csv") , ("AM.PG.csv"), ("AM.BAC.csv"), ("AM.INTC.csv"), ("AM.VZ.csv"), ("AM.NKE.csv") , ("AM.XOM.csv"), ("AM.KO.csv"), ("AM.T.csv"), ("AM.PFE.csv") , ("AM.MRK.csv"), ("AM.MS.csv"), ("AM.AAL.csv"), ("AM.GT.csv"), ("AM.UBER.csv") , ("AM.AMD.csv"), ("AM.PDD.csv"), ("AM.CVX.csv")] #the files are located in my python project for i in range(len(datalist)): data = dataFeed(dataname=datalist[i], timeframe=bt.TimeFrame.Minutes, compression=60) cerebro.adddata(data, name=datalist[i]) # 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))