How to backtest a long-short portfolio composition and do rebalancing?
-
Hi everyone, I am new to backtrader and I am working on a project to backtest a portfolio based on equity long-short strategy and do the rebalancing annually.
Here is how my data looks like. Rather than use ticker, I use "gvkey" to identify different stocks. For the trading:
- there are 20 stocks in my portfolio
- the trading frequency is 1 year
- it only consider the close price at June 30th every year
*the final_rank is calculated annual (even for stock that rank 1 in this year, it may rank 20 in next year) - if "final_rank" < 10 in that year , we will establish a long position for that specific stock ; if "final_rank" >10 in that year, we will short sell that stocks. (position = 1 means that we long the stock, vice versa)
- the value of each stock should always equal to 10% of the portfolio value throughout the whole period
And now I get very confused about how should I write my code:
-
I now use only one CSV file which includes all the data of different stocks. Should I separate this data into 20 CSV files and run the backtest one by one? Or if there is any way for backtrader to execute the trading according to the stocks (gvkey)?
-
This strategy seems to be complicated, I am really stuck in writing my strategy, especially the entry signals.
-
Given that my data only consider the close price at 6-30 every year. And if an order created, it seems that this order will be filled at the price on next year. Is there any way for me to make the order filled by the current year price?
Following some parts of my current code, and I only know don't know how to integrate my strategy into my code. Could anyone give me some thoughts about what should i do?
class GenericCSV_Full(GenericCSVData): lines = ('gvkey','final_rank','position',) params =(('gvkey', 2),('final_rank', 4),('position',5), ) # here is what I don't know how to do it class MyStrategy(bt.Strategy): def log(self, txt, dt=None): ... def __init__(self): ... def next(self): if self.data.final_rank[0] < 10 and ???: self.buy() #how can I tell backtrader that after trading, the value of this stocks should equal to 10% of portfolio value? should i use sizer or rebalance function? elif self.data.final_rank[0] > 10 and ???: self.sell() if __name__ == '__main__': cerebro = bt.Cerebro() cerebro.addstrategy(TestStrategy) data = GenericCSV_Full( dataname="../data_final.csv", fromdate=datetime.datetime(2011, 6, 30), todate=datetime.datetime(2020, 6, 30), dtformat=('%Y-%m-%d'), datetime=1, high=-1, low=-1, open=-1, close=3, volume=-1, openinterest=-1 ) cerebro.adddata(data) #Set the initial portfolio cash amount cerebro.broker.setcash(10000000.0) #Set the commission rate cerebro.broker.setcommission(commission=0.001) cerebro.run()
I have tried many attempts but still cannot get thing right :(
Please help. Thank you so much -
@chenys said in How to backtest a long-short portfolio composition and do rebalancing?:
I now use only one CSV file which includes all the data of different stocks. Should I separate this data into 20 CSV files and run the backtest one by one? Or if there is any way for backtrader to execute the trading according to the stocks (gvkey)?
You can combine the tickers together into one portfolio and run it that way. Each ticker you add goes into a list called
datas
in strategy, so you can access the first ticker's dataself.datas[0]
and secondself.datas[1]
etc. For your strategy you will iterate through this list to create two new list, one forlong
and one forshort
.@chenys said in How to backtest a long-short portfolio composition and do rebalancing?:
Given that my data only consider the close price at 6-30 every year. And if an order created, it seems that this order will be filled at the price on next year. Is there any way for me to make the order filled by the current year price?
Try this: cheat-on-close and here
-
@run-out
Does it mean that my data feeds include 20 CSV files, each file only include data for 1 stock? So I need to separate my current file into 20 files? -
@chenys having a separate csv per ticket is a better (and easiest) option in your case IMHO. The alternative would be to develop a custom data feed in order to comply with backtrader's way of working with data.
-
Agreed with @vladisld that this would be easier, but if you want to load the whole file, you can do so as a dataframe, get a list of the tickers (using unique() perhaps), then iterate through the tickers and load your data
-
hi, than you so much for your advice, I already separate my file based on stocks and I amend my data feed code as follow (haven't finish writing strategy yet).
But my output seems very strange, it looks like it backtest the stocks one by one instead of all together. Could you tell me how to backtest all the data feed as a portfolio composition?
from backtrader.feeds import GenericCSVData class dataFeed(btfeeds.GenericCSVData): lines = ('gvkey','final_rank','position',) #params = (('name', index), ) params =(('gvkey', 2),('final_rank', 4),('position',5), ) if __name__ == '__main__': cerebro = bt.Cerebro() datalist = [("AXP.csv"),("AAPL.csv"),("CAT.csv"),("CVX.csv"),("CSCO.csv"),("DIS.csv"),("XOM.csv"),("IBM.csv"),("INTC.csv"),("JNJ.csv"),("KO.csv"),("MMM.csv"),("MRK.csv"),("MSFT.csv"),("NKE.csv"),("PG.csv"),("TRV.csv"),("V.csv"),("WMT.csv"),("AMZN.csv")] for d in range(len(datalist)): data = GenericCSV_Full( dataname=datalist[i], # Do not pass values before this date, same as our final data fromdate=datetime.datetime(2011, 6, 30), # Do not pass values after this date, same as our final data todate=datetime.datetime(2020, 6, 30), dtformat=('%Y-%m-%d'), #for not presented variables (i.e., high, low, open), variable name = -1 #for variables in our data, variable name = index number datetime=1, high=-1, low=-1, open=-1, close=3, volume=-1, openinterest=-1 ) cerebro.adddata(data, name = datalist[i]) #Set the initial portfolio cash amount cerebro.broker.setcash(10000000.0) #Set the commission rate cerebro.broker.setcommission(commission=0.001) print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.run() print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
Output:
Starting Portfolio Value: 10000000.00 Final Portfolio Value: 10000000.00 Starting Portfolio Value: 10000000.00 Final Portfolio Value: 10000000.00 Starting Portfolio Value: 10000000.00 Final Portfolio Value: 10000000.00 ... Starting Portfolio Value: 10000000.00 Final Portfolio Value: 10000000.00 Starting Portfolio Value: 10000000.00 Final Portfolio Value: 10000000.00 Starting Portfolio Value: 10000000.00 Final Portfolio Value: 10000000.00
-
@vladisld
thank you! I have separated my file based on stocks and feed them into backtrader, but the output seems strange (I post my code in another reply).It seems that the code backtest the stock individually, is there any way to make it backtest in portfolio level?
-
I update my code as follows, but the output still not desirable.
Each closing price is getting printed more and more time as the loop continues. what should I do to fix the code?
class dataFeed(btfeeds.GenericCSVData): lines = ('gvkey','final_rank','po',) #params = (('name', index), ) params =(('gvkey', 2),('final_rank', 4),('po',5), ) class TestStrategy(bt.Strategy): def log(self, txt, dt=None): 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 next(self): for d in self.datas: dt, dn = self.datetime.date(), d._name self.log('Close, %.2f' % d.close[0]) if __name__ == '__main__': cerebro = bt.Cerebro() cerebro.addstrategy(TestStrategy) datalist = [("AXP.csv"),("AAPL.csv"),("CAT.csv"),("CVX.csv"),("CSCO.csv"),("DIS.csv"),("XOM.csv"),("IBM.csv"),("INTC.csv"),("JNJ.csv"),("KO.csv"),("MMM.csv"),("MRK.csv"),("MSFT.csv"), ("NKE.csv"),("PG.csv"),("TRV.csv"),("V.csv"),("WMT.csv"),("AMZN.csv")] for i in range(len(datalist)): data = dataFeed( dataname=datalist[i], # Do not pass values before this date, same as our final data fromdate=datetime.datetime(2011, 6, 30), # Do not pass values after this date, same as our final data todate=datetime.datetime(2021, 6, 30), dtformat=('%Y-%m-%d'), #for not presented variables (i.e., high, low, open), variable name = -1 #for variables in our data, variable name = index number datetime=1, high=-1, low=-1, open=-1, close=3, volume=-1, openinterest=-1 ) cerebro.adddata(data, name = datalist[i]) #Set the initial portfolio cash amount cerebro.broker.setcash(10000000.0) #Set the commission rate cerebro.broker.setcommission(commission=0.001) cerebro.addsizer(bt.sizers.PercentSizer, percents=10) print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.run() print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
output:
Starting Portfolio Value: 10000000.00 2011-06-30, Close, 51.70 2012-06-30, Close, 58.21 2013-06-30, Close, 74.76 2014-06-30, Close, 94.87 2015-06-30, Close, 77.72 2016-06-30, Close, 60.76 2017-06-30, Close, 84.24 2018-06-30, Close, 98.00 2019-06-30, Close, 123.44 2020-06-30, Close, 95.20 Final Portfolio Value: 10000000.00 Starting Portfolio Value: 10000000.00 2011-06-30, Close, 51.70 2011-06-30, Close, 51.70 2011-06-30, Close, 335.67 2011-06-30, Close, 335.67 2012-06-30, Close, 58.21 2012-06-30, Close, 58.21 2012-06-30, Close, 584.00 2012-06-30, Close, 584.00 2013-06-30, Close, 74.76 2013-06-30, Close, 74.76 2013-06-30, Close, 396.53 2013-06-30, Close, 396.53 2014-06-30, Close, 94.87 2014-06-30, Close, 94.87 2014-06-30, Close, 92.93 2014-06-30, Close, 92.93 2015-06-30, Close, 77.72 2015-06-30, Close, 77.72 2015-06-30, Close, 125.42 2015-06-30, Close, 125.42 2016-06-30, Close, 60.76 2016-06-30, Close, 60.76 2016-06-30, Close, 95.60 2016-06-30, Close, 95.60 2017-06-30, Close, 84.24 2017-06-30, Close, 84.24 2017-06-30, Close, 144.02 2017-06-30, Close, 144.02 2018-06-30, Close, 98.00 2018-06-30, Close, 98.00 2018-06-30, Close, 185.11 2018-06-30, Close, 185.11 2019-06-30, Close, 123.44 2019-06-30, Close, 123.44 2019-06-30, Close, 197.92 2019-06-30, Close, 197.92 2020-06-30, Close, 95.20 2020-06-30, Close, 95.20 2020-06-30, Close, 364.80 2020-06-30, Close, 364.80 Final Portfolio Value: 10000000.00 Starting Portfolio Value: 10000000.00 2011-06-30, Close, 51.70 2011-06-30, Close, 51.70 2011-06-30, Close, 51.70 2011-06-30, Close, 335.67 2011-06-30, Close, 335.67 2011-06-30, Close, 335.67 2011-06-30, Close, 106.46 2011-06-30, Close, 106.46 2011-06-30, Close, 106.46 2012-06-30, Close, 58.21 2012-06-30, Close, 58.21 2012-06-30, Close, 58.21 2012-06-30, Close, 584.00 2012-06-30, Close, 584.00 2012-06-30, Close, 584.00 2012-06-30, Close, 84.91 2012-06-30, Close, 84.91 2012-06-30, Close, 84.91 2013-06-30, Close, 74.76 2013-06-30, Close, 74.76 2013-06-30, Close, 74.76 2013-06-30, Close, 396.53 2013-06-30, Close, 396.53 2013-06-30, Close, 396.53 2013-06-30, Close, 82.49 2013-06-30, Close, 82.49 2013-06-30, Close, 82.49 2014-06-30, Close, 94.87 2014-06-30, Close, 94.87 2014-06-30, Close, 94.87 2014-06-30, Close, 92.93 2014-06-30, Close, 92.93 2014-06-30, Close, 92.93 2014-06-30, Close, 108.67 2014-06-30, Close, 108.67 2014-06-30, Close, 108.67 2015-06-30, Close, 77.72 2015-06-30, Close, 77.72 2015-06-30, Close, 77.72 2015-06-30, Close, 125.42 2015-06-30, Close, 125.42 2015-06-30, Close, 125.42 2015-06-30, Close, 84.82 2015-06-30, Close, 84.82 2015-06-30, Close, 84.82 2016-06-30, Close, 60.76 2016-06-30, Close, 60.76 2016-06-30, Close, 60.76 2016-06-30, Close, 95.60 2016-06-30, Close, 95.60 2016-06-30, Close, 95.60 2016-06-30, Close, 75.81 2016-06-30, Close, 75.81 2016-06-30, Close, 75.81 2017-06-30, Close, 84.24 2017-06-30, Close, 84.24 2017-06-30, Close, 84.24 2017-06-30, Close, 144.02 2017-06-30, Close, 144.02 2017-06-30, Close, 144.02 2017-06-30, Close, 107.46 2017-06-30, Close, 107.46 2017-06-30, Close, 107.46 2018-06-30, Close, 98.00 2018-06-30, Close, 98.00 2018-06-30, Close, 98.00 2018-06-30, Close, 185.11 2018-06-30, Close, 185.11 2018-06-30, Close, 185.11 2018-06-30, Close, 135.67 2018-06-30, Close, 135.67 2018-06-30, Close, 135.67 2019-06-30, Close, 123.44 2019-06-30, Close, 123.44 2019-06-30, Close, 123.44 2019-06-30, Close, 197.92 2019-06-30, Close, 197.92 2019-06-30, Close, 197.92 2019-06-30, Close, 136.29 2019-06-30, Close, 136.29 2019-06-30, Close, 136.29 2020-06-30, Close, 95.20 2020-06-30, Close, 95.20 2020-06-30, Close, 95.20 2020-06-30, Close, 364.80 2020-06-30, Close, 364.80 2020-06-30, Close, 364.80 2020-06-30, Close, 126.50 2020-06-30, Close, 126.50 2020-06-30, Close, 126.50 Final Portfolio Value: 10000000.00 Starting Portfolio Value: 10000000.00 2011-06-30, Close, 51.70 2011-06-30, Close, 51.70 2011-06-30, Close, 51.70 2011-06-30, Close, 51.70 2011-06-30, Close, 335.67 2011-06-30, Close, 335.67 2011-06-30, Close, 335.67 2011-06-30, Close, 335.67 2011-06-30, Close, 106.46 2011-06-30, Close, 106.46 2011-06-30, Close, 106.46 2011-06-30, Close, 106.46 2011-06-30, Close, 102.84 2011-06-30, Close, 102.84 2011-06-30, Close, 102.84 2011-06-30, Close, 102.84 2012-06-30, Close, 58.21 2012-06-30, Close, 58.21 2012-06-30, Close, 58.21 2012-06-30, Close, 58.21 2012-06-30, Close, 584.00 2012-06-30, Close, 584.00 2012-06-30, Close, 584.00 2012-06-30, Close, 584.00 2012-06-30, Close, 84.91 2012-06-30, Close, 84.91 2012-06-30, Close, 84.91 2012-06-30, Close, 84.91 2012-06-30, Close, 105.50 2012-06-30, Close, 105.50 2012-06-30, Close, 105.50 2012-06-30, Close, 105.50 2013-06-30, Close, 74.76 2013-06-30, Close, 74.76 2013-06-30, Close, 74.76 2013-06-30, Close, 74.76 2013-06-30, Close, 396.53 2013-06-30, Close, 396.53 2013-06-30, Close, 396.53 2013-06-30, Close, 396.53 2013-06-30, Close, 82.49 2013-06-30, Close, 82.49 2013-06-30, Close, 82.49 2013-06-30, Close, 82.49 2013-06-30, Close, 118.34 2013-06-30, Close, 118.34 2013-06-30, Close, 118.34 2013-06-30, Close, 118.34 2014-06-30, Close, 94.87 2014-06-30, Close, 94.87 2014-06-30, Close, 94.87 2014-06-30, Close, 94.87 2014-06-30, Close, 92.93 2014-06-30, Close, 92.93 2014-06-30, Close, 92.93 2014-06-30, Close, 92.93 2014-06-30, Close, 108.67 2014-06-30, Close, 108.67 2014-06-30, Close, 108.67 2014-06-30, Close, 108.67 2014-06-30, Close, 130.55 2014-06-30, Close, 130.55 2014-06-30, Close, 130.55 2014-06-30, Close, 130.55 2015-06-30, Close, 77.72 2015-06-30, Close, 77.72 2015-06-30, Close, 77.72 2015-06-30, Close, 77.72 2015-06-30, Close, 125.42 2015-06-30, Close, 125.42 2015-06-30, Close, 125.42 2015-06-30, Close, 125.42 2015-06-30, Close, 84.82 2015-06-30, Close, 84.82 2015-06-30, Close, 84.82 2015-06-30, Close, 84.82 2015-06-30, Close, 96.47 2015-06-30, Close, 96.47 2015-06-30, Close, 96.47 2015-06-30, Close, 96.47 2016-06-30, Close, 60.76 2016-06-30, Close, 60.76 2016-06-30, Close, 60.76 2016-06-30, Close, 60.76 2016-06-30, Close, 95.60 2016-06-30, Close, 95.60 2016-06-30, Close, 95.60 2016-06-30, Close, 95.60 2016-06-30, Close, 75.81 2016-06-30, Close, 75.81 2016-06-30, Close, 75.81 2016-06-30, Close, 75.81 2016-06-30, Close, 104.83 2016-06-30, Close, 104.83 2016-06-30, Close, 104.83 2016-06-30, Close, 104.83 2017-06-30, Close, 84.24 2017-06-30, Close, 84.24 2017-06-30, Close, 84.24 2017-06-30, Close, 84.24 2017-06-30, Close, 144.02 2017-06-30, Close, 144.02 2017-06-30, Close, 144.02 2017-06-30, Close, 144.02 2017-06-30, Close, 107.46 2017-06-30, Close, 107.46 2017-06-30, Close, 107.46 2017-06-30, Close, 107.46 2017-06-30, Close, 104.33 2017-06-30, Close, 104.33 2017-06-30, Close, 104.33 2017-06-30, Close, 104.33 2018-06-30, Close, 98.00 2018-06-30, Close, 98.00 2018-06-30, Close, 98.00 2018-06-30, Close, 98.00 2018-06-30, Close, 185.11 2018-06-30, Close, 185.11 2018-06-30, Close, 185.11 2018-06-30, Close, 185.11 2018-06-30, Close, 135.67 2018-06-30, Close, 135.67 2018-06-30, Close, 135.67 2018-06-30, Close, 135.67 2018-06-30, Close, 126.43 2018-06-30, Close, 126.43 2018-06-30, Close, 126.43 2018-06-30, Close, 126.43 2019-06-30, Close, 123.44 2019-06-30, Close, 123.44 2019-06-30, Close, 123.44 2019-06-30, Close, 123.44 2019-06-30, Close, 197.92 2019-06-30, Close, 197.92 2019-06-30, Close, 197.92 2019-06-30, Close, 197.92 2019-06-30, Close, 136.29 2019-06-30, Close, 136.29 2019-06-30, Close, 136.29 2019-06-30, Close, 136.29 2019-06-30, Close, 124.44 2019-06-30, Close, 124.44 2019-06-30, Close, 124.44 2019-06-30, Close, 124.44 2020-06-30, Close, 95.20 2020-06-30, Close, 95.20 2020-06-30, Close, 95.20 2020-06-30, Close, 95.20 2020-06-30, Close, 364.80 2020-06-30, Close, 364.80 2020-06-30, Close, 364.80 2020-06-30, Close, 364.80 2020-06-30, Close, 126.50 2020-06-30, Close, 126.50 2020-06-30, Close, 126.50 2020-06-30, Close, 126.50 2020-06-30, Close, 89.23 2020-06-30, Close, 89.23 2020-06-30, Close, 89.23 2020-06-30, Close, 89.23 Final Portfolio Value: 10000000.00 ....
-
@chenys you probably need to just add the data to the cerebro inside the loop. The rest of the logic ( including setting the broker cash, updating sizer and actually running the engine ) should be done only once - outsize the loop.
This way multiple data feed will be tested together within a single instance of the cerebro engine.
You may take a look at the following example of multi data strategy handling as well:
https://www.backtrader.com/blog/posts/2017-04-09-multi-example/multi-example/
-
@vladisld thank you! It works well now
-
from backtrader.feeds import GenericCSVData class dataFeed(btfeeds.GenericCSVData): lines = ('gvkey','final_rank','po',) #params = (('name', index), ) params =(('gvkey', 2),('final_rank', 4),('po',5), ) class TestStrategy(bt.Strategy): def log(self, txt, dt=None): dt = dt or self.datas[0].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 self.po = self.datas[i].po 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(dn + ", " + 'Close, %.2f' % d.close[0] +', ' + 'Position, %.0f' % d.po[0]) if not self.position: if self.po[0] == 1: self.log('BUY CREATE, %.2f' % d.close[0]) self.order = self.buy() if __name__ == '__main__': cerebro = bt.Cerebro() cerebro.addstrategy(TestStrategy) datalist = [("AXP.csv"),("AAPL.csv"),("CAT.csv"),("CVX.csv"),("CSCO.csv"),("DIS.csv"),("XOM.csv"),("IBM.csv"),("INTC.csv"),("JNJ.csv"),("KO.csv"),("MMM.csv"),("MRK.csv"),("MSFT.csv"), ("NKE.csv"),("PG.csv"),("TRV.csv"),("V.csv"),("WMT.csv"),("AMZN.csv")] for i in range(len(datalist)): data = dataFeed( dataname=datalist[i], # Do not pass values before this date, same as our final data fromdate=datetime.datetime(2011, 6, 30), # Do not pass values after this date, same as our final data todate=datetime.datetime(2021, 6, 30), dtformat=('%Y-%m-%d'), #for not presented variables (i.e., high, low, open), variable name = -1 #for variables in our data, variable name = index number datetime=1, high=-1, low=-1, open=-1, close=3, volume=-1, openinterest=-1 ) cerebro.adddata(data, name = datalist[i]) #Set the initial portfolio cash amount cerebro.broker.setcash(10000000.0) #Set the commission rate cerebro.broker.setcommission(commission=0.001) cerebro.addsizer(bt.sizers.PercentSizer, percents=10) print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.run() print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
Starting Portfolio Value: 10000000.00 2011-06-30, AXP.csv, Close, 51.70, Position, 1 2011-06-30, AAPL.csv, Close, 335.67, Position, 2 2011-06-30, CAT.csv, Close, 106.46, Position, 2 2011-06-30, CVX.csv, Close, 102.84, Position, 1 2011-06-30, CSCO.csv, Close, 15.61, Position, 2 2011-06-30, DIS.csv, Close, 39.04, Position, 2 2011-06-30, XOM.csv, Close, 81.38, Position, 1 2011-06-30, IBM.csv, Close, 171.55, Position, 1 2011-06-30, INTC.csv, Close, 22.16, Position, 1 2011-06-30, JNJ.csv, Close, 66.52, Position, 2 2011-06-30, KO.csv, Close, 67.29, Position, 1 2011-06-30, MMM.csv, Close, 94.85, Position, 2 2011-06-30, MRK.csv, Close, 35.29, Position, 2 2011-06-30, MSFT.csv, Close, 26.00, Position, 1 2011-06-30, NKE.csv, Close, 89.98, Position, 2 2011-06-30, PG.csv, Close, 63.57, Position, 2 2011-06-30, TRV.csv, Close, 58.38, Position, 1 2011-06-30, V.csv, Close, 84.26, Position, 1 2011-06-30, WMT.csv, Close, 53.14, Position, 1 2011-06-30, AMZN.csv, Close, 204.49, Position, 2 2012-06-30, AXP.csv, Close, 58.21, Position, 1 2012-06-30, AAPL.csv, Close, 584.00, Position, 2 2012-06-30, CAT.csv, Close, 84.91, Position, 1 2012-06-30, CVX.csv, Close, 105.50, Position, 1 2012-06-30, CSCO.csv, Close, 17.17, Position, 1 2012-06-30, DIS.csv, Close, 48.50, Position, 2 2012-06-30, XOM.csv, Close, 85.57, Position, 1 2012-06-30, IBM.csv, Close, 195.58, Position, 1 2012-06-30, INTC.csv, Close, 26.65, Position, 1 2012-06-30, JNJ.csv, Close, 67.56, Position, 2 2012-06-30, KO.csv, Close, 78.19, Position, 2 2012-06-30, MMM.csv, Close, 89.60, Position, 2 2012-06-30, MRK.csv, Close, 41.75, Position, 2 2012-06-30, MSFT.csv, Close, 30.59, Position, 1 2012-06-30, NKE.csv, Close, 87.78, Position, 1 2012-06-30, PG.csv, Close, 61.25, Position, 2 2012-06-30, TRV.csv, Close, 63.84, Position, 2 2012-06-30, V.csv, Close, 123.63, Position, 1 2012-06-30, WMT.csv, Close, 69.72, Position, 2 2012-06-30, AMZN.csv, Close, 228.35, Position, 2 2013-06-30, AXP.csv, Close, 74.76, Position, 2 2013-06-30, AAPL.csv, Close, 396.53, Position, 1 2013-06-30, CAT.csv, Close, 82.49, Position, 1 2013-06-30, CVX.csv, Close, 118.34, Position, 1 2013-06-30, CSCO.csv, Close, 24.34, Position, 1 2013-06-30, DIS.csv, Close, 63.15, Position, 2 2013-06-30, XOM.csv, Close, 90.35, Position, 1 2013-06-30, IBM.csv, Close, 191.11, Position, 1 2013-06-30, INTC.csv, Close, 24.23, Position, 1 2013-06-30, JNJ.csv, Close, 85.86, Position, 2 2013-06-30, KO.csv, Close, 40.11, Position, 2 2013-06-30, MMM.csv, Close, 109.35, Position, 1 2013-06-30, MRK.csv, Close, 46.45, Position, 2 2013-06-30, MSFT.csv, Close, 34.55, Position, 2 2013-06-30, NKE.csv, Close, 63.68, Position, 2 2013-06-30, PG.csv, Close, 76.99, Position, 2 2013-06-30, TRV.csv, Close, 79.92, Position, 1 2013-06-30, V.csv, Close, 182.75, Position, 2 2013-06-30, WMT.csv, Close, 74.49, Position, 1 2013-06-30, AMZN.csv, Close, 277.69, Position, 2 2014-06-30, AXP.csv, Close, 94.87, Position, 1 2014-06-30, AAPL.csv, Close, 92.93, Position, 1 2014-06-30, CAT.csv, Close, 108.67, Position, 2 2014-06-30, CVX.csv, Close, 130.55, Position, 1 2014-06-30, CSCO.csv, Close, 24.85, Position, 1 2014-06-30, DIS.csv, Close, 85.74, Position, 2 2014-06-30, XOM.csv, Close, 100.68, Position, 1 2014-06-30, IBM.csv, Close, 181.27, Position, 1 2014-06-30, INTC.csv, Close, 30.90, Position, 1 2014-06-30, JNJ.csv, Close, 104.62, Position, 2 2014-06-30, KO.csv, Close, 42.36, Position, 2 2014-06-30, MMM.csv, Close, 143.24, Position, 2 2014-06-30, MRK.csv, Close, 57.85, Position, 2 2014-06-30, MSFT.csv, Close, 41.70, Position, 1 2014-06-30, NKE.csv, Close, 77.55, Position, 2 2014-06-30, PG.csv, Close, 78.59, Position, 2 2014-06-30, TRV.csv, Close, 94.07, Position, 1 2014-06-30, V.csv, Close, 210.71, Position, 2 2014-06-30, WMT.csv, Close, 75.07, Position, 1 2014-06-30, AMZN.csv, Close, 324.78, Position, 2 2015-06-30, AXP.csv, Close, 77.72, Position, 1 2015-06-30, AAPL.csv, Close, 125.42, Position, 1 2015-06-30, CAT.csv, Close, 84.82, Position, 1 2015-06-30, CVX.csv, Close, 96.47, Position, 1 2015-06-30, CSCO.csv, Close, 27.46, Position, 1 2015-06-30, DIS.csv, Close, 114.14, Position, 2 2015-06-30, XOM.csv, Close, 83.20, Position, 2 2015-06-30, IBM.csv, Close, 162.66, Position, 2 2015-06-30, INTC.csv, Close, 30.41, Position, 1 2015-06-30, JNJ.csv, Close, 97.46, Position, 2 2015-06-30, KO.csv, Close, 39.23, Position, 2 2015-06-30, MMM.csv, Close, 154.30, Position, 2 2015-06-30, MRK.csv, Close, 56.93, Position, 1 2015-06-30, MSFT.csv, Close, 44.15, Position, 1 2015-06-30, NKE.csv, Close, 108.02, Position, 2 2015-06-30, PG.csv, Close, 78.24, Position, 2 2015-06-30, TRV.csv, Close, 96.66, Position, 1 2015-06-30, V.csv, Close, 67.15, Position, 2 2015-06-30, WMT.csv, Close, 70.93, Position, 1 2015-06-30, AMZN.csv, Close, 434.09, Position, 2 2016-06-30, AXP.csv, Close, 60.76, Position, 1 2016-06-30, AAPL.csv, Close, 95.60, Position, 1 2016-06-30, CAT.csv, Close, 75.81, Position, 2 2016-06-30, CVX.csv, Close, 104.83, Position, 2 2016-06-30, CSCO.csv, Close, 28.69, Position, 1 2016-06-30, DIS.csv, Close, 97.82, Position, 2 2016-06-30, XOM.csv, Close, 93.74, Position, 2 2016-06-30, IBM.csv, Close, 151.78, Position, 1 2016-06-30, INTC.csv, Close, 32.80, Position, 1 2016-06-30, JNJ.csv, Close, 121.30, Position, 2 2016-06-30, KO.csv, Close, 45.33, Position, 2 2016-06-30, MMM.csv, Close, 175.12, Position, 1 2016-06-30, MRK.csv, Close, 57.61, Position, 2 2016-06-30, MSFT.csv, Close, 51.17, Position, 2 2016-06-30, NKE.csv, Close, 55.20, Position, 1 2016-06-30, PG.csv, Close, 84.67, Position, 2 2016-06-30, TRV.csv, Close, 119.04, Position, 1 2016-06-30, V.csv, Close, 74.17, Position, 1 2016-06-30, WMT.csv, Close, 73.02, Position, 1 2016-06-30, AMZN.csv, Close, 715.62, Position, 2 2017-06-30, AXP.csv, Close, 84.24, Position, 1 2017-06-30, AAPL.csv, Close, 144.02, Position, 1 2017-06-30, CAT.csv, Close, 107.46, Position, 2 2017-06-30, CVX.csv, Close, 104.33, Position, 1 2017-06-30, CSCO.csv, Close, 31.30, Position, 1 2017-06-30, DIS.csv, Close, 106.25, Position, 1 2017-06-30, XOM.csv, Close, 80.73, Position, 2 2017-06-30, IBM.csv, Close, 153.83, Position, 1 2017-06-30, INTC.csv, Close, 33.74, Position, 1 2017-06-30, JNJ.csv, Close, 132.29, Position, 2 2017-06-30, KO.csv, Close, 44.85, Position, 2 2017-06-30, MMM.csv, Close, 208.19, Position, 2 2017-06-30, MRK.csv, Close, 64.09, Position, 2 2017-06-30, MSFT.csv, Close, 68.93, Position, 2 2017-06-30, NKE.csv, Close, 59.00, Position, 1 2017-06-30, PG.csv, Close, 87.15, Position, 2 2017-06-30, TRV.csv, Close, 126.53, Position, 1 2017-06-30, V.csv, Close, 93.78, Position, 2 2017-06-30, WMT.csv, Close, 75.68, Position, 1 2017-06-30, AMZN.csv, Close, 968.00, Position, 2 2018-06-30, AXP.csv, Close, 98.00, Position, 1 2018-06-30, AAPL.csv, Close, 185.11, Position, 1 2018-06-30, CAT.csv, Close, 135.67, Position, 2 2018-06-30, CVX.csv, Close, 126.43, Position, 1 2018-06-30, CSCO.csv, Close, 43.03, Position, 2 2018-06-30, DIS.csv, Close, 104.81, Position, 1 2018-06-30, XOM.csv, Close, 82.73, Position, 1 2018-06-30, IBM.csv, Close, 139.70, Position, 1 2018-06-30, INTC.csv, Close, 49.71, Position, 1 2018-06-30, JNJ.csv, Close, 121.34, Position, 2 2018-06-30, KO.csv, Close, 43.86, Position, 2 2018-06-30, MMM.csv, Close, 196.72, Position, 2 2018-06-30, MRK.csv, Close, 60.70, Position, 2 2018-06-30, MSFT.csv, Close, 98.61, Position, 2 2018-06-30, NKE.csv, Close, 79.68, Position, 2 2018-06-30, PG.csv, Close, 78.06, Position, 1 2018-06-30, TRV.csv, Close, 122.34, Position, 1 2018-06-30, V.csv, Close, 132.45, Position, 1 2018-06-30, WMT.csv, Close, 85.65, Position, 2 2018-06-30, AMZN.csv, Close, 1699.80, Position, 2 2019-06-30, AXP.csv, Close, 123.44, Position, 1 2019-06-30, AAPL.csv, Close, 197.92, Position, 1 2019-06-30, CAT.csv, Close, 136.29, Position, 1 2019-06-30, CVX.csv, Close, 124.44, Position, 1 2019-06-30, CSCO.csv, Close, 54.73, Position, 2 2019-06-30, DIS.csv, Close, 139.64, Position, 1 2019-06-30, XOM.csv, Close, 76.63, Position, 1 2019-06-30, IBM.csv, Close, 137.90, Position, 1 2019-06-30, INTC.csv, Close, 47.87, Position, 1 2019-06-30, JNJ.csv, Close, 139.28, Position, 2 2019-06-30, KO.csv, Close, 50.92, Position, 2 2019-06-30, MMM.csv, Close, 173.34, Position, 1 2019-06-30, MRK.csv, Close, 83.85, Position, 2 2019-06-30, MSFT.csv, Close, 133.96, Position, 2 2019-06-30, NKE.csv, Close, 83.95, Position, 2 2019-06-30, PG.csv, Close, 109.65, Position, 2 2019-06-30, TRV.csv, Close, 149.52, Position, 1 2019-06-30, V.csv, Close, 173.55, Position, 2 2019-06-30, WMT.csv, Close, 110.49, Position, 2 2019-06-30, AMZN.csv, Close, 1893.63, Position, 2 2020-06-30, AXP.csv, Close, 95.20, Position, 1 2020-06-30, AAPL.csv, Close, 364.80, Position, 1 2020-06-30, CAT.csv, Close, 126.50, Position, 1 2020-06-30, CVX.csv, Close, 89.23, Position, 2 2020-06-30, CSCO.csv, Close, 46.64, Position, 1 2020-06-30, DIS.csv, Close, 111.51, Position, 2 2020-06-30, XOM.csv, Close, 44.72, Position, 1 2020-06-30, IBM.csv, Close, 120.77, Position, 1 2020-06-30, INTC.csv, Close, 59.83, Position, 1 2020-06-30, JNJ.csv, Close, 140.63, Position, 2 2020-06-30, KO.csv, Close, 44.68, Position, 1 2020-06-30, MMM.csv, Close, 155.99, Position, 1 2020-06-30, MRK.csv, Close, 77.33, Position, 2 2020-06-30, MSFT.csv, Close, 203.51, Position, 2 2020-06-30, NKE.csv, Close, 98.05, Position, 2 2020-06-30, PG.csv, Close, 119.57, Position, 2 2020-06-30, TRV.csv, Close, 114.05, Position, 1 2020-06-30, V.csv, Close, 193.17, Position, 2 2020-06-30, WMT.csv, Close, 119.78, Position, 2 2020-06-30, AMZN.csv, Close, 2758.82, Position, 2 Final Portfolio Value: 10000000.00
I try to use a very simple strategy to test it, if position = 1, then sell this stock and log this action. But I don't know why nothing happen. Could you please give me some clue?
Thank you so very much
-
@chenys said in How to backtest a long-short portfolio composition and do rebalancing?:
AMZN.csv, Close, 204.49, Position, 2
def __init__(self): for i, d in enumerate(self.datas): self.dataclose = self.datas[i].close self.po = self.datas[i].po
the
self.po
is initialized to thepo
line of the last added data ( AMZN in your case).It seems the
po
column for AMZN is always 2 and not 1 as your logic expects for opening a position.I would suggest to just go over the entire code with a debugger - this way you'll get a better grasp on it.
-
@vladisld
Thanks for your advice and I have now finished writing and testing my code, it can work really well now.But my last step is try to plot the performance. I tried to use the basic plot function, but it seems that it plot the stocks separately (as shown in the portfolio). Is there any way to plot at portfolio value?
Thank you in advance.