Signal 6 — Cross-Sectional Momentum
| Thuộc tính | Giá trị |
|---|---|
| Phân loại | Momentum |
| Khung thời gian | Monthly rebalance |
| Paper gốc | Jegadeesh-Titman (1993); Carhart (1997) |
| Loại dữ liệu | Daily returns trên rổ ≥ 30 mã |
| Hướng giao dịch | Long-short / Long-only top quintile |
| Capacity | Rất cao |
Logic. Mỗi tháng, rank toàn bộ universe theo return 12 tháng (skip tháng gần nhất để tránh short-term reversal). Long top 20%, short bottom 20% (hoặc long-only top decile khi thị trường không cho short). Equal-weight trong quintile. Rebalance hàng tháng.
Code Python.
python
def momentum_ranks(returns_df, lookback=252, skip=21):
"""returns_df: DataFrame, cols = tickers, index = dates."""
mom = (1 + returns_df).rolling(lookback).apply(
lambda x: np.prod(x[:-skip]) - 1, raw=True
)
ranks = mom.rank(axis=1, pct=True)
longs = ranks > 0.8
shorts = ranks < 0.2
weights = pd.DataFrame(0.0, index=returns_df.index, columns=returns_df.columns)
weights[longs] = 1.0 / longs.sum(axis=1).values[:, None]
weights[shorts] = -1.0 / shorts.sum(axis=1).values[:, None]
return weightsQuantConnect setup. Dùng Universe.Coarse để chọn top 100 mã theo dollar volume. Schedule.On(DateRules.MonthStart, TimeRules.AfterMarketOpen) để rebalance. History request self.History(symbols, 252, Resolution.Daily) để tính momentum scores.