1class MomentumStrategy(Strategy):
2 """Equal-weight momentum — buys top performers, rebalances monthly."""
3 name = "MomentumStrategy"
4 rebalance_frequency = "monthly"
5 max_positions = 4
6
7 def rebalance(self, state: PortfolioState) -> List[Order]:
8
9 returns = {}
10 for ticker in state.prices.keys():
11 rows = state.bar_data[state.bar_data['ticker'] == ticker]['close'].values
12 if len(rows) >= 2 and rows[0] != 0:
13 returns[ticker] = (rows[-1] - rows[0]) / rows[0]
14
15 if not returns:
16 return []
17
18
19 ranked = sorted(returns.items(), key=lambda x: x[1], reverse=True)
20 top = [t for t, _ in ranked[:self.max_positions]]
21
22
23 weight = 0.95 / len(top)
24 weights = {t: weight for t in top}
25
26 return self.target_weights(weights, state)
27