diff --git a/crates/fidc-core/src/universe.rs b/crates/fidc-core/src/universe.rs index af57370..8dbc2e0 100644 --- a/crates/fidc-core/src/universe.rs +++ b/crates/fidc-core/src/universe.rs @@ -431,4 +431,52 @@ mod tests { .starts_with("risk_decision=") ); } + + #[test] + fn selector_defers_static_execution_risk_for_lagged_execution() { + let data = DataSet::from_components( + vec![ + instrument("000001.SZ"), + instrument("688001.SH"), + instrument("000002.SZ"), + ], + vec![ + market("000001.SZ", 10.0), + market("688001.SH", 10.0), + market("000002.SZ", 10.0), + ], + vec![ + factor("000001.SZ", 8.0), + factor("688001.SH", 9.0), + factor("000002.SZ", 10.0), + ], + vec![ + candidate("000001.SZ", true, false), + candidate("688001.SH", false, true), + candidate("000002.SZ", false, false), + ], + vec![benchmark()], + ) + .unwrap(); + let selector = DynamicMarketCapBandSelector::new(2000.0, 7.0, 10.0, 0.0, 10, 0.0, 0.0, 0.0); + let (selected, diagnostics) = selector.select_with_diagnostics(&SelectionContext { + decision_date: d(), + benchmark: &benchmark(), + reference_level: 2000.0, + data: &data, + dynamic_universe: None, + risk_config: Some(&FidcRiskControlConfig::default()), + defer_selection_risk: true, + }); + + let selected_symbols = selected + .iter() + .map(|candidate| candidate.symbol.as_str()) + .collect::>(); + assert!(selected_symbols.contains("000001.SZ")); + assert!(selected_symbols.contains("688001.SH")); + assert!(selected_symbols.contains("000002.SZ")); + assert_eq!(diagnostics.not_eligible_count, 0); + assert!(diagnostics.risk_decisions.is_empty()); + } }