diff --git a/crates/fidc-core/src/broker.rs b/crates/fidc-core/src/broker.rs index 3a8a8bf..88873d4 100644 --- a/crates/fidc-core/src/broker.rs +++ b/crates/fidc-core/src/broker.rs @@ -5734,6 +5734,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy, @@ -6208,6 +6209,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, diff --git a/crates/fidc-core/src/data.rs b/crates/fidc-core/src/data.rs index a5006a4..1ba9d87 100644 --- a/crates/fidc-core/src/data.rs +++ b/crates/fidc-core/src/data.rs @@ -202,6 +202,8 @@ pub struct CandidateEligibility { pub date: NaiveDate, pub symbol: String, pub is_st: bool, + #[serde(default)] + pub is_star_st: bool, pub is_new_listing: bool, pub is_paused: bool, pub allow_buy: bool, @@ -215,6 +217,7 @@ pub struct CandidateEligibility { impl CandidateEligibility { pub fn eligible_for_selection(&self) -> bool { !self.is_st + && !self.is_star_st && !self.is_new_listing && !self.is_paused && !self.is_kcb @@ -3128,15 +3131,16 @@ fn read_candidates(path: &Path) -> Result, DataSetErro date: row.parse_date(0)?, symbol: row.get(1)?.to_string(), is_st: row.parse_bool(2)?, - is_new_listing: row.parse_bool(3)?, - is_paused: row.parse_bool(4)?, - allow_buy: row.parse_bool(5)?, - allow_sell: row.parse_bool(6)?, - is_kcb: row.parse_optional_bool(7).unwrap_or(false), - is_one_yuan: row.parse_optional_bool(8).unwrap_or(false), + is_star_st: row.parse_bool(3)?, + is_new_listing: row.parse_bool(4)?, + is_paused: row.parse_bool(5)?, + allow_buy: row.parse_bool(6)?, + allow_sell: row.parse_bool(7)?, + is_kcb: row.parse_optional_bool(8).unwrap_or(false), + is_one_yuan: row.parse_optional_bool(9).unwrap_or(false), risk_level_code: row .fields - .get(9) + .get(10) .map(String::as_str) .map(str::trim) .filter(|value| !value.is_empty()) @@ -4003,6 +4007,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -4093,6 +4098,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, diff --git a/crates/fidc-core/src/engine.rs b/crates/fidc-core/src/engine.rs index 700b8de..d485ec9 100644 --- a/crates/fidc-core/src/engine.rs +++ b/crates/fidc-core/src/engine.rs @@ -4024,6 +4024,7 @@ mod tests { date, symbol: SYMBOL.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, diff --git a/crates/fidc-core/src/platform_expr_strategy.rs b/crates/fidc-core/src/platform_expr_strategy.rs index 3c23f4a..82c76b4 100644 --- a/crates/fidc-core/src/platform_expr_strategy.rs +++ b/crates/fidc-core/src/platform_expr_strategy.rs @@ -8512,6 +8512,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -8637,6 +8638,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: false, @@ -8825,6 +8827,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -9146,6 +9149,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -9287,6 +9291,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -9433,6 +9438,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -9529,6 +9535,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -9642,6 +9649,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: false, @@ -9760,6 +9768,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: false, @@ -9911,6 +9920,7 @@ mod tests { date: first_date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: false, @@ -9923,6 +9933,7 @@ mod tests { date: second_date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: false, @@ -10194,6 +10205,7 @@ mod tests { date, symbol: delayed_symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -10206,6 +10218,7 @@ mod tests { date, symbol: other_symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -10485,6 +10498,7 @@ mod tests { date, symbol: delayed_symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -10497,6 +10511,7 @@ mod tests { date, symbol: other_symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -10716,6 +10731,7 @@ mod tests { date: first_date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -10728,6 +10744,7 @@ mod tests { date: second_date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -10926,6 +10943,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: false, @@ -11044,6 +11062,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: false, @@ -11182,6 +11201,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: false, @@ -11288,6 +11308,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -11422,6 +11443,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -11524,6 +11546,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -11654,6 +11677,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -11788,6 +11812,7 @@ mod tests { date: current, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -11896,6 +11921,7 @@ mod tests { date: current, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -12008,6 +12034,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -12122,6 +12149,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: false, @@ -12235,6 +12263,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: false, @@ -12379,6 +12408,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -12534,6 +12564,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -12690,6 +12721,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -12846,6 +12878,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -13013,6 +13046,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -13171,6 +13205,7 @@ mod tests { date: *date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -13319,6 +13354,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -13458,6 +13494,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: true, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -13578,6 +13615,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -13728,6 +13766,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -13825,6 +13864,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -14048,6 +14088,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -14239,6 +14280,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -14338,6 +14380,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -14453,6 +14496,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: false, @@ -14556,6 +14600,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -14655,6 +14700,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: true, allow_buy: true, @@ -14837,6 +14883,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -15046,6 +15093,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -15215,6 +15263,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -15357,6 +15406,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -15516,6 +15566,7 @@ mod tests { date: decision_date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -15528,6 +15579,7 @@ mod tests { date: execution_date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -15671,6 +15723,7 @@ mod tests { date, symbol: "301001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: true, is_paused: false, allow_buy: true, @@ -15683,6 +15736,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -15803,6 +15857,7 @@ mod tests { date: *date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -15946,6 +16001,7 @@ mod tests { date: *date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -16094,6 +16150,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -16229,6 +16286,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -16365,6 +16423,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -16522,6 +16581,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -16657,6 +16717,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -16814,6 +16875,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -16974,6 +17036,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -17123,6 +17186,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -17297,6 +17361,7 @@ mod tests { date: *date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -17570,6 +17635,7 @@ mod tests { date: *date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -17730,6 +17796,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -17875,6 +17942,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -18056,6 +18124,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -18234,6 +18303,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -18456,6 +18526,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -18606,6 +18677,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -18758,6 +18830,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -18999,6 +19072,7 @@ mod tests { date, symbol: symbol.clone(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -19186,6 +19260,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -19331,6 +19406,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -19470,6 +19546,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -19606,6 +19683,7 @@ mod tests { date, symbol: item.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -19735,6 +19813,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: true, allow_buy: false, @@ -19837,6 +19916,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -19990,6 +20070,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -20162,6 +20243,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -20311,6 +20393,7 @@ mod tests { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -20445,6 +20528,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_kcb: false, is_paused: false, @@ -20565,6 +20649,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_kcb: false, is_paused: false, @@ -21250,6 +21335,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -21374,6 +21460,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -21489,6 +21576,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -21612,6 +21700,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -21753,6 +21842,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -21881,6 +21971,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -22004,6 +22095,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -22121,6 +22213,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -22260,6 +22353,7 @@ mod tests { date: *date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -22467,6 +22561,7 @@ mod tests { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, diff --git a/crates/fidc-core/src/platform_runtime_schema.rs b/crates/fidc-core/src/platform_runtime_schema.rs index ca0f1e4..6270125 100644 --- a/crates/fidc-core/src/platform_runtime_schema.rs +++ b/crates/fidc-core/src/platform_runtime_schema.rs @@ -154,6 +154,7 @@ const RESERVED_SCOPE_NAMES: &[&str] = &[ "round_lot", "paused", "is_st", + "is_star_st", "is_kcb", "is_one_yuan", "is_new_listing", diff --git a/crates/fidc-core/src/platform_strategy_spec.rs b/crates/fidc-core/src/platform_strategy_spec.rs index b63d6da..8b5fac9 100644 --- a/crates/fidc-core/src/platform_strategy_spec.rs +++ b/crates/fidc-core/src/platform_strategy_spec.rs @@ -182,20 +182,14 @@ pub struct StrategyEngineConfig { #[derive(Debug, Clone, Default, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct StrategyRiskPolicySpec { - #[serde( - default, - alias = "reject_st_selection", - alias = "reject_star_st_selection", - alias = "rejectStarStSelection" - )] + #[serde(default, alias = "reject_st_selection", alias = "rejectStSelection")] pub reject_st_selection: Option, - #[serde( - default, - alias = "reject_st_buy", - alias = "reject_star_st_buy", - alias = "rejectStarStBuy" - )] + #[serde(default, alias = "reject_st_buy", alias = "rejectStBuy")] pub reject_st_buy: Option, + #[serde(default, alias = "reject_star_st_selection")] + pub reject_star_st_selection: Option, + #[serde(default, alias = "reject_star_st_buy")] + pub reject_star_st_buy: Option, #[serde(default, alias = "reject_paused_selection")] pub reject_paused_selection: Option, #[serde(default, alias = "reject_paused_buy")] @@ -264,18 +258,10 @@ pub struct StrategyRiskPolicySpec { } const RISK_POLICY_BOOL_ALIAS_GROUPS: &[(&str, &[&str])] = &[ - ( - "rejectStSelection", - &[ - "reject_st_selection", - "rejectStarStSelection", - "reject_star_st_selection", - ], - ), - ( - "rejectStBuy", - &["reject_st_buy", "rejectStarStBuy", "reject_star_st_buy"], - ), + ("rejectStSelection", &["reject_st_selection"]), + ("rejectStarStSelection", &["reject_star_st_selection"]), + ("rejectStBuy", &["reject_st_buy"]), + ("rejectStarStBuy", &["reject_star_st_buy"]), ("rejectPausedSelection", &["reject_paused_selection"]), ("rejectPausedBuy", &["reject_paused_buy"]), ("rejectPausedSell", &["reject_paused_sell"]), @@ -770,6 +756,12 @@ fn apply_risk_policy_overrides( if let Some(value) = policy.reject_st_buy { static_rules.reject_st_buy = value; } + if let Some(value) = policy.reject_star_st_selection { + static_rules.reject_star_st_selection = value; + } + if let Some(value) = policy.reject_star_st_buy { + static_rules.reject_star_st_buy = value; + } if let Some(value) = policy.reject_paused_selection { static_rules.reject_paused_selection = value; } @@ -2246,7 +2238,7 @@ mod tests { } #[test] - fn parses_snake_case_and_star_st_risk_policy_aliases_into_platform_config() { + fn parses_st_and_star_st_risk_policy_switches_into_platform_config() { let spec = serde_json::json!({ "engine_config": { "risk_policy": { @@ -2276,8 +2268,10 @@ mod tests { let cfg = platform_expr_config_from_value("", "", &spec).expect("config"); - assert!(cfg.risk_config.static_rules.reject_st_selection); - assert!(cfg.risk_config.static_rules.reject_st_buy); + assert!(!cfg.risk_config.static_rules.reject_st_selection); + assert!(!cfg.risk_config.static_rules.reject_st_buy); + assert!(cfg.risk_config.static_rules.reject_star_st_selection); + assert!(cfg.risk_config.static_rules.reject_star_st_buy); assert!(!cfg.risk_config.static_rules.reject_paused_selection); assert!(!cfg.risk_config.static_rules.reject_kcb_buy); assert!(!cfg.risk_config.static_rules.reject_bjse_selection); diff --git a/crates/fidc-core/src/portfolio.rs b/crates/fidc-core/src/portfolio.rs index a53ef9e..17a40b3 100644 --- a/crates/fidc-core/src/portfolio.rs +++ b/crates/fidc-core/src/portfolio.rs @@ -1080,6 +1080,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -1167,6 +1168,7 @@ mod tests { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, diff --git a/crates/fidc-core/src/risk_control.rs b/crates/fidc-core/src/risk_control.rs index 4a50f9f..c153965 100644 --- a/crates/fidc-core/src/risk_control.rs +++ b/crates/fidc-core/src/risk_control.rs @@ -15,6 +15,8 @@ pub struct ChinaAShareRiskControl; pub struct StaticRiskRuleConfig { pub reject_st_selection: bool, pub reject_st_buy: bool, + pub reject_star_st_selection: bool, + pub reject_star_st_buy: bool, pub reject_paused_selection: bool, pub reject_paused_buy: bool, pub reject_paused_sell: bool, @@ -45,6 +47,8 @@ impl Default for StaticRiskRuleConfig { Self { reject_st_selection: true, reject_st_buy: true, + reject_star_st_selection: true, + reject_star_st_buy: true, reject_paused_selection: true, reject_paused_buy: true, reject_paused_sell: true, @@ -346,6 +350,14 @@ impl ChinaAShareRiskControl { if reject_st && candidate.is_st { return Some("st"); } + let reject_star_st = match scope { + RiskCheckScope::Selection => config.static_rules.reject_star_st_selection, + RiskCheckScope::Buy => config.static_rules.reject_star_st_buy, + RiskCheckScope::Sell => false, + }; + if reject_star_st && candidate.is_star_st { + return Some("star_st"); + } let reject_new_listing = match scope { RiskCheckScope::Selection => config.static_rules.reject_new_listing_selection, RiskCheckScope::Buy => config.static_rules.reject_new_listing_buy, @@ -547,6 +559,7 @@ fn missing_selection_risk_state_rejected(code: &str, config: &FidcRiskControlCon let fields = missing_risk_state_fields(code); if fields.is_empty() { return config.static_rules.reject_st_selection + || config.static_rules.reject_star_st_selection || config.static_rules.reject_paused_selection || config.static_rules.reject_inactive_selection || config.static_rules.reject_new_listing_selection @@ -564,6 +577,7 @@ fn missing_buy_risk_state_rejected(code: &str, config: &FidcRiskControlConfig) - let fields = missing_risk_state_fields(code); if fields.is_empty() { return config.static_rules.reject_st_buy + || config.static_rules.reject_star_st_buy || config.static_rules.reject_paused_buy || config.static_rules.reject_inactive_buy || config.static_rules.reject_new_listing_buy @@ -603,11 +617,16 @@ fn missing_single_field_rejected( scope: RiskCheckScope, ) -> bool { match field { - "is_st" | "is_star_st" | "st" | "star_st" | "star_st_status" => match scope { + "is_st" | "st" => match scope { RiskCheckScope::Selection => config.static_rules.reject_st_selection, RiskCheckScope::Buy => config.static_rules.reject_st_buy, RiskCheckScope::Sell => false, }, + "is_star_st" | "star_st" | "star_st_status" => match scope { + RiskCheckScope::Selection => config.static_rules.reject_star_st_selection, + RiskCheckScope::Buy => config.static_rules.reject_star_st_buy, + RiskCheckScope::Sell => false, + }, "paused" | "is_paused" | "suspended" | "is_suspended" => match scope { RiskCheckScope::Selection => config.static_rules.reject_paused_selection, RiskCheckScope::Buy => config.static_rules.reject_paused_buy, @@ -669,6 +688,7 @@ fn missing_single_field_rejected( _ => match scope { RiskCheckScope::Selection => { config.static_rules.reject_st_selection + || config.static_rules.reject_star_st_selection || config.static_rules.reject_paused_selection || config.static_rules.reject_inactive_selection || config.static_rules.reject_new_listing_selection @@ -681,6 +701,7 @@ fn missing_single_field_rejected( } RiskCheckScope::Buy => { config.static_rules.reject_st_buy + || config.static_rules.reject_star_st_buy || config.static_rules.reject_paused_buy || config.static_rules.reject_inactive_buy || config.static_rules.reject_new_listing_buy @@ -721,6 +742,7 @@ mod tests { date, symbol: "002633.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -844,6 +866,74 @@ mod tests { assert_eq!(configured_reason, None); } + #[test] + fn st_and_star_st_filters_are_independent() { + let date = d(2025, 1, 2); + let market = market(date, 6.27, 5.63); + + let mut st_candidate = candidate(date); + st_candidate.is_st = true; + st_candidate.allow_sell = true; + let mut star_st_candidate = candidate(date); + star_st_candidate.is_star_st = true; + star_st_candidate.allow_sell = true; + + let mut config = FidcRiskControlConfig::default(); + config.static_rules.reject_st_selection = false; + config.static_rules.reject_st_buy = false; + config.static_rules.reject_star_st_selection = true; + config.static_rules.reject_star_st_buy = true; + + assert_eq!( + ChinaAShareRiskControl::selection_rejection_reason_with_config( + date, + &st_candidate, + &market, + None, + &config, + ), + None + ); + assert_eq!( + ChinaAShareRiskControl::selection_rejection_reason_with_config( + date, + &star_st_candidate, + &market, + None, + &config, + ), + Some("star_st") + ); + + config.static_rules.reject_st_selection = true; + config.static_rules.reject_st_buy = true; + config.static_rules.reject_star_st_selection = false; + config.static_rules.reject_star_st_buy = false; + + assert_eq!( + ChinaAShareRiskControl::buy_rejection_reason_with_config( + date, + &st_candidate, + &market, + None, + 6.27, + &config, + ), + Some("st") + ); + assert_eq!( + ChinaAShareRiskControl::buy_rejection_reason_with_config( + date, + &star_st_candidate, + &market, + None, + 6.27, + &config, + ), + None + ); + } + #[test] fn configurable_bjse_filter_can_be_disabled() { let date = d(2025, 1, 2); diff --git a/crates/fidc-core/src/strategy.rs b/crates/fidc-core/src/strategy.rs index d40a90f..bb619b6 100644 --- a/crates/fidc-core/src/strategy.rs +++ b/crates/fidc-core/src/strategy.rs @@ -3140,6 +3140,7 @@ mod tests { date: *date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, diff --git a/crates/fidc-core/src/strategy_ai.rs b/crates/fidc-core/src/strategy_ai.rs index fbe4aa9..16435fc 100644 --- a/crates/fidc-core/src/strategy_ai.rs +++ b/crates/fidc-core/src/strategy_ai.rs @@ -277,7 +277,7 @@ pub fn built_in_strategy_manual() -> StrategyAiManual { ManualField { name: "turnover_ratio/effective_turnover_ratio".to_string(), field_type: "float".to_string(), detail: "换手率标准字段和有效换手率。".to_string() }, ManualField { name: "open/high/low/close/last/last_price/prev_close/amount".to_string(), field_type: "float".to_string(), detail: "开盘、最高、最低、收盘、盘中价、昨收和成交额。".to_string() }, ManualField { name: "upper_limit/lower_limit/price_tick/round_lot/minimum_order_quantity/order_step_size".to_string(), field_type: "float/int".to_string(), detail: "涨跌停、最小价位、整手、最小下单量和数量步长。KSH/BJSE 等板块可与 round_lot 不同。".to_string() }, - ManualField { name: "paused/is_st/is_kcb/is_one_yuan/is_new_listing".to_string(), field_type: "bool".to_string(), detail: "可交易性与板块标志。".to_string() }, + ManualField { name: "paused/is_st/is_star_st/is_kcb/is_one_yuan/is_new_listing".to_string(), field_type: "bool".to_string(), detail: "可交易性与板块标志,ST 与 *ST 是独立字段。".to_string() }, ManualField { name: "allow_buy/allow_sell/at_upper_limit/at_lower_limit".to_string(), field_type: "bool".to_string(), detail: "盘中买卖与涨跌停状态。".to_string() }, ManualField { name: "touched_upper_limit/touched_lower_limit/hit_upper_limit/hit_lower_limit".to_string(), field_type: "bool".to_string(), detail: "当日分钟执行价曾经触达涨跌停。".to_string() }, ManualField { name: "symbol_open_order_count/symbol_open_buy_qty/symbol_open_sell_qty/latest_symbol_open_order_id".to_string(), field_type: "int".to_string(), detail: "当前证券在挂单簿中的未成交挂单摘要和最近挂单 id。".to_string() }, diff --git a/crates/fidc-core/src/universe.rs b/crates/fidc-core/src/universe.rs index 8545fb8..e9162b4 100644 --- a/crates/fidc-core/src/universe.rs +++ b/crates/fidc-core/src/universe.rs @@ -347,6 +347,7 @@ mod tests { date: d(), symbol: symbol.to_string(), is_st, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, diff --git a/crates/fidc-core/tests/core_rules.rs b/crates/fidc-core/tests/core_rules.rs index d9830a7..0178446 100644 --- a/crates/fidc-core/tests/core_rules.rs +++ b/crates/fidc-core/tests/core_rules.rs @@ -17,6 +17,7 @@ fn candidate() -> CandidateEligibility { date: d(2024, 1, 3), symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, diff --git a/crates/fidc-core/tests/corporate_actions.rs b/crates/fidc-core/tests/corporate_actions.rs index bd458fd..a6fc29d 100644 --- a/crates/fidc-core/tests/corporate_actions.rs +++ b/crates/fidc-core/tests/corporate_actions.rs @@ -137,6 +137,7 @@ fn stock_candidate(date: NaiveDate) -> CandidateEligibility { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -281,6 +282,7 @@ fn engine_reinvests_dividend_receivable_in_round_lots() { date: buy_date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -293,6 +295,7 @@ fn engine_reinvests_dividend_receivable_in_round_lots() { date: ex_date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -305,6 +308,7 @@ fn engine_reinvests_dividend_receivable_in_round_lots() { date: payable_date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, diff --git a/crates/fidc-core/tests/decision_quote_preload.rs b/crates/fidc-core/tests/decision_quote_preload.rs index c680e2d..b63d739 100644 --- a/crates/fidc-core/tests/decision_quote_preload.rs +++ b/crates/fidc-core/tests/decision_quote_preload.rs @@ -143,6 +143,7 @@ fn engine_preloads_declared_decision_quotes_for_current_positions() { date: first, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -155,6 +156,7 @@ fn engine_preloads_declared_decision_quotes_for_current_positions() { date: second, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -309,6 +311,7 @@ fn engine_reuses_preloaded_decision_quotes_without_loader_call() { date: first, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -321,6 +324,7 @@ fn engine_reuses_preloaded_decision_quotes_without_loader_call() { date: second, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -540,6 +544,7 @@ fn engine_loads_distinct_decision_quote_times_on_same_day() { date: first, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -552,6 +557,7 @@ fn engine_loads_distinct_decision_quote_times_on_same_day() { date: second, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, diff --git a/crates/fidc-core/tests/delisting.rs b/crates/fidc-core/tests/delisting.rs index 1608d4d..e3cf953 100644 --- a/crates/fidc-core/tests/delisting.rs +++ b/crates/fidc-core/tests/delisting.rs @@ -175,6 +175,7 @@ fn engine_settles_delisted_position_before_missing_market_snapshot_breaks_run() date: date1, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -187,6 +188,7 @@ fn engine_settles_delisted_position_before_missing_market_snapshot_breaks_run() date: date1, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -199,6 +201,7 @@ fn engine_settles_delisted_position_before_missing_market_snapshot_breaks_run() date: date2, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -398,6 +401,7 @@ fn engine_applies_successor_conversion_before_delisted_cash_settlement() { date: date1, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -410,6 +414,7 @@ fn engine_applies_successor_conversion_before_delisted_cash_settlement() { date: date1, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -422,6 +427,7 @@ fn engine_applies_successor_conversion_before_delisted_cash_settlement() { date: date2, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, diff --git a/crates/fidc-core/tests/engine_hooks.rs b/crates/fidc-core/tests/engine_hooks.rs index cfa07f2..6d6f0ea 100644 --- a/crates/fidc-core/tests/engine_hooks.rs +++ b/crates/fidc-core/tests/engine_hooks.rs @@ -81,6 +81,7 @@ fn single_day_anchor_data(date: NaiveDate) -> DataSet { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -149,6 +150,7 @@ fn candidate_row(date: NaiveDate, symbol: &str) -> CandidateEligibility { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -1125,6 +1127,7 @@ fn engine_runs_strategy_hooks_in_daily_order() { date: date1, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -1137,6 +1140,7 @@ fn engine_runs_strategy_hooks_in_daily_order() { date: date2, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -1284,6 +1288,7 @@ fn engine_executes_open_auction_decisions_before_on_day() { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -1383,6 +1388,7 @@ fn engine_executes_futures_order_intents_against_future_account() { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -1973,6 +1979,7 @@ fn engine_runs_minute_hooks_and_executes_minute_orders() { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -2157,6 +2164,7 @@ fn strategy_context_exposes_engine_native_data_helpers() { date, symbol: "000001.SZ".to_string(), is_st, + is_star_st: false, is_new_listing: false, is_paused, allow_buy: true, @@ -2317,6 +2325,7 @@ fn strategy_context_exposes_final_order_runtime_view() { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -2571,6 +2580,7 @@ fn engine_applies_account_cash_flow_and_financing_intents() { date: date1, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -2583,6 +2593,7 @@ fn engine_applies_account_cash_flow_and_financing_intents() { date: date2, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -2755,6 +2766,7 @@ fn engine_rejects_pending_limit_orders_at_market_close() { date: date1, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -2767,6 +2779,7 @@ fn engine_rejects_pending_limit_orders_at_market_close() { date: date2, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -2958,6 +2971,7 @@ fn engine_runs_scheduled_rules_for_daily_weekly_and_monthly_triggers() { date: date1, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -2970,6 +2984,7 @@ fn engine_runs_scheduled_rules_for_daily_weekly_and_monthly_triggers() { date: date2, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -2982,6 +2997,7 @@ fn engine_runs_scheduled_rules_for_daily_weekly_and_monthly_triggers() { date: date3, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -3207,6 +3223,7 @@ fn engine_dispatches_process_events_to_external_bus_listeners() { date: date1, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -3219,6 +3236,7 @@ fn engine_dispatches_process_events_to_external_bus_listeners() { date: date2, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -3231,6 +3249,7 @@ fn engine_dispatches_process_events_to_external_bus_listeners() { date: date3, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -3564,6 +3583,7 @@ fn engine_applies_dynamic_universe_and_subscription_directives() { date: *date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -3576,6 +3596,7 @@ fn engine_applies_dynamic_universe_and_subscription_directives() { date: *date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -3699,6 +3720,7 @@ fn engine_exposes_current_process_context_to_strategies() { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, diff --git a/crates/fidc-core/tests/explicit_order_flow.rs b/crates/fidc-core/tests/explicit_order_flow.rs index cd0abd6..63c8579 100644 --- a/crates/fidc-core/tests/explicit_order_flow.rs +++ b/crates/fidc-core/tests/explicit_order_flow.rs @@ -56,6 +56,7 @@ fn order_value_rounding_data(date: NaiveDate, symbol: &str, price: f64) -> DataS date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -166,6 +167,7 @@ fn single_symbol_limit_price_data( date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -236,6 +238,7 @@ fn broker_executes_explicit_order_value_buy() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -387,6 +390,7 @@ fn broker_delayed_limit_open_sell_uses_minute_price() { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -520,6 +524,7 @@ fn broker_executes_order_shares_and_order_lots() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -647,6 +652,7 @@ fn broker_executes_target_shares_like_order_to() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_kcb: false, is_paused: false, @@ -805,6 +811,7 @@ fn broker_executes_target_portfolio_smart_with_custom_prices() { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -817,6 +824,7 @@ fn broker_executes_target_portfolio_smart_with_custom_prices() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -949,6 +957,7 @@ fn broker_executes_target_portfolio_smart_with_algo_order_style() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -1091,6 +1100,7 @@ fn broker_executes_order_percent_and_target_percent() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -1214,6 +1224,7 @@ fn broker_uses_day_open_price_for_open_auction_matching() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -1319,6 +1330,7 @@ fn broker_open_auction_uses_auction_volume_without_quote_liquidity() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -1421,6 +1433,7 @@ fn broker_cancels_buy_when_open_hits_upper_limit() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -1535,6 +1548,7 @@ fn broker_applies_price_ratio_slippage_on_snapshot_fills() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -1636,6 +1650,7 @@ fn broker_applies_dynamic_slippage_on_snapshot_fills() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -1742,6 +1757,7 @@ fn broker_applies_tick_size_slippage_on_intraday_last_fills() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -1861,6 +1877,7 @@ fn broker_rejects_intraday_last_order_without_execution_quotes() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -1969,6 +1986,7 @@ fn broker_executes_intraday_last_on_start_quote_without_trade_delta() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -2086,6 +2104,7 @@ fn broker_cancels_market_order_remainder_when_intraday_quote_liquidity_exhausted date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -2215,6 +2234,7 @@ fn broker_cancels_market_buy_when_minute_has_no_volume() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -2320,6 +2340,7 @@ fn broker_splits_intraday_quote_fills_and_tracks_commission_by_order() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -2482,6 +2503,7 @@ fn broker_aggregates_intraday_quote_fills_into_vwap_leg() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -2628,6 +2650,7 @@ fn broker_executes_algo_vwap_value_with_time_window() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -2787,6 +2810,7 @@ fn broker_executes_algo_twap_percent_across_window_quotes() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -2948,6 +2972,7 @@ fn broker_uses_best_own_price_for_intraday_matching() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -3064,6 +3089,7 @@ fn broker_uses_best_counterparty_price_for_intraday_matching() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -3230,6 +3256,7 @@ fn rebalance_optimizer_skips_unfunded_buy_when_existing_position_cannot_sell() { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -3242,6 +3269,7 @@ fn rebalance_optimizer_skips_unfunded_buy_when_existing_position_cannot_sell() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -3420,6 +3448,7 @@ fn rebalance_uses_prev_close_for_open_auction_valuation() { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -3432,6 +3461,7 @@ fn rebalance_uses_prev_close_for_open_auction_valuation() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -3604,6 +3634,7 @@ fn rebalance_optimizer_prioritizes_higher_target_weight_when_cash_is_tight() { date, symbol: "000001.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -3616,6 +3647,7 @@ fn rebalance_optimizer_prioritizes_higher_target_weight_when_cash_is_tight() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -3743,6 +3775,7 @@ fn broker_uses_board_specific_min_quantity_and_step_size_for_buy_sizing() { date, symbol: "688001.SH".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -3846,6 +3879,7 @@ fn broker_allows_bjse_quantities_above_minimum_without_round_lot_step() { date, symbol: "430001.BJ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -3951,6 +3985,7 @@ fn broker_allows_full_odd_lot_sell_when_liquidating_position() { date, symbol: symbol.to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -4067,6 +4102,7 @@ fn same_day_sell_then_rebuy_is_rejected_by_default() { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -4206,6 +4242,7 @@ fn same_day_sell_then_rebuy_can_be_allowed_by_policy() { date, symbol: (*symbol).to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -4466,6 +4503,7 @@ fn two_day_limit_order_data(day1_open: f64, day2_open: f64) -> DataSet { date: day1, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -4478,6 +4516,7 @@ fn two_day_limit_order_data(day1_open: f64, day2_open: f64) -> DataSet { date: day2, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true, @@ -4885,6 +4924,7 @@ fn broker_reserves_sellable_quantity_for_open_limit_sells() { date, symbol: "000002.SZ".to_string(), is_st: false, + is_star_st: false, is_new_listing: false, is_paused: false, allow_buy: true,