fix: greedy模式仅在select_num=1时生效
问题:greedy在select_num>1时仓位分配取决于ETF池大小,而非动量强度 - 场景1: 有色金属(1ETF)>原油(3ETF)>黄金(4ETF) → 有色25%,原油75%,黄金0% - 场景2: 黄金(4ETF)>创业板(4ETF)>纳指(4ETF) → 黄金100%,其他0% 修复:select_num>1时greedy退化为equal权重 回测对比: - select_num=3, rank: 326.60% - select_num=1, greedy: 730.61% (集中度更高,收益更好)
This commit is contained in:
@@ -530,17 +530,18 @@ class SimpleRotationStrategy:
|
||||
def _compute_greedy_weights(self, holdings: List[str], factors: Dict[str, float]) -> Dict[str, float]:
|
||||
"""Compute greedy weights for signal-level holdings.
|
||||
|
||||
Greedy Algorithm:
|
||||
1. Each index has absorption capacity = min(n_etfs, ceil(1/max_weight)) × max_weight
|
||||
2. Iterate through holdings in order (sorted by momentum)
|
||||
3. Each index absorbs up to its capacity
|
||||
4. Remaining weight flows to next index
|
||||
Greedy Algorithm (only for select_num=1):
|
||||
1. The top-1 index has absorption capacity = min(n_etfs, ceil(1/max_weight)) × max_weight
|
||||
2. If capacity < 100%, remaining weight flows to next index by momentum
|
||||
3. Continue until 100% allocated
|
||||
|
||||
Example (select_num=1, max_weight=0.25):
|
||||
- 有色金属(1 ETF): capacity=25%, absorbs 25%, remaining=75%
|
||||
- 原油(3 ETFs): capacity=75%, absorbs 75%, remaining=0%
|
||||
- Total: 100%
|
||||
|
||||
For select_num>1, falls back to equal weight (greedy not applicable).
|
||||
|
||||
Args:
|
||||
holdings: List of signal codes (sorted by momentum desc)
|
||||
factors: Dict of signal_code -> momentum score
|
||||
@@ -551,6 +552,12 @@ class SimpleRotationStrategy:
|
||||
if not holdings:
|
||||
return {}
|
||||
|
||||
# Greedy only for select_num=1
|
||||
if self.select_num > 1:
|
||||
# Fall back to equal weight
|
||||
w = 1.0 / len(holdings)
|
||||
return {code: w for code in holdings}
|
||||
|
||||
signal_weights = {}
|
||||
remaining_weight = 1.0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user