Backtrader Community

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

    Strategy based on constituent lists

    General Code/Help
    1
    1
    22
    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.
    • jondej123
      jondej123 last edited by

      When I try to make a portfolio strategy based on yearly constituent lists, my code works. But when I try it for monthly constituent lists, it does not work. You can find my code for the yearly strategy below:

      class EquallyWeighted(bt.Strategy):
      params = (
      ('constituent_companies', {}), # a dictionary mapping year to list of consistent companies
      )

      def __init__(self):
          self.current_year = self.datas[0].datetime.date().year
          self.constituent_companies = self.params.constituent_companies.get(self.current_year, [])
          self.weights = {}  # Dictionary to store the weights for each company
      
      def next(self):
          if self.datas[0].datetime.date().year != self.current_year:
              self.current_year = self.datas[0].datetime.date().year
              self.close_all_positions()  # close all positions
      
              self.constituent_companies = self.params.constituent_companies.get(self.current_year, [])
              self.calculate_weights()  # calculate new weights for the constituent companies
      
          for i, d in enumerate(self.datas):
              if not self.getposition(d).size:
                  if d._name in self.constituent_companies:
                      size = self.broker.get_cash() * self.weights[d._name]  # calculate position size based on weight
                      self.buy(data=d, size=size)
      
      def close_all_positions(self):
          for i, d in enumerate(self.datas):
              position = self.getposition(d).size
              if position > 0:
                  self.close(data=d)
      
      def calculate_weights(self):
          num_companies = len(self.constituent_companies)
          if num_companies > 0:
              weight = 1.0 / num_companies
              for company in self.constituent_companies:
                  self.weights[company] = weight
      

      if name == 'main':
      # Create a cerebro entity
      cerebro = bt.Cerebro()

      # Define the path to the CSV file
      base_path = '/Users/jonat/Documents/Documenten/data/Test/Constituents/'
      
      # Read constituent companies for each year
      constituent_companies = {}
      years = [2000, 2001, 2002, 2003, 2004]  # Update with your desired years
      for year in years:
          csv_path = base_path + f'constituent_companies_{year}.csv'
          with open(csv_path, 'r', encoding='utf-8-sig') as csvfile:
              reader = csv.reader(csvfile)
              next(reader)  # Skip the header row
              companies = [row[0] for row in reader if row[0]]  # Read company names from column A
              constituent_companies[year] = companies
      
      cerebro.addstrategy(EquallyWeighted, constituent_companies=constituent_companies)
      
      datalist = ['AAPL.csv', 'DIS.csv', 'IBM.csv', 'BA.csv', 'F.csv', 'GE.csv', 'KO.csv', 'MMM.csv', 'PG.csv', 'XOM.csv']
      datapath= "/Users/jonat/Documents/Documenten/data/Test/"
      
      for i in range(len(datalist)):
          data= bt.feeds.YahooFinanceCSVData(
              dataname=datapath+datalist[i],
              # Do not pass values before this date
              fromdate=datetime(2000, 1, 1),
              # Do not pass values after this date
              todate=datetime(2004, 12, 31),
              reverse=False)
          cerebro.adddata(data, name=datalist[i])
          
      # Set our desired cash start
      cerebro.broker.setcash(1000.0)
      
      # Add a FixedSize sizer according to the stake
      cerebro.addsizer(bt.sizers.PercentSizer, percents=10)
      
      # Set the commission
      cerebro.broker.setcommission(commission=0.0)
      
      # Print out the starting conditions
      print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
      
      # Run over everything
      cerebro.run()
      
      # Print out the final result
      print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
      

      You can find my code for the monthly strategy below:

      class EquallyWeightedM(bt.Strategy):
      params = (
      ('constituent_companies', {}), # a dictionary mapping year to list of consistent companies
      )

      def __init__(self):
          self.constituent_companies = constituent_companies
          self.weights = {}  # Dictionary to store the weights for each company
      
      def start(self):
          self.calculate_weights()
      
      def next(self):
          for i, d in enumerate(self.datas):
              if not self.getposition(d).size:
                  if d._name in self.weights:
                      size = self.broker.get_cash() * self.weights[d._name]  # calculate position size based on weight
                      self.buy(data=d, size=size)
      
      def calculate_weights(self):
          num_companies = len(self.constituent_companies)
          if num_companies > 0:
              weight = 1.0 / num_companies
              for company in self.constituent_companies:
                  self.weights[company] = weight
      

      if name == 'main':
      cerebro = bt.Cerebro()
      cerebro.addstrategy(EquallyWeightedM, constituent_companies=constituent_companies)

      base_path = '/Users/jonat/Documents/Documenten/data/Test/Constituents/'
      dates = [datetime(2000, 1, 1), datetime(2000, 2, 1), datetime(2000, 3, 1), datetime(2000, 4, 1), datetime(2000, 5, 1)]
      
      for date in dates:
          csv_path = base_path + f'constituent_companies_{date.strftime("%Y-%m-%d")}.csv'
          with open(csv_path, 'r', encoding='utf-8-sig') as csvfile:
              reader = csv.reader(csvfile)
              next(reader)  # Skip the header row
              companies = [row[0] for row in reader if row[0]]  # Read company names from column A
      
      datalist = ['AAPL.csv', 'DIS.csv', 'IBM.csv', 'BA.csv', 'F.csv', 'GE.csv', 'KO.csv', 'MMM.csv', 'PG.csv', 'XOM.csv']
      datapath= "/Users/jonat/Documents/Documenten/data/Test/"
      
      for i in range(len(datalist)):
          data = bt.feeds.YahooFinanceCSVData(
              dataname=datapath+datalist[i],
              fromdate=datetime(2000, 1, 1),
              todate=datetime(2004, 12, 31),
              reverse=False
          )
          cerebro.adddata(data, name=datalist[i])
      
      cerebro.broker.setcash(1000.0)
      cerebro.addsizer(bt.sizers.PercentSizer, percents=10)
      cerebro.broker.setcommission(commission=0.0)
      
      print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
      cerebro.run()
      print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
      

      Can someone help me out?

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