Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

    How to backtest a long-short portfolio composition and do rebalancing?

    Indicators/Strategies/Analyzers
    3
    13
    1413
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • C
      chenys last edited by

      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

      Screenshot 2021-08-04 164519.jpg

      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

      1 Reply Last reply Reply Quote 0
      • run-out
        run-out last edited by

        @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 data self.datas[0] and second self.datas[1] etc. For your strategy you will iterate through this list to create two new list, one for long and one for short.

        @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

        RunBacktest.com

        C 1 Reply Last reply Reply Quote 1
        • C
          chenys @run-out last edited by

          @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?

          vladisld 1 Reply Last reply Reply Quote 0
          • vladisld
            vladisld @chenys last edited by

            @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.

            run-out C 3 Replies Last reply Reply Quote 0
            • run-out
              run-out @vladisld last edited by

              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

              RunBacktest.com

              C 1 Reply Last reply Reply Quote 1
              • C
                chenys @run-out last edited by

                @run-out

                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
                
                1 Reply Last reply Reply Quote 0
                • C
                  chenys @vladisld last edited by

                  @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?

                  1 Reply Last reply Reply Quote 0
                  • C
                    chenys @vladisld last edited by

                    @vladisld

                    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
                    ....
                    
                    vladisld 1 Reply Last reply Reply Quote 0
                    • vladisld
                      vladisld @chenys last edited by

                      @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/

                      C 2 Replies Last reply Reply Quote 0
                      • C
                        chenys @vladisld last edited by

                        @vladisld thank you! It works well now

                        1 Reply Last reply Reply Quote 0
                        • C
                          chenys @vladisld last edited by

                          @vladisld

                          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

                          vladisld 1 Reply Last reply Reply Quote 0
                          • vladisld
                            vladisld @chenys last edited by

                            @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 the po 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.

                            C 1 Reply Last reply Reply Quote 1
                            • C
                              chenys @vladisld last edited by

                              @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.

                              Screenshot 2021-08-09 221156.jpg

                              1 Reply Last reply Reply Quote 0
                              • 1 / 1
                              • First post
                                Last post
                              Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors