For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/
Log and Plot show different results
-
Hi, I have a problem with the plotting of my indicator. I theory the program should buy or sell when the price gets to one of the bolloinger bands. This seems to work as you can see in the logs, but when I plot the results the program seems to be buying at random moments way before or after the lines match. Is this a problem in my code or is there something wrong with backtrader?
import backtrader as bt import backtrader.feeds as btfeed import backtrader.analyzers as btanalyzers import datetime # from datetime import datetime def printTradeAnalysis(analyzer): ''' Function to print the Technical Analysis results in a nice format. ''' # Get the results we are interested in total_open = analyzer.total.open total_closed = analyzer.total.closed total_won = analyzer.won.total total_lost = analyzer.lost.total win_streak = analyzer.streak.won.longest lose_streak = analyzer.streak.lost.longest pnl_net = round(analyzer.pnl.net.total, 2) strike_rate = (total_won / total_closed) * 100 # Designate the rows h1 = ['Total Open', 'Total Closed', 'Total Won', 'Total Lost'] h2 = ['Strike Rate', 'Win Streak', 'Losing Streak', 'PnL Net'] r1 = [total_open, total_closed, total_won, total_lost] r2 = [strike_rate, win_streak, lose_streak, pnl_net] # Check which set of headers is the longest. if len(h1) > len(h2): header_length = len(h1) else: header_length = len(h2) # Print the rows print_list = [h1, r1, h2, r2] row_format = "{:<15}" * (header_length + 1) print("Trade Analysis Results:") for row in print_list: print(row_format.format('', *row)) 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''' dt = dt or self.datas[0].datetime.datetime(0) print('%s, %s' % (dt.isoformat(), txt)) def __init__(self): # self.dataclose = self.datas[0].close self.bb_inds = dict() for d in self.datas: bb = bt.ind.BollingerBands(d, period=21, devfactor=2.0, movav=bt.ind.MovAv.Simple) self.bb_inds[d] = dict() self.bb_inds[d]["bb_top"] = bb.top self.bb_inds[d]["bb_bot"] = bb.bot print(self.bb_inds) 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 d.close[0] < self.bb_inds[d]["bb_bot"][0]: print(d.close[0]) print(self.bb_inds[d]["bb_bot"][0]) print(self.log('T ime, %.2f' [0])) # BUY, BUY, BUY!!! (with default parameters) self.log('BUY CREATE, %.2f' % d.close[0]) # current close less than previous close # if self.dataclose[-1] < self.dataclose[-2]: # previous close less than the previous close # Keep track of the created order to avoid a 2nd order #self.order = self.buy() self.buy(data = d) # Already in the market ... we might sell if d.close[0] > self.bb_inds[d]["bb_top"][0]: # SELL, SELL, SELL!!! (with all possible default parameters) self.log('SELL CREATE, %.2f' % d.close[0]) # Keep track of the created order to avoid a 2nd order #self.order = self.sell() self.sell(data = d) if self.position.size != 0: if self.data.datetime.time() > datetime.time(20, 59): self.close(exectype=bt.Order.Stop, data=d, size=pos) self.log('CLOSE CREAR´TE, %.2f' % d.close[0]) if __name__ == '__main__': # Create a cerebro entity cerebro = bt.Cerebro(stdstats = False) startcash = 1000 # Add a strategy cerebro.addstrategy(firstStrategy) # cerebro.addindicator(BollingerBands) # cerebro.addanalyzer(btanalyzers.TradeAnalyzer, _name ='mytrades') cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name="ta") 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")]""" for i in range(len(datalist)): data = dataFeed(dataname=datalist[i], timeframe=bt.TimeFrame.Minutes, compression=1,) 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.addobservermulti( bt.observers.BuySell, barplot=True, bardist=0.001) # buy / sell arrows #cerebro.run() #thestrats = cerebro.run() #thestrat = thestrats[0] strategies = cerebro.run() firstStrategy = strategies[0] # 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('TradeAnalysis:', thestrat.analyzers.mytrades.get_analysis()) # print the analyzers printTradeAnalysis(firstStrategy.analyzers.ta.get_analysis()) print('Final Portfolio Value: ${}'.format(portvalue)) print('P/L: ${}'.format(pnl)) cerebro.plot()