From 428434d98df667d1058f4f60d4a1ae03af2e5cab Mon Sep 17 00:00:00 2001 From: boris Date: Sun, 12 Jul 2026 04:37:03 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=AC=A1=E6=97=A5=E5=BC=80?= =?UTF-8?q?=E7=9B=98=E7=9B=AE=E6=A0=87=E5=B8=82=E5=80=BC=E6=9C=AA=E6=9D=A5?= =?UTF-8?q?=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/fidc-core/src/broker.rs | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/crates/fidc-core/src/broker.rs b/crates/fidc-core/src/broker.rs index 7f9439f..39c1edf 100644 --- a/crates/fidc-core/src/broker.rs +++ b/crates/fidc-core/src/broker.rs @@ -427,6 +427,12 @@ where symbol: &str, snapshot: &crate::data::DailyMarketSnapshot, ) -> f64 { + if self.matching_type == MatchingType::NextBarOpen + && snapshot.prev_close.is_finite() + && snapshot.prev_close > 0.0 + { + return snapshot.prev_close; + } if self.aiquant_execution_rules && self.execution_price_field == PriceField::Last { let start_cursor = self .runtime_intraday_start_time @@ -7147,6 +7153,38 @@ mod tests { ); } + #[test] + fn next_open_target_value_valuation_uses_previous_close() { + let date = chrono::NaiveDate::from_ymd_opt(2025, 1, 2).expect("valid date"); + let broker = BrokerSimulator::new_with_execution_price( + ChinaAShareCostModel::default(), + ChinaEquityRuleHooks, + PriceField::Open, + ) + .with_matching_type(MatchingType::NextBarOpen); + let mut snapshot = limit_test_snapshot(); + snapshot.date = date; + snapshot.prev_close = 10.0; + snapshot.open = 11.0; + snapshot.close = 20.0; + let data = DataSet::from_components_with_actions_and_quotes( + vec![limit_test_instrument()], + vec![snapshot], + Vec::new(), + vec![limit_test_candidate(true, true)], + vec![limit_test_benchmark()], + Vec::new(), + Vec::new(), + ) + .expect("valid dataset"); + let snapshot = data.market(date, "000001.SZ").expect("market snapshot"); + + assert_eq!( + broker.target_value_valuation_price(date, &data, "000001.SZ", snapshot), + 10.0 + ); + } + #[test] fn target_portfolio_smart_ignores_zero_weight_symbols_without_market_snapshot() { let date = chrono::NaiveDate::from_ymd_opt(2025, 1, 2).expect("valid date");