perf: isolate ordered selection hot path

This commit is contained in:
boris
2026-09-05 05:47:11 +08:00
parent 6a304e2fc2
commit d89dd24f0a
+70 -40
View File
@@ -10122,46 +10122,18 @@ impl PlatformExprStrategy {
// complete ranking for replacement limiting, select directly from the // complete ranking for replacement limiting, select directly from the
// ordered stream instead of materializing a second candidate vector. // ordered stream instead of materializing a second candidate vector.
if self.rank_reuses_market_cap_order() && self.config.daily_replacement_limit == 0 { if self.rank_reuses_market_cap_order() && self.config.daily_replacement_limit == 0 {
let execution_day = ctx.data.daily_snapshot_view(date); let selected = self.select_market_cap_ordered_symbols(
let universe_factor_day = ctx.data.daily_snapshot_view(universe_factor_date); ctx,
let factor_day = ctx.data.daily_snapshot_view(stock_factor_date); date,
let mut selected = Vec::with_capacity(limit.min(universe_symbol_ids.len())); universe_factor_date,
for symbol_id in universe_symbol_ids { stock_factor_date,
let factor = universe_factor_day day,
.factor(symbol_id) band_low,
.expect("market-cap order references missing factor row"); band_high,
let symbol = factor.symbol.as_str(); limit,
let stock = self.uncached_selection_stock_state_from_views_by_symbol_id( universe_symbol_ids,
ctx, &mut diagnostics,
date, )?;
stock_factor_date,
symbol_id,
symbol,
&execution_day,
&factor_day,
)?;
let field_value = self.selection_field_value_from_caps(
decision_market_cap_bn(factor),
decision_free_float_cap_bn(factor),
&stock,
);
if !field_value.is_finite() || field_value < band_low || field_value > band_high {
continue;
}
if self.selection_candidate_passes_filters(
ctx,
date,
day,
symbol,
&stock,
&mut diagnostics,
)? {
selected.push(factor.symbol.clone());
if selected.len() >= limit {
break;
}
}
}
return Ok((selected, diagnostics, risk_decisions)); return Ok((selected, diagnostics, risk_decisions));
} }
@@ -10180,6 +10152,64 @@ impl PlatformExprStrategy {
Ok((selected, diagnostics, risk_decisions)) Ok((selected, diagnostics, risk_decisions))
} }
#[inline(never)]
#[allow(clippy::too_many_arguments)]
fn select_market_cap_ordered_symbols(
&self,
ctx: &StrategyContext<'_>,
date: NaiveDate,
universe_factor_date: NaiveDate,
stock_factor_date: NaiveDate,
day: &DayExpressionState,
band_low: f64,
band_high: f64,
limit: usize,
universe_symbol_ids: Vec<u32>,
diagnostics: &mut Vec<String>,
) -> Result<Vec<String>, BacktestError> {
let execution_day = ctx.data.daily_snapshot_view(date);
let universe_factor_day = ctx.data.daily_snapshot_view(universe_factor_date);
let factor_day = ctx.data.daily_snapshot_view(stock_factor_date);
let mut selected = Vec::with_capacity(limit.min(universe_symbol_ids.len()));
for symbol_id in universe_symbol_ids {
let factor = universe_factor_day
.factor(symbol_id)
.expect("market-cap order references missing factor row");
let symbol = factor.symbol.as_str();
let stock = self.uncached_selection_stock_state_from_views_by_symbol_id(
ctx,
date,
stock_factor_date,
symbol_id,
symbol,
&execution_day,
&factor_day,
)?;
let field_value = self.selection_field_value_from_caps(
decision_market_cap_bn(factor),
decision_free_float_cap_bn(factor),
&stock,
);
if !field_value.is_finite() || field_value < band_low || field_value > band_high {
continue;
}
if self.selection_candidate_passes_filters(
ctx,
date,
day,
symbol,
&stock,
diagnostics,
)? {
selected.push(factor.symbol.clone());
if selected.len() >= limit {
break;
}
}
}
Ok(selected)
}
#[inline(never)] #[inline(never)]
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn select_ranked_symbols( fn select_ranked_symbols(