修正延迟撮合选股与目标金额语义

This commit is contained in:
boris
2026-07-17 08:55:16 +08:00
parent 8f167e7de1
commit a734cbeaec
+29 -34
View File
@@ -7745,31 +7745,11 @@ impl PlatformExprStrategy {
band_high: f64, band_high: f64,
limit: usize, limit: usize,
) -> Result<(Vec<String>, Vec<String>, Vec<FidcRiskDecisionAudit>), BacktestError> { ) -> Result<(Vec<String>, Vec<String>, Vec<FidcRiskDecisionAudit>), BacktestError> {
let selection_risk_deferral = if ctx.is_lagged_execution() { // Selection policy is evaluated on the signal day. Lagged execution only
SelectionRiskDeferral::All // defers buy/sell risk to the actual execution bar; it must not disable an
} else { // explicitly configured signal-day universe filter.
SelectionRiskDeferral::None let universe = self.selectable_universe_on(ctx, date, universe_factor_date);
}; let risk_decisions = self.selection_risk_decisions(ctx, date, universe_factor_date);
let universe = if selection_risk_deferral != SelectionRiskDeferral::None {
self.selectable_universe_on_with_options(
ctx,
date,
universe_factor_date,
selection_risk_deferral,
)
} else {
self.selectable_universe_on(ctx, date, universe_factor_date)
};
let risk_decisions = if selection_risk_deferral != SelectionRiskDeferral::None {
self.selection_risk_decisions_with_options(
ctx,
date,
universe_factor_date,
selection_risk_deferral,
)
} else {
self.selection_risk_decisions(ctx, date, universe_factor_date)
};
let mut diagnostics = Self::selection_risk_decision_diagnostics( let mut diagnostics = Self::selection_risk_decision_diagnostics(
&risk_decisions, &risk_decisions,
date, date,
@@ -9456,7 +9436,16 @@ impl Strategy for PlatformExprStrategy {
} }
projected = trial_projected; projected = trial_projected;
projected_execution_state = trial_execution_state; projected_execution_state = trial_execution_state;
if quantity_delta != 0 { if self.config.target_portfolio_daily_enabled {
order_intents.push(OrderIntent::TargetValue {
symbol: position.symbol.clone(),
target_value,
reason: "daily_position_target_adjust".to_string(),
});
if quantity_delta > 0 {
same_bar_buy_symbols.insert(position.symbol.clone());
}
} else if quantity_delta != 0 {
order_intents.push(OrderIntent::Shares { order_intents.push(OrderIntent::Shares {
symbol: position.symbol.clone(), symbol: position.symbol.clone(),
quantity: quantity_delta, quantity: quantity_delta,
@@ -16344,6 +16333,8 @@ mod tests {
cfg.stock_filter_expr = "false".to_string(); cfg.stock_filter_expr = "false".to_string();
cfg.stop_loss_expr.clear(); cfg.stop_loss_expr.clear();
cfg.take_profit_expr.clear(); cfg.take_profit_expr.clear();
cfg.target_portfolio_daily_enabled = true;
cfg.matching_type = MatchingType::NextBarOpen;
cfg.risk_config.trading_constraints.volume_limit_enabled = true; cfg.risk_config.trading_constraints.volume_limit_enabled = true;
cfg.risk_config.trading_constraints.liquidity_limit_enabled = true; cfg.risk_config.trading_constraints.liquidity_limit_enabled = true;
cfg.risk_config.trading_constraints.volume_percent = 0.25; cfg.risk_config.trading_constraints.volume_percent = 0.25;
@@ -16353,13 +16344,17 @@ mod tests {
assert!(decision.order_intents.iter().any(|intent| matches!( assert!(decision.order_intents.iter().any(|intent| matches!(
intent, intent,
OrderIntent::Shares { OrderIntent::TargetValue {
symbol: intent_symbol, symbol: intent_symbol,
quantity, target_value,
reason reason
} if intent_symbol == symbol } if intent_symbol == symbol
&& reason == "daily_position_target_adjust" && reason == "daily_position_target_adjust"
&& *quantity == 100 && *target_value > 0.0
)));
assert!(!decision.order_intents.iter().any(|intent| matches!(
intent,
OrderIntent::Shares { reason, .. } if reason == "daily_position_target_adjust"
))); )));
} }
@@ -19088,7 +19083,7 @@ mod tests {
} }
#[test] #[test]
fn platform_next_open_selection_records_risk_diagnostics_without_filtering() { fn platform_next_open_selection_applies_explicit_signal_day_risk_filter() {
let factor_date = d(2023, 11, 10); let factor_date = d(2023, 11, 10);
let decision_date = d(2023, 11, 13); let decision_date = d(2023, 11, 13);
let execution_date = d(2023, 11, 14); let execution_date = d(2023, 11, 14);
@@ -19259,7 +19254,7 @@ mod tests {
decision decision
.diagnostics .diagnostics
.iter() .iter()
.any(|item| item == "selected_symbols=600462.SH"), .all(|item| item != "selected_symbols=600462.SH"),
"{:?}", "{:?}",
decision.diagnostics decision.diagnostics
); );
@@ -19272,15 +19267,15 @@ mod tests {
decision.diagnostics decision.diagnostics
); );
assert!( assert!(
decision.order_intents.iter().any(|intent| matches!( decision.order_intents.iter().all(|intent| !matches!(
intent, intent,
OrderIntent::Shares { symbol, quantity, .. } OrderIntent::Shares { symbol, quantity, .. }
if symbol == candidate_symbol && *quantity > 0 if symbol == candidate_symbol && *quantity > 0
) || matches!( ) && !matches!(
intent, intent,
OrderIntent::Value { symbol, value, .. } OrderIntent::Value { symbol, value, .. }
if symbol == candidate_symbol && *value > 0.0 if symbol == candidate_symbol && *value > 0.0
) || matches!( ) && !matches!(
intent, intent,
OrderIntent::TargetValue { OrderIntent::TargetValue {
symbol, symbol,