拆分ST与星号ST风控语义

This commit is contained in:
boris
2026-07-03 09:00:50 +08:00
parent c32926cc34
commit 3bb001c374
17 changed files with 308 additions and 36 deletions
+2
View File
@@ -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,
+13 -7
View File
@@ -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<Vec<CandidateEligibility>, 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,
+1
View File
@@ -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,
@@ -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,
@@ -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",
+21 -27
View File
@@ -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<bool>,
#[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<bool>,
#[serde(default, alias = "reject_star_st_selection")]
pub reject_star_st_selection: Option<bool>,
#[serde(default, alias = "reject_star_st_buy")]
pub reject_star_st_buy: Option<bool>,
#[serde(default, alias = "reject_paused_selection")]
pub reject_paused_selection: Option<bool>,
#[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);
+2
View File
@@ -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,
+91 -1
View File
@@ -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);
+1
View File
@@ -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,
+1 -1
View File
@@ -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() },
+1
View File
@@ -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,
+1
View File
@@ -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,
@@ -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,
@@ -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,
+6
View File
@@ -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,
+22
View File
@@ -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,
@@ -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,