修正FIDC选股阶段风控语义

This commit is contained in:
boris
2026-07-05 03:08:38 +08:00
parent 8125ea2e3b
commit 549595c1c6
2 changed files with 31 additions and 50 deletions
+16 -20
View File
@@ -50,20 +50,15 @@ pub struct SelectionContext<'a> {
pub data: &'a DataSet,
pub dynamic_universe: Option<&'a BTreeSet<String>>,
pub risk_config: Option<&'a FidcRiskControlConfig>,
pub defer_selection_risk: bool,
}
impl SelectionContext<'_> {
fn eligible_universe(&self) -> Vec<EligibleUniverseSnapshot> {
let eligible = if self.defer_selection_risk {
self.data.fundamental_universe_on(self.decision_date)
} else {
match self.risk_config {
Some(risk_config) => self
.data
.eligible_universe_on_with_risk_config(self.decision_date, risk_config),
None => self.data.eligible_universe_on(self.decision_date).to_vec(),
}
let eligible = match self.risk_config {
Some(risk_config) => self
.data
.eligible_universe_on_with_risk_config(self.decision_date, risk_config),
None => self.data.eligible_universe_on(self.decision_date).to_vec(),
};
match self.dynamic_universe {
Some(symbols) if !symbols.is_empty() => eligible
@@ -75,9 +70,6 @@ impl SelectionContext<'_> {
}
fn selection_risk_decisions(&self) -> Vec<FidcRiskDecisionAudit> {
if self.defer_selection_risk {
return Vec::new();
}
let default_risk_config;
let risk_config = match self.risk_config {
Some(value) => value,
@@ -411,7 +403,6 @@ mod tests {
data: &data,
dynamic_universe: None,
risk_config: Some(&FidcRiskControlConfig::default()),
defer_selection_risk: false,
});
let rules = diagnostics
@@ -433,7 +424,7 @@ mod tests {
}
#[test]
fn selector_defers_static_execution_risk_for_lagged_execution() {
fn selector_applies_configured_selection_risk_on_decision_date() {
let data = DataSet::from_components(
vec![
instrument("000001.SZ"),
@@ -466,17 +457,22 @@ mod tests {
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::<BTreeSet<_>>();
assert!(selected_symbols.contains("000001.SZ"));
assert!(selected_symbols.contains("688001.SH"));
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());
assert_eq!(diagnostics.not_eligible_count, 2);
let rules = diagnostics
.risk_decisions
.iter()
.map(|decision| decision.rule_code.as_str())
.collect::<BTreeSet<_>>();
assert!(rules.contains("st"), "{:?}", diagnostics.risk_decisions);
assert!(rules.contains("kcb"), "{:?}", diagnostics.risk_decisions);
}
}