Buy / Sell executing - but not being identified as Trades
-
Hi,
Newbie Backtrader here. First up - thanks for the powerful tool.
Am importing a DF from a CSV and using it to generate buy’s and sells. Backtrader is able to identify Buy/ Sell orders and is also able to execute buys and sells.
However, Backtrader does not seem to be identifying the Buys and Sells as Trades. As a result the pnlplus and the pnlminus columns in the output file are all empty. Also when I plot using cerebro.plot(), I get a blank for the Trades section.
Am sure I am making a noob mistake. Please help.
Thank you.
Regards,
Sangoman -
Attaching Code :
import math import pandas as pd import matplotlib matplotlib.use('QT5Agg') from backtrader.feeds import PandasData from backtrader.feeds import GenericCSVData class PandasData_Signal(PandasData): # Add a 'pe' line to the inherited ones from the base class lines = ('Signal',) # add the parameter to the parameters inherited from the base class params = (('Signal', 18),) import backtrader as bt class MLSignal(bt.Strategy): def log(self, txt, dt=None): dt = dt or self.datas[0].datetime.datetime(0) print('%s,%s' % (dt.isoformat(),txt)) pass def __init__(self): # Keep a reference to the "close" line in the data[0] dataseries self.dataclose = self.datas[0].close self.datasignal = self.datas[0].Signal self.order = None self.trade = None self.buyprice = None self.buycomm = None 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, Price: %.2f, Cost: %.2f, Comm %.2f' % (order.executed.price, order.executed.value, order.executed.comm)) self.buyprice = order.executed.price self.buycomm = order.executed.comm else: # Sell self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' % (order.executed.price, order.executed.value, order.executed.comm)) self.sellprice = order.executed.price self.sellcomm = order.executed.comm self.bar_executed = len(self) elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('Order Canceled/Margin/Rejected') self.order = None def notify_trade(self, trade): if trade.justopened: self.log('----TRADE OPENED----') self.log('Size: {:.3f}, value: {:.3f}'.format(trade.size, trade.value)) elif trade.isclosed: self.log('----TRADE CLOSED----') self.log('Profit: {} Gross {}, Net {}'.format(trade.size, round(trade.pnl,2), round(trade.pnlcomm,2))) else: self.log('NO TRADE') def next(self): self.log(' Close, %.2f' % self.dataclose[0]) self.log(' Signal, %.2f' % self.datasignal[0]) if self.order: return if self.datasignal[0] == 1: self.log('BUY CREATE, %.2f' % self.dataclose[0]) self.order = self.buy() if self.datasignal[0] == -1: self.log('SELL CREATE, %.2f' % self.dataclose[0]) self.order = self.sell() class maxRiskSizer(bt.Sizer): ''' Returns the number of shares rounded down that can be purchased for the max risk tolerance ''' params = (('risk', 0.2),) def _getsizing(self, comminfo, cash, data, isbuy): if isbuy == True: size = math.floor((cash * self.p.risk) / data[0]) else: size = math.floor((cash * self.p.risk) / data[0]) * -1 return size daaata = pd.read_csv("C:/Users/sangramb/Template/Development_Folder/Learning/SuperTrend.csv") daaata['timestamp'] = pd.to_datetime(daaata['timestamp'],format='%Y-%m-%d %H:%M:%S') #print(dataframe.head()) data = PandasData_Signal(dataname=daaata, #dtformat = ('%Y-%m-%d %H:%M:%S'), datetime=0, open=1, high=2, low=3, close=4, #volume=5, #openinterest=-1 Signal=18) cerebro = bt.Cerebro() cerebro.broker.setcash(100000000) print("STARTING CASH VALUE") print(cerebro.broker.getvalue()) cerebro.addsizer(maxRiskSizer) #cerebro.addwriter(bt.WriterFile, csv=args.writercsv, rounding= None) cerebro.addwriter(bt.WriterFile, csv = True, out='signal_strategy_results1.csv') # Set the commission cerebro.broker.setcommission(commission=0.0015) # Set our desired cash start cerebro.adddata(data) # Set our strategy cerebro.addstrategy(MLSignal) cerebro.run() print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue()) print('Final value is %.2f times the initial investment'%(cerebro.broker.getvalue()/100000000)) #cerebro.addanalyzer(btanalyzers.DrawDown, _name='myDrawDown') #cerebro.addanalyzer(btanalyzers.DrawDown, _name='myDrawDown') cerebro.plot(iplot = False)
-
And finally a pic of the Plot
-
@sangoman said in Buy / Sell executing - but not being identified as Trades:
Backtrader does not seem to be identifying the Buys and Sells as Trades
AFAIU Backtrader reports a trade when particular position goes to zero. So if trades are not reported it could be related to the
maxRiskSizer
that you are using.Could you attach the log output of your run and print the order sizes and the position on each order notification?
-
@vladisld - thank you for your prompt and helpful message.
It seems like you were/ are absolutely correct. Here is a short extract from the log file (unable to paste the excel - sorry)
Your hunch was right - the size of the positions is different. Which then leads me to an alternate question. How do I use a position size such that for every long position I am using 20% of my portfolio. And when it comes to closing, I simply square the position.
2021-01-29T00:00:00, Signal, -1.00
2021-01-29T00:00:00,SELL CREATE, 34252.20
2021-01-30T00:00:00,SELL EXECUTED, Price: 34246.28, Size: -308.00, Comm 15821.78
2021-01-30T00:00:00, Close, 34262.88
2021-01-30T00:00:00, Signal, 0.00
2021-01-31T00:00:00, Close, 33092.98
2021-01-31T00:00:00, Signal, 0.00
2021-02-01T00:00:00, Close, 33526.37
2021-02-01T00:00:00, Signal, 0.00
2021-02-02T00:00:00, Close, 35466.24
2021-02-02T00:00:00, Signal, 0.00
2021-02-03T00:00:00, Close, 37618.87
2021-02-03T00:00:00, Signal, 0.00
2021-02-04T00:00:00, Close, 36936.66
2021-02-04T00:00:00, Signal, 0.00
2021-02-05T00:00:00, Close, 38290.24
2021-02-05T00:00:00, Signal, 0.00
2021-02-06T00:00:00, Close, 39186.94
2021-02-06T00:00:00, Signal, 0.00
2021-02-07T00:00:00, Close, 38795.69
2021-02-07T00:00:00, Signal, 0.00
2021-02-08T00:00:00, Close, 46374.87
2021-02-08T00:00:00, Signal, 0.00
2021-02-09T00:00:00, Close, 46420.42
2021-02-09T00:00:00, Signal, 1.00
2021-02-09T00:00:00,BUY CREATE, 46420.42
2021-02-10T00:00:00,BUY EXECUTED, Price: 46420.42, Size: 273.00, Comm 19009.16
2021-02-10T00:00:00, Close, 44807.58