- Investment universe: 500 largest non-financial stocks with available gross profits-to-assets and book-to-market ratios
- Annual ranking: Rank stocks based on gross profits-to-assets and book-to-market ratios (1=lowest, 500=highest)
- Portfolio construction: At the end of each June, buy $1 of each of the top 150 stocks with highest combined profitability and value ranks; short $1 of each of the bottom 150 stocks with lowest combined ranks
- Rebalancing: Rebalance the portfolio yearly
import backtrader as bt class ProfitValueStrategy(bt.Strategy): def __init__(self): self.rank_size = 500 self.top_bottom_size = 150 def next(self): if self.datetime.date().month == 6 and self.datetime.date().day == 30: self.rank_stocks() self.construct_portfolio() self.rebalance() def rank_stocks(self): stocks = self.datas ranks =  for stock in stocks: gross_profit_to_assets = stock.gross_profit / stock.total_assets book_to_market = stock.book_value / stock.market_cap ranks.append((stock, gross_profit_to_assets, book_to_market)) self.ranks = sorted(ranks, key=lambda x: (x, x), reverse=True)[:self.rank_size] def construct_portfolio(self): self.long_stocks = [stock for stock in self.ranks[:self.top_bottom_size]] self.short_stocks = [stock for stock in self.ranks[-self.top_bottom_size:]] def rebalance(self): self.broker.set_cash(0) for stock in self.long_stocks: self.order_target_value(stock, target=1) for stock in self.short_stocks: self.order_target_value(stock, target=-1) cerebro = bt.Cerebro() # Add data to cerebro (not shown) cerebro.addstrategy(ProfitValueStrategy) cerebro.broker.set_coc(True) results = cerebro.run()
This code is a sample implementation of the trading rules using the Backtrader library. Please note that you would need to add your stock data to the ‘cerebro’ object and ensure that the stock data includes the required attributes (gross_profit, total_assets, book_value, and market_cap) for the ranking calculations.