From 616cab0e7ecf3f0eae4a5fa9402a0a30f2f1c47f Mon Sep 17 00:00:00 2001 From: boris Date: Wed, 13 May 2026 21:57:57 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E6=9B=B4=E6=96=B0=20fidc-backtest-eng?= =?UTF-8?q?ine=20-=202026-05-13?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fidc-core/src/platform_expr_strategy.rs | 10 +++++-- .../fidc-core/src/platform_strategy_spec.rs | 11 ++++++- crates/fidc-core/src/strategy.rs | 30 +++++++++++++------ 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/crates/fidc-core/src/platform_expr_strategy.rs b/crates/fidc-core/src/platform_expr_strategy.rs index 28f5cf2..82ed18f 100644 --- a/crates/fidc-core/src/platform_expr_strategy.rs +++ b/crates/fidc-core/src/platform_expr_strategy.rs @@ -196,7 +196,7 @@ pub struct PlatformExprStrategyConfig { pub stock_short_ma_days: usize, pub stock_mid_ma_days: usize, pub stock_long_ma_days: usize, - pub skip_month_day_ranges: Vec<(u32, u32, u32)>, + pub skip_month_day_ranges: Vec<(Option, u32, u32, u32)>, pub rebalance_schedule: Option, pub rotation_enabled: bool, pub daily_top_up_enabled: bool, @@ -263,11 +263,17 @@ fn band_low(index_close) { } fn in_skip_window(&self, date: NaiveDate) -> bool { + let year = date.year() as u32; let month = date.month(); let day = date.day(); self.skip_month_day_ranges .iter() - .any(|(m, start_day, end_day)| month == *m && day >= *start_day && day <= *end_day) + .any(|(window_year, m, start_day, end_day)| { + window_year.map(|value| value == year).unwrap_or(true) + && month == *m + && day >= *start_day + && day <= *end_day + }) } } diff --git a/crates/fidc-core/src/platform_strategy_spec.rs b/crates/fidc-core/src/platform_strategy_spec.rs index 751ff24..0927c1e 100644 --- a/crates/fidc-core/src/platform_strategy_spec.rs +++ b/crates/fidc-core/src/platform_strategy_spec.rs @@ -156,6 +156,8 @@ pub struct IndexThrottleConfig { #[derive(Debug, Clone, Default, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct SkipWindowConfig { + #[serde(default)] + pub year: Option, #[serde(default)] pub month: Option, #[serde(default)] @@ -391,7 +393,14 @@ pub fn platform_expr_config_from_spec( cfg.skip_month_day_ranges = engine .skip_windows .iter() - .filter_map(|window| Some((window.month?, window.start_day?, window.end_day?))) + .filter_map(|window| { + Some(( + window.year, + window.month?, + window.start_day?, + window.end_day?, + )) + }) .collect(); } if let Some(spec_signal_symbol) = engine diff --git a/crates/fidc-core/src/strategy.rs b/crates/fidc-core/src/strategy.rs index a7a6614..f979c00 100644 --- a/crates/fidc-core/src/strategy.rs +++ b/crates/fidc-core/src/strategy.rs @@ -1104,7 +1104,7 @@ pub struct CnSmallCapRotationConfig { pub take_profit_pct: f64, pub signal_symbol: Option, pub skip_months: Vec, - pub skip_month_day_ranges: Vec<(u32, u32, u32)>, + pub skip_month_day_ranges: Vec<(Option, u32, u32, u32)>, } impl CnSmallCapRotationConfig { @@ -1159,23 +1159,29 @@ impl CnSmallCapRotationConfig { signal_symbol: Some("000852.SH".to_string()), skip_months: vec![], skip_month_day_ranges: vec![ - (1, 15, 30), - (4, 15, 29), - (8, 15, 31), - (10, 20, 30), - (12, 20, 30), + (None, 1, 15, 30), + (None, 4, 15, 29), + (None, 8, 15, 31), + (None, 10, 20, 30), + (None, 12, 20, 30), ], } } fn in_skip_window(&self, date: NaiveDate) -> bool { + let year = date.year() as u32; let month = date.month(); let day = date.day(); self.skip_months.contains(&month) || self .skip_month_day_ranges .iter() - .any(|(m, start_day, end_day)| month == *m && day >= *start_day && day <= *end_day) + .any(|(window_year, m, start_day, end_day)| { + window_year.map(|value| value == year).unwrap_or(true) + && month == *m + && day >= *start_day + && day <= *end_day + }) } } @@ -1533,7 +1539,7 @@ pub struct OmniMicroCapConfig { pub trade_rate: f64, pub stop_loss_ratio: f64, pub take_profit_ratio: f64, - pub skip_month_day_ranges: Vec<(u32, u32, u32)>, + pub skip_month_day_ranges: Vec<(Option, u32, u32, u32)>, } impl OmniMicroCapConfig { @@ -1592,11 +1598,17 @@ impl OmniMicroCapConfig { } fn in_skip_window(&self, date: NaiveDate) -> bool { + let year = date.year() as u32; let month = date.month(); let day = date.day(); self.skip_month_day_ranges .iter() - .any(|(m, start_day, end_day)| month == *m && day >= *start_day && day <= *end_day) + .any(|(window_year, m, start_day, end_day)| { + window_year.map(|value| value == year).unwrap_or(true) + && month == *m + && day >= *start_day + && day <= *end_day + }) } }