From 2811886a52b681dc03b47898d8418eee8b01ed6d Mon Sep 17 00:00:00 2001 From: boris Date: Wed, 9 Sep 2026 07:21:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8C=BA=E5=88=86=E6=AC=A1=E6=97=A5=E5=9B=9E?= =?UTF-8?q?=E6=94=BE=E8=B0=83=E5=BA=A6=E6=A0=87=E7=AD=BE=E4=B8=8E=E5=AE=9E?= =?UTF-8?q?=E9=99=85=E6=97=A5=E7=BA=BF=E5=8F=AF=E8=A7=81=E6=97=B6=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/fidc-core/src/platform_expr_strategy.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/fidc-core/src/platform_expr_strategy.rs b/crates/fidc-core/src/platform_expr_strategy.rs index e6b8cb3..7b0582b 100644 --- a/crates/fidc-core/src/platform_expr_strategy.rs +++ b/crates/fidc-core/src/platform_expr_strategy.rs @@ -5671,8 +5671,9 @@ impl PlatformExprStrategy { return Err(BacktestError::Execution("daily_pattern_requires_next_bar_open: 完整日线形态只能在下一交易日执行".into())); } let date = day.date.min(ctx.decision_date); - if ctx.active_datetime.is_some_and(|t| t.date() == date && t.time() < NaiveTime::from_hms_opt(16, 0, 0).unwrap()) { - return Err(BacktestError::Execution("daily_pattern_not_yet_visible: 不允许使用未完成的当日日线".into())); + // Lagged replay retains the decision day's schedule label; execution is on a later session. + if !ctx.is_lagged_execution() && ctx.active_datetime.is_some_and(|t| t.date() == date && t.time() < NaiveTime::from_hms_opt(16, 0, 0).unwrap()) { + return Err(BacktestError::Execution(format!("daily_pattern_not_yet_visible: 不允许使用未完成的当日日线; decision_date={date}, execution_date={}, active_datetime={:?}",ctx.execution_date,ctx.active_datetime))); } let stock = stock.ok_or_else(|| BacktestError::Execution("pattern_signal requires stock context".into()))?; let key = (date, stock.symbol.to_string(), serde_json::to_string(spec).unwrap()); @@ -14163,7 +14164,9 @@ mod tests { let expression=r#"pattern_signal("{\"template\":\"ma_below\",\"parameters\":{\"ma_window\":20}}")"#; let day=strategy.day_state(&ctx,dates[19]).unwrap();let stock=strategy.stock_state(&ctx,dates[19],symbol).unwrap(); assert!(!strategy.eval_bool(&ctx,expression,&day,Some(&stock),None).unwrap()); - ctx.active_datetime=dates[19].and_hms_opt(10,0,0); + ctx.active_datetime=dates[19].and_hms_opt(10,18,0); + assert!(!strategy.eval_bool(&ctx,expression,&day,Some(&stock),None).unwrap()); + ctx.execution_date=dates[19]; assert!(strategy.eval_bool(&ctx,expression,&day,Some(&stock),None).unwrap_err().to_string().contains("not_yet_visible")); ctx.active_datetime=None;strategy.config.matching_type=MatchingType::CurrentBarClose; assert!(strategy.eval_bool(&ctx,expression,&day,Some(&stock),None).unwrap_err().to_string().contains("requires_next_bar_open"));