From 8495bf6ad8adcd3827ce1d4970aa62f01e322976 Mon Sep 17 00:00:00 2001 From: boris Date: Sun, 21 Jun 2026 02:19:59 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=81=E8=AE=B8=E5=BC=B1=E5=B8=82=E6=B6=A8?= =?UTF-8?q?=E5=81=9C=E6=8C=81=E4=BB=93=E9=83=A8=E5=88=86=E5=87=8F=E4=BB=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fidc-core/src/platform_expr_strategy.rs | 45 ++++++++++++++----- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/crates/fidc-core/src/platform_expr_strategy.rs b/crates/fidc-core/src/platform_expr_strategy.rs index 0d1426d..ea2de6e 100644 --- a/crates/fidc-core/src/platform_expr_strategy.rs +++ b/crates/fidc-core/src/platform_expr_strategy.rs @@ -2319,6 +2319,27 @@ impl PlatformExprStrategy { } } + fn mark_highlimit_for_delayed_exit_at_time( + &mut self, + ctx: &StrategyContext<'_>, + date: NaiveDate, + symbol: &str, + execution_time: NaiveTime, + ) -> Result<(), BacktestError> { + if !self.config.delayed_limit_open_exit_enabled + || self.pending_highlimit_holdings.contains(symbol) + { + return Ok(()); + } + if matches!( + self.stock_is_at_upper_limit_at_time(ctx, date, symbol, execution_time)?, + Some(true) + ) { + self.pending_highlimit_holdings.insert(symbol.to_string()); + } + Ok(()) + } + fn stock_state_with_factor_date_and_time( &self, ctx: &StrategyContext<'_>, @@ -7463,14 +7484,12 @@ impl Strategy for PlatformExprStrategy { if position.quantity == 0 || delayed_sold_symbols.contains(&position.symbol) { continue; } - if self.regular_sell_should_wait_due_to_highlimit( + self.mark_highlimit_for_delayed_exit_at_time( ctx, execution_date, &position.symbol, self.intraday_execution_start_time(), - )? { - continue; - } + )?; if pending_full_close_symbols.contains(&position.symbol) { continue; } @@ -11706,7 +11725,7 @@ mod tests { } #[test] - fn platform_aiquant_weak_market_skips_pending_highlimit_target_adjust_until_open() { + fn platform_aiquant_weak_market_allows_pending_highlimit_partial_target_adjust() { let prev_date = d(2023, 5, 4); let date = d(2023, 5, 5); let symbol = "600148.SH"; @@ -11845,13 +11864,15 @@ mod tests { let decision = strategy.on_day(&ctx).expect("platform decision"); assert!( - !decision.order_intents.iter().any(|intent| matches!( + decision.order_intents.iter().any(|intent| matches!( intent, OrderIntent::Shares { symbol: intent_symbol, + quantity, reason, - .. - } if intent_symbol == symbol && reason == "daily_position_target_adjust" + } if intent_symbol == symbol + && reason == "daily_position_target_adjust" + && *quantity < 0 )), "{:?}", decision.order_intents @@ -11999,13 +12020,15 @@ mod tests { let decision = strategy.on_day(&ctx).expect("platform decision"); assert!( - !decision.order_intents.iter().any(|intent| matches!( + decision.order_intents.iter().any(|intent| matches!( intent, OrderIntent::Shares { symbol: intent_symbol, + quantity, reason, - .. - } if intent_symbol == symbol && reason == "daily_position_target_adjust" + } if intent_symbol == symbol + && reason == "daily_position_target_adjust" + && *quantity < 0 )), "{:?}", decision.order_intents