Strategy based on constituent lists
-
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?
-
-