Revert "revert: benchmark generic transient selection"
This reverts commit b2da70897a.
This commit is contained in:
@@ -3981,32 +3981,6 @@ impl PlatformExprStrategy {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn selection_stock_state_with_factor_date_from_views<'a>(
|
|
||||||
&self,
|
|
||||||
ctx: &StrategyContext<'a>,
|
|
||||||
date: NaiveDate,
|
|
||||||
factor_date: NaiveDate,
|
|
||||||
symbol: &str,
|
|
||||||
execution_day: &DailySnapshotView<'a>,
|
|
||||||
factor_day: &DailySnapshotView<'a>,
|
|
||||||
) -> Result<Arc<StockExpressionState>, BacktestError> {
|
|
||||||
let source = ViewStockStateSnapshotSource {
|
|
||||||
execution: execution_day,
|
|
||||||
factor: factor_day,
|
|
||||||
same_date: factor_date == date,
|
|
||||||
};
|
|
||||||
let use_intraday_quote = self.selection_quote_usage != StockFilterQuoteUsage::DailyOnly;
|
|
||||||
self.stock_state_with_factor_date_and_time_from_source(
|
|
||||||
ctx,
|
|
||||||
date,
|
|
||||||
factor_date,
|
|
||||||
symbol,
|
|
||||||
None,
|
|
||||||
use_intraday_quote,
|
|
||||||
&source,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn uncached_selection_stock_state_from_views_by_symbol_id<'a>(
|
fn uncached_selection_stock_state_from_views_by_symbol_id<'a>(
|
||||||
&self,
|
&self,
|
||||||
@@ -9497,6 +9471,7 @@ impl PlatformExprStrategy {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
fn selectable_universe_on_with_options(
|
fn selectable_universe_on_with_options(
|
||||||
&self,
|
&self,
|
||||||
ctx: &StrategyContext<'_>,
|
ctx: &StrategyContext<'_>,
|
||||||
@@ -9514,6 +9489,7 @@ impl PlatformExprStrategy {
|
|||||||
.0
|
.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
fn selection_universe_and_risk_decisions_with_options(
|
fn selection_universe_and_risk_decisions_with_options(
|
||||||
&self,
|
&self,
|
||||||
ctx: &StrategyContext<'_>,
|
ctx: &StrategyContext<'_>,
|
||||||
@@ -10141,15 +10117,14 @@ impl PlatformExprStrategy {
|
|||||||
universe_factor_date,
|
universe_factor_date,
|
||||||
5,
|
5,
|
||||||
);
|
);
|
||||||
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);
|
|
||||||
|
|
||||||
// The universe is already stably ordered by market cap. When the
|
// The universe is already stably ordered by market cap. When the
|
||||||
// strategy asks for that exact ascending order and does not need a
|
// strategy asks for that exact ascending order and does not need a
|
||||||
// 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 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()));
|
let mut selected = Vec::with_capacity(limit.min(universe_symbol_ids.len()));
|
||||||
for symbol_id in universe_symbol_ids {
|
for symbol_id in universe_symbol_ids {
|
||||||
let factor = universe_factor_day
|
let factor = universe_factor_day
|
||||||
@@ -10190,28 +10165,57 @@ impl PlatformExprStrategy {
|
|||||||
return Ok((selected, diagnostics, risk_decisions));
|
return Ok((selected, diagnostics, risk_decisions));
|
||||||
}
|
}
|
||||||
|
|
||||||
let universe = universe_symbol_ids
|
let selected = self.select_ranked_symbols(
|
||||||
.into_iter()
|
ctx,
|
||||||
.map(|symbol_id| {
|
date,
|
||||||
|
universe_factor_date,
|
||||||
|
stock_factor_date,
|
||||||
|
day,
|
||||||
|
band_low,
|
||||||
|
band_high,
|
||||||
|
limit,
|
||||||
|
universe_symbol_ids,
|
||||||
|
&mut diagnostics,
|
||||||
|
)?;
|
||||||
|
Ok((selected, diagnostics, risk_decisions))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
fn select_ranked_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 candidates = Vec::with_capacity(universe_symbol_ids.len());
|
||||||
|
let mut candidate_states = Vec::with_capacity(universe_symbol_ids.len());
|
||||||
|
let mut missing_rank_count = 0usize;
|
||||||
|
let mut missing_rank_examples = Vec::new();
|
||||||
|
for symbol_id in universe_symbol_ids {
|
||||||
let factor = universe_factor_day
|
let factor = universe_factor_day
|
||||||
.factor(symbol_id)
|
.factor(symbol_id)
|
||||||
.expect("market-cap order references missing factor row");
|
.expect("market-cap order references missing factor row");
|
||||||
EligibleUniverseSnapshot {
|
let candidate = EligibleUniverseSnapshot {
|
||||||
symbol: factor.symbol.clone(),
|
symbol: factor.symbol.clone(),
|
||||||
market_cap_bn: decision_market_cap_bn(factor),
|
market_cap_bn: decision_market_cap_bn(factor),
|
||||||
free_float_cap_bn: decision_free_float_cap_bn(factor),
|
free_float_cap_bn: decision_free_float_cap_bn(factor),
|
||||||
}
|
};
|
||||||
})
|
let stock = self.uncached_selection_stock_state_from_views_by_symbol_id(
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let mut candidates = Vec::new();
|
|
||||||
let mut missing_rank_count = 0usize;
|
|
||||||
let mut missing_rank_examples = Vec::new();
|
|
||||||
for candidate in universe {
|
|
||||||
let stock = self.selection_stock_state_with_factor_date_from_views(
|
|
||||||
ctx,
|
ctx,
|
||||||
date,
|
date,
|
||||||
stock_factor_date,
|
stock_factor_date,
|
||||||
|
symbol_id,
|
||||||
&candidate.symbol,
|
&candidate.symbol,
|
||||||
&execution_day,
|
&execution_day,
|
||||||
&factor_day,
|
&factor_day,
|
||||||
@@ -10269,12 +10273,14 @@ impl PlatformExprStrategy {
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
candidates.push((candidate, stock, rank_value));
|
let state_index = candidate_states.len();
|
||||||
|
candidate_states.push(stock);
|
||||||
|
candidates.push((candidate, rank_value, state_index));
|
||||||
}
|
}
|
||||||
if !self.rank_reuses_market_cap_order() {
|
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.1;
|
||||||
let rhs_value = rhs.2;
|
let rhs_value = rhs.1;
|
||||||
let ordering = if self.config.rank_desc {
|
let ordering = if self.config.rank_desc {
|
||||||
rhs_value
|
rhs_value
|
||||||
.partial_cmp(&lhs_value)
|
.partial_cmp(&lhs_value)
|
||||||
@@ -10293,14 +10299,15 @@ impl PlatformExprStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut selected = Vec::new();
|
let mut selected = Vec::new();
|
||||||
for (candidate, stock, _) in candidates {
|
for (candidate, _, state_index) in candidates {
|
||||||
|
let stock = &candidate_states[state_index];
|
||||||
if !self.selection_candidate_passes_filters(
|
if !self.selection_candidate_passes_filters(
|
||||||
ctx,
|
ctx,
|
||||||
date,
|
date,
|
||||||
day,
|
day,
|
||||||
&candidate.symbol,
|
&candidate.symbol,
|
||||||
&stock,
|
stock,
|
||||||
&mut diagnostics,
|
diagnostics,
|
||||||
)? {
|
)? {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -10317,7 +10324,7 @@ impl PlatformExprStrategy {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((selected, diagnostics, risk_decisions))
|
Ok(selected)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stock_filter_quote_usage(&self) -> StockFilterQuoteUsage {
|
fn stock_filter_quote_usage(&self) -> StockFilterQuoteUsage {
|
||||||
@@ -10913,7 +10920,6 @@ impl PlatformExprStrategy {
|
|||||||
selection_limit: usize,
|
selection_limit: usize,
|
||||||
) -> Result<(Vec<String>, Vec<String>, usize, Vec<String>), BacktestError> {
|
) -> Result<(Vec<String>, Vec<String>, usize, Vec<String>), BacktestError> {
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
let mut candidates = Vec::new();
|
|
||||||
let mut missing_rank_count = 0usize;
|
let mut missing_rank_count = 0usize;
|
||||||
let mut missing_rank_examples = Vec::new();
|
let mut missing_rank_examples = Vec::new();
|
||||||
let quote_usage = self.stock_filter_quote_usage();
|
let quote_usage = self.stock_filter_quote_usage();
|
||||||
@@ -10926,20 +10932,33 @@ impl PlatformExprStrategy {
|
|||||||
} else {
|
} else {
|
||||||
SelectionRiskDeferral::None
|
SelectionRiskDeferral::None
|
||||||
};
|
};
|
||||||
let universe = self.selectable_universe_on_with_options(
|
let (universe_symbol_ids, _) = self.selection_symbol_ids_and_risk_decisions_with_options(
|
||||||
ctx,
|
ctx,
|
||||||
date,
|
date,
|
||||||
universe_factor_date,
|
universe_factor_date,
|
||||||
selection_risk_deferral,
|
selection_risk_deferral,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
|
let mut candidates = Vec::with_capacity(universe_symbol_ids.len());
|
||||||
|
let mut candidate_states = Vec::with_capacity(universe_symbol_ids.len());
|
||||||
let execution_day = ctx.data.daily_snapshot_view(date);
|
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 factor_day = ctx.data.daily_snapshot_view(stock_factor_date);
|
||||||
let quote_candidate_limit = self.quote_plan_candidate_limit(selection_limit);
|
let quote_candidate_limit = self.quote_plan_candidate_limit(selection_limit);
|
||||||
for candidate in universe {
|
for symbol_id in universe_symbol_ids {
|
||||||
let stock = self.selection_stock_state_with_factor_date_from_views(
|
let factor = universe_factor_day
|
||||||
|
.factor(symbol_id)
|
||||||
|
.expect("market-cap order references missing factor row");
|
||||||
|
let candidate = EligibleUniverseSnapshot {
|
||||||
|
symbol: factor.symbol.clone(),
|
||||||
|
market_cap_bn: decision_market_cap_bn(factor),
|
||||||
|
free_float_cap_bn: decision_free_float_cap_bn(factor),
|
||||||
|
};
|
||||||
|
let stock = self.uncached_selection_stock_state_from_views_by_symbol_id(
|
||||||
ctx,
|
ctx,
|
||||||
date,
|
date,
|
||||||
stock_factor_date,
|
stock_factor_date,
|
||||||
|
symbol_id,
|
||||||
&candidate.symbol,
|
&candidate.symbol,
|
||||||
&execution_day,
|
&execution_day,
|
||||||
&factor_day,
|
&factor_day,
|
||||||
@@ -10977,7 +10996,9 @@ impl PlatformExprStrategy {
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
candidates.push((candidate.symbol.clone(), rank_value, stock));
|
let state_index = candidate_states.len();
|
||||||
|
candidate_states.push(stock);
|
||||||
|
candidates.push((candidate.symbol.clone(), rank_value, state_index));
|
||||||
}
|
}
|
||||||
candidates.sort_by(|lhs, rhs| {
|
candidates.sort_by(|lhs, rhs| {
|
||||||
let ordering = if self.config.rank_desc {
|
let ordering = if self.config.rank_desc {
|
||||||
@@ -10999,9 +11020,10 @@ impl PlatformExprStrategy {
|
|||||||
let mut quote_candidate_symbols = Vec::new();
|
let mut quote_candidate_symbols = Vec::new();
|
||||||
let mut selected_symbols = Vec::new();
|
let mut selected_symbols = Vec::new();
|
||||||
let mut processed_scope = 0usize;
|
let mut processed_scope = 0usize;
|
||||||
for (symbol, _, stock) in &candidates {
|
for (symbol, _, state_index) in &candidates {
|
||||||
|
let stock = &candidate_states[*state_index];
|
||||||
processed_scope += 1;
|
processed_scope += 1;
|
||||||
if !self.stock_passes_quote_plan_filter(ctx, day, &stock, quote_usage)? {
|
if !self.stock_passes_quote_plan_filter(ctx, day, stock, quote_usage)? {
|
||||||
if diagnostics.len() < 12 {
|
if diagnostics.len() < 12 {
|
||||||
diagnostics.push(format!("{symbol} quote_plan rejected by stock_expr"));
|
diagnostics.push(format!("{symbol} quote_plan rejected by stock_expr"));
|
||||||
}
|
}
|
||||||
@@ -11019,7 +11041,7 @@ impl PlatformExprStrategy {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if quote_usage == StockFilterQuoteUsage::IntradayQuote
|
if quote_usage == StockFilterQuoteUsage::IntradayQuote
|
||||||
&& !self.stock_passes_expr(ctx, day, &stock)?
|
&& !self.stock_passes_expr(ctx, day, stock)?
|
||||||
{
|
{
|
||||||
if diagnostics.len() < 12 {
|
if diagnostics.len() < 12 {
|
||||||
diagnostics.push(format!("{symbol} quote_plan rejected by stock_expr"));
|
diagnostics.push(format!("{symbol} quote_plan rejected by stock_expr"));
|
||||||
|
|||||||
Reference in New Issue
Block a user