优化等价市值排序的选股路径

This commit is contained in:
boris
2026-08-29 06:01:02 +08:00
parent 257088d7d9
commit c55caaf79b
@@ -9219,6 +9219,15 @@ impl PlatformExprStrategy {
.unwrap_or_else(|| self.field_value(candidate))) .unwrap_or_else(|| self.field_value(candidate)))
} }
fn rank_reuses_market_cap_order(&self) -> bool {
self.config.rank_expr.trim().is_empty()
&& !self.config.rank_desc
&& matches!(
self.config.rank_by.trim(),
"market_cap" | "market_cap_bn"
)
}
fn can_sell_position(&self, ctx: &StrategyContext<'_>, date: NaiveDate, symbol: &str) -> bool { fn can_sell_position(&self, ctx: &StrategyContext<'_>, date: NaiveDate, symbol: &str) -> bool {
self.can_sell_position_at_time(ctx, date, symbol, None) self.can_sell_position_at_time(ctx, date, symbol, None)
} }
@@ -9429,6 +9438,7 @@ impl PlatformExprStrategy {
} }
candidates.push((candidate, stock, rank_value)); candidates.push((candidate, stock, rank_value));
} }
if !self.rank_reuses_market_cap_order() {
candidates.sort_by(|lhs, rhs| { candidates.sort_by(|lhs, rhs| {
let lhs_value = lhs.2; let lhs_value = lhs.2;
let rhs_value = rhs.2; let rhs_value = rhs.2;
@@ -9447,6 +9457,7 @@ impl PlatformExprStrategy {
ordering ordering
} }
}); });
}
let mut selected = Vec::new(); let mut selected = Vec::new();
for (candidate, stock, _) in candidates { for (candidate, stock, _) in candidates {
@@ -13749,6 +13760,28 @@ mod tests {
); );
} }
#[test]
fn market_cap_ascending_rank_reuses_only_equivalent_universe_order() {
let mut cfg = PlatformExprStrategyConfig::microcap_rotation();
cfg.rank_by = "market_cap".to_string();
let strategy = PlatformExprStrategy::new(cfg.clone());
assert!(strategy.rank_reuses_market_cap_order());
cfg.rank_by = "market_cap_bn".to_string();
assert!(PlatformExprStrategy::new(cfg.clone()).rank_reuses_market_cap_order());
cfg.rank_desc = true;
assert!(!PlatformExprStrategy::new(cfg.clone()).rank_reuses_market_cap_order());
cfg.rank_desc = false;
cfg.rank_expr = "close".to_string();
assert!(!PlatformExprStrategy::new(cfg.clone()).rank_reuses_market_cap_order());
cfg.rank_expr.clear();
cfg.rank_by = "free_float_cap".to_string();
assert!(!PlatformExprStrategy::new(cfg).rank_reuses_market_cap_order());
}
#[test] #[test]
fn current_rolling_helpers_do_not_load_factor_maps_or_decision_rollings() { fn current_rolling_helpers_do_not_load_factor_maps_or_decision_rollings() {
let mut cfg = PlatformExprStrategyConfig::microcap_rotation(); let mut cfg = PlatformExprStrategyConfig::microcap_rotation();