修复策略显式排除股票匹配
This commit is contained in:
@@ -6420,11 +6420,28 @@ impl PlatformExprStrategy {
|
||||
_candidate: &crate::data::CandidateEligibility,
|
||||
market: &DailyMarketSnapshot,
|
||||
) -> bool {
|
||||
let excludes = &self.config.universe_exclude;
|
||||
if excludes.iter().any(|item| item == "bjse") && market.symbol.ends_with(".BJ") {
|
||||
return false;
|
||||
Self::universe_exclude_reason(&self.config.universe_exclude, &market.symbol).is_none()
|
||||
}
|
||||
|
||||
fn universe_exclude_reason(excludes: &[String], symbol: &str) -> Option<&'static str> {
|
||||
let normalized_symbol = symbol.trim().to_ascii_lowercase();
|
||||
if normalized_symbol.is_empty() {
|
||||
return None;
|
||||
}
|
||||
true
|
||||
let symbol_base = normalized_symbol.split('.').next().unwrap_or("");
|
||||
for raw_item in excludes {
|
||||
let item = raw_item.trim().to_ascii_lowercase();
|
||||
if item.is_empty() {
|
||||
continue;
|
||||
}
|
||||
if item == "bjse" && normalized_symbol.ends_with(".bj") {
|
||||
return Some("bjse");
|
||||
}
|
||||
if item == normalized_symbol || (!symbol_base.is_empty() && item == symbol_base) {
|
||||
return Some("universe_exclude");
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn stock_numeric_field_value(
|
||||
@@ -6652,14 +6669,10 @@ impl PlatformExprStrategy {
|
||||
let market = ctx.data.require_market(date, symbol)?;
|
||||
let candidate = ctx.data.require_candidate(date, symbol)?;
|
||||
|
||||
if self
|
||||
.config
|
||||
.universe_exclude
|
||||
.iter()
|
||||
.any(|item| item == "bjse")
|
||||
&& market.symbol.ends_with(".BJ")
|
||||
if let Some(reason) =
|
||||
Self::universe_exclude_reason(&self.config.universe_exclude, &market.symbol)
|
||||
{
|
||||
return Ok(Some("bjse".to_string()));
|
||||
return Ok(Some(reason.to_string()));
|
||||
}
|
||||
let upper_limit_check_price =
|
||||
self.projected_risk_check_price(ctx, date, symbol, &market, OrderSide::Buy, None);
|
||||
@@ -9093,6 +9106,37 @@ mod tests {
|
||||
NaiveDate::from_ymd_opt(year, month, day).expect("valid date")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn universe_exclude_matches_explicit_symbols_and_bjse_alias() {
|
||||
let excludes = vec![
|
||||
"920149.bj".to_string(),
|
||||
"688555.sh".to_string(),
|
||||
"000001".to_string(),
|
||||
"bjse".to_string(),
|
||||
];
|
||||
|
||||
assert_eq!(
|
||||
PlatformExprStrategy::universe_exclude_reason(&excludes, "920149.BJ"),
|
||||
Some("universe_exclude")
|
||||
);
|
||||
assert_eq!(
|
||||
PlatformExprStrategy::universe_exclude_reason(&excludes, "688555.SH"),
|
||||
Some("universe_exclude")
|
||||
);
|
||||
assert_eq!(
|
||||
PlatformExprStrategy::universe_exclude_reason(&excludes, "000001.SZ"),
|
||||
Some("universe_exclude")
|
||||
);
|
||||
assert_eq!(
|
||||
PlatformExprStrategy::universe_exclude_reason(&["bjse".to_string()], "920508.BJ"),
|
||||
Some("bjse")
|
||||
);
|
||||
assert_eq!(
|
||||
PlatformExprStrategy::universe_exclude_reason(&excludes, "300001.SZ"),
|
||||
None
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn platform_expr_rewrites_nested_ternary() {
|
||||
let expr = "pct_change(\"close\", 10) + (((close / rolling_mean(\"close\", 20)) - 1) > 0 ? 0.04 : -0.04)";
|
||||
|
||||
Reference in New Issue
Block a user