按有序市值流提前停止选股
This commit is contained in:
@@ -9228,6 +9228,47 @@ impl PlatformExprStrategy {
|
||||
)
|
||||
}
|
||||
|
||||
fn selection_candidate_passes_filters(
|
||||
&self,
|
||||
ctx: &StrategyContext<'_>,
|
||||
date: NaiveDate,
|
||||
day: &DayExpressionState,
|
||||
candidate: &EligibleUniverseSnapshot,
|
||||
stock: &StockExpressionState,
|
||||
diagnostics: &mut Vec<String>,
|
||||
) -> Result<bool, BacktestError> {
|
||||
if !ctx.is_lagged_execution()
|
||||
&& let Some(reason) = self.stock_selection_limit_rejection_reason(stock)
|
||||
{
|
||||
if diagnostics.len() < 12 {
|
||||
diagnostics.push(format!("{} rejected by {}", candidate.symbol, reason));
|
||||
}
|
||||
return Ok(false);
|
||||
}
|
||||
if !self.stock_passes_expr(ctx, day, stock)? {
|
||||
if diagnostics.len() < 12 {
|
||||
diagnostics.push(format!("{} rejected by stock_expr", candidate.symbol));
|
||||
}
|
||||
return Ok(false);
|
||||
}
|
||||
if self.config.stop_take_reference_price_mode
|
||||
== PlatformStopTakeReferencePriceMode::SignalDayPostAdjustedClose
|
||||
&& ctx
|
||||
.data
|
||||
.market_latest_back_adjusted_close(date, &candidate.symbol)
|
||||
.is_none()
|
||||
{
|
||||
if diagnostics.len() < 12 {
|
||||
diagnostics.push(format!(
|
||||
"{} rejected by missing signal-day post-adjusted close",
|
||||
candidate.symbol
|
||||
));
|
||||
}
|
||||
return Ok(false);
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn can_sell_position(&self, ctx: &StrategyContext<'_>, date: NaiveDate, symbol: &str) -> bool {
|
||||
self.can_sell_position_at_time(ctx, date, symbol, None)
|
||||
}
|
||||
@@ -9373,6 +9414,41 @@ impl PlatformExprStrategy {
|
||||
universe_factor_date,
|
||||
5,
|
||||
);
|
||||
|
||||
// The universe is already stably ordered by market cap. When the
|
||||
// strategy asks for that exact ascending order and does not need a
|
||||
// complete ranking for replacement limiting, select directly from the
|
||||
// ordered stream instead of materializing a second candidate vector.
|
||||
if self.rank_reuses_market_cap_order() && self.config.daily_replacement_limit == 0 {
|
||||
let mut selected = Vec::with_capacity(limit.min(universe.len()));
|
||||
for candidate in universe {
|
||||
let stock = self.selection_stock_state_with_factor_date(
|
||||
ctx,
|
||||
date,
|
||||
stock_factor_date,
|
||||
&candidate.symbol,
|
||||
)?;
|
||||
let field_value = self.selection_field_value(&candidate, &stock);
|
||||
if !field_value.is_finite() || field_value < band_low || field_value > band_high {
|
||||
continue;
|
||||
}
|
||||
if self.selection_candidate_passes_filters(
|
||||
ctx,
|
||||
date,
|
||||
day,
|
||||
&candidate,
|
||||
&stock,
|
||||
&mut diagnostics,
|
||||
)? {
|
||||
selected.push(candidate.symbol);
|
||||
if selected.len() >= limit {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Ok((selected, diagnostics, risk_decisions));
|
||||
}
|
||||
|
||||
let mut candidates = Vec::new();
|
||||
let mut missing_rank_count = 0usize;
|
||||
let mut missing_rank_examples = Vec::new();
|
||||
@@ -9461,33 +9537,14 @@ impl PlatformExprStrategy {
|
||||
|
||||
let mut selected = Vec::new();
|
||||
for (candidate, stock, _) in candidates {
|
||||
if !ctx.is_lagged_execution()
|
||||
&& let Some(reason) = self.stock_selection_limit_rejection_reason(&stock)
|
||||
{
|
||||
if diagnostics.len() < 12 {
|
||||
diagnostics.push(format!("{} rejected by {}", candidate.symbol, reason));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if !self.stock_passes_expr(ctx, day, &stock)? {
|
||||
if diagnostics.len() < 12 {
|
||||
diagnostics.push(format!("{} rejected by stock_expr", candidate.symbol));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if self.config.stop_take_reference_price_mode
|
||||
== PlatformStopTakeReferencePriceMode::SignalDayPostAdjustedClose
|
||||
&& ctx
|
||||
.data
|
||||
.market_latest_back_adjusted_close(date, &candidate.symbol)
|
||||
.is_none()
|
||||
{
|
||||
if diagnostics.len() < 12 {
|
||||
diagnostics.push(format!(
|
||||
"{} rejected by missing signal-day post-adjusted close",
|
||||
candidate.symbol
|
||||
));
|
||||
}
|
||||
if !self.selection_candidate_passes_filters(
|
||||
ctx,
|
||||
date,
|
||||
day,
|
||||
&candidate,
|
||||
&stock,
|
||||
&mut diagnostics,
|
||||
)? {
|
||||
continue;
|
||||
}
|
||||
selected.push(candidate.symbol.clone());
|
||||
|
||||
Reference in New Issue
Block a user