fix: preserve authoritative STAR market classification in risk checks
This commit is contained in:
@@ -397,7 +397,7 @@ impl ChinaAShareRiskControl {
|
||||
RiskCheckScope::Buy => config.static_rules.reject_kcb_buy,
|
||||
RiskCheckScope::Sell => false,
|
||||
};
|
||||
if reject_kcb && (candidate.is_kcb || symbol_is_kcb(&candidate.symbol)) {
|
||||
if reject_kcb && candidate.is_kcb {
|
||||
return Some("kcb");
|
||||
}
|
||||
let reject_bjse = match scope {
|
||||
@@ -600,11 +600,6 @@ impl ChinaAShareRiskControl {
|
||||
}
|
||||
}
|
||||
|
||||
fn symbol_is_kcb(symbol: &str) -> bool {
|
||||
let normalized = symbol.trim().to_ascii_uppercase();
|
||||
(normalized.starts_with("688") || normalized.starts_with("689")) && normalized.ends_with(".SH")
|
||||
}
|
||||
|
||||
fn symbol_is_bjse(symbol: &str) -> bool {
|
||||
let normalized = symbol.trim().to_ascii_uppercase();
|
||||
normalized.ends_with(".BJ") || normalized.ends_with(".BSE") || normalized.ends_with(".BE")
|
||||
@@ -1009,6 +1004,24 @@ mod tests {
|
||||
assert_eq!(configured_reason, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn kcb_filter_uses_classification_instead_of_security_code() {
|
||||
let date = d(2025, 1, 2);
|
||||
let market = market(date, 6.27, 5.63);
|
||||
let mut candidate = candidate(date);
|
||||
let config = FidcRiskControlConfig::default();
|
||||
for symbol in ["688001.SH", "689001.SH", "000001.SZ"] {
|
||||
candidate.symbol = symbol.to_string();
|
||||
for is_kcb in [false, true] {
|
||||
candidate.is_kcb = is_kcb;
|
||||
let reason = ChinaAShareRiskControl::buy_rejection_reason_with_config(
|
||||
date, &candidate, &market, None, 6.27, &config,
|
||||
);
|
||||
assert_eq!(reason, is_kcb.then_some("kcb"), "{symbol}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn st_and_star_st_filters_are_independent() {
|
||||
let date = d(2025, 1, 2);
|
||||
@@ -1139,6 +1152,7 @@ mod tests {
|
||||
let date = d(2025, 1, 2);
|
||||
let mut candidate = candidate(date);
|
||||
candidate.symbol = "688506.SH".to_string();
|
||||
candidate.is_kcb = true;
|
||||
candidate.risk_level_code = Some("missing_risk_state".to_string());
|
||||
let market = market(date, 6.27, 5.63);
|
||||
let mut config = FidcRiskControlConfig::default();
|
||||
|
||||
Reference in New Issue
Block a user