From 670686681d1773505ba3ac3dd576b68617d9025c Mon Sep 17 00:00:00 2001 From: boris Date: Wed, 26 Aug 2026 06:43:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=87=8F=E5=B0=91=E6=AF=8F=E6=97=A5=E8=AF=8A?= =?UTF-8?q?=E6=96=AD=E6=96=87=E6=9C=AC=E4=B8=B4=E6=97=B6=E5=88=86=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/fidc-core/src/engine.rs | 63 ++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/crates/fidc-core/src/engine.rs b/crates/fidc-core/src/engine.rs index a1a6ab5..255834c 100644 --- a/crates/fidc-core/src/engine.rs +++ b/crates/fidc-core/src/engine.rs @@ -1935,14 +1935,14 @@ where .ok_or(BacktestError::MissingBenchmark { date: execution_date, })?; - let notes = corporate_action_notes.join(" | "); - let diagnostics = std::iter::once(format!( - "decision_lag_warmup lag_days={} execution_index={}", - self.config.decision_lag_trading_days, execution_idx - )) - .chain(broker_diagnostics.into_iter()) - .collect::>() - .join(" | "); + let notes = join_text_parts(corporate_action_notes.into_iter()); + let diagnostics = join_text_parts( + std::iter::once(format!( + "decision_lag_warmup lag_days={} execution_index={}", + self.config.decision_lag_trading_days, execution_idx + )) + .chain(broker_diagnostics.into_iter()), + ); let holdings_for_day = portfolio.holdings_summary(execution_date); let holding_start = result.daily_holdings.len(); let holding_count = holdings_for_day.len(); @@ -3012,17 +3012,17 @@ where .ok_or(BacktestError::MissingBenchmark { date: execution_date, })?; - let notes = corporate_action_notes - .into_iter() - .chain(decision.notes.into_iter()) - .collect::>() - .join(" | "); - let diagnostics = decision - .diagnostics - .into_iter() - .chain(broker_diagnostics.into_iter()) - .collect::>() - .join(" | "); + let notes = join_text_parts( + corporate_action_notes + .into_iter() + .chain(decision.notes.into_iter()), + ); + let diagnostics = join_text_parts( + decision + .diagnostics + .into_iter() + .chain(broker_diagnostics.into_iter()), + ); let holdings_for_day = portfolio.holdings_summary(execution_date); let holding_start = result.daily_holdings.len(); let holding_count = holdings_for_day.len(); @@ -4303,6 +4303,22 @@ fn futures_limit_satisfied(side: OrderSide, price: f64, limit_price: Option } } +fn join_text_parts(parts: I) -> String +where + I: IntoIterator, +{ + let mut iterator = parts.into_iter(); + let Some(first) = iterator.next() else { + return String::new(); + }; + let mut result = first; + for part in iterator { + result.push_str(" | "); + result.push_str(&part); + } + result +} + fn futures_cancel_report( date: NaiveDate, order: FuturesOpenOrder, @@ -4392,6 +4408,15 @@ mod tests { const SYMBOL: &str = "000001.SZ"; + #[test] + fn join_text_parts_matches_vec_join_contract() { + assert_eq!(super::join_text_parts(Vec::::new()), ""); + assert_eq!( + super::join_text_parts(vec!["a".to_string(), "".to_string(), "c".to_string()]), + "a | | c" + ); + } + #[derive(Debug)] struct BuyWhenDecisionDateStrategy { decision_date: NaiveDate,