diff --git a/Cargo.lock b/Cargo.lock index f29ee3d..da19904 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,6 +145,15 @@ version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" +[[package]] +name = "castaway" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" +dependencies = [ + "rustversion", +] + [[package]] name = "cc" version = "1.2.59" @@ -192,6 +201,20 @@ dependencies = [ "windows-link", ] +[[package]] +name = "compact_str" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79fcda08c33bb58b97008b2cdada6622500e949e060f5913361763121abd2416" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "serde", + "static_assertions", + "zmij", +] + [[package]] name = "const-random" version = "0.1.18" @@ -316,6 +339,7 @@ version = "0.1.0" dependencies = [ "ahash 0.8.12", "chrono", + "compact_str", "indexmap", "rayon", "rhai", @@ -2044,3 +2068,9 @@ dependencies = [ "quote", "syn 3.0.5", ] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/crates/fidc-core/Cargo.toml b/crates/fidc-core/Cargo.toml index c685408..f635bc0 100644 --- a/crates/fidc-core/Cargo.toml +++ b/crates/fidc-core/Cargo.toml @@ -6,6 +6,7 @@ license.workspace = true authors.workspace = true [dependencies] +compact_str = { version = "=0.10.0", features = ["serde"] } rust_decimal.workspace = true ahash.workspace = true chrono.workspace = true diff --git a/crates/fidc-core/src/broker.rs b/crates/fidc-core/src/broker.rs index 643973d..2eeb8b6 100644 --- a/crates/fidc-core/src/broker.rs +++ b/crates/fidc-core/src/broker.rs @@ -8299,7 +8299,7 @@ mod tests { let date = chrono::NaiveDate::from_ymd_opt(2025, 1, 2).expect("valid date"); DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-02 09:33:00".to_string()), day_open: 10.0, open: 10.0, @@ -8425,7 +8425,7 @@ mod tests { let date = chrono::NaiveDate::from_ymd_opt(2025, 1, 2).expect("valid date"); CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -8505,7 +8505,7 @@ mod tests { .iter() .map(|symbol| { let mut snapshot = limit_test_snapshot(); - snapshot.symbol = (*symbol).to_string(); + snapshot.symbol = (*symbol).into(); if block_exit && *symbol == "000001.SZ" { snapshot.day_open = snapshot.lower_limit; snapshot.open = snapshot.lower_limit; @@ -8520,7 +8520,7 @@ mod tests { .iter() .map(|symbol| { let mut candidate = limit_test_candidate(true, true); - candidate.symbol = (*symbol).to_string(); + candidate.symbol = (*symbol).into(); candidate }) .collect::>(); @@ -10479,7 +10479,7 @@ mod tests { .iter() .map(|symbol| { let mut snapshot = limit_test_snapshot(); - snapshot.symbol = (*symbol).to_string(); + snapshot.symbol = (*symbol).into(); if *symbol == "000001.SZ" { snapshot.day_open = 9.0; snapshot.open = 9.0; @@ -10497,7 +10497,7 @@ mod tests { .iter() .map(|symbol| { let mut candidate = limit_test_candidate(true, true); - candidate.symbol = (*symbol).to_string(); + candidate.symbol = (*symbol).into(); candidate }) .collect::>(); @@ -10631,7 +10631,7 @@ mod tests { .iter() .map(|symbol| { let mut snapshot = limit_test_snapshot(); - snapshot.symbol = (*symbol).to_string(); + snapshot.symbol = (*symbol).into(); snapshot }) .collect::>(); @@ -10639,7 +10639,7 @@ mod tests { .iter() .map(|symbol| { let mut candidate = limit_test_candidate(true, true); - candidate.symbol = (*symbol).to_string(); + candidate.symbol = (*symbol).into(); candidate }) .collect::>(); @@ -10696,7 +10696,7 @@ mod tests { .iter() .map(|symbol| { let mut snapshot = limit_test_snapshot(); - snapshot.symbol = (*symbol).to_string(); + snapshot.symbol = (*symbol).into(); snapshot }) .collect::>(); @@ -10704,7 +10704,7 @@ mod tests { .iter() .map(|symbol| { let mut candidate = limit_test_candidate(true, true); - candidate.symbol = (*symbol).to_string(); + candidate.symbol = (*symbol).into(); candidate }) .collect::>(); @@ -10834,7 +10834,7 @@ mod tests { .iter() .map(|symbol| { let mut snapshot = limit_test_snapshot(); - snapshot.symbol = (*symbol).to_string(); + snapshot.symbol = (*symbol).into(); snapshot }) .collect::>(); @@ -10842,7 +10842,7 @@ mod tests { .iter() .map(|symbol| { let mut candidate = limit_test_candidate(true, true); - candidate.symbol = (*symbol).to_string(); + candidate.symbol = (*symbol).into(); candidate }) .collect::>(); @@ -11623,7 +11623,7 @@ mod tests { .with_volume_limit(false) .with_liquidity_limit(false); let mut snapshot = limit_test_snapshot(); - snapshot.symbol = symbol.to_string(); + snapshot.symbol = symbol.into(); snapshot.last_price = 4.21; snapshot.close = 4.21; snapshot.bid1 = 4.20; @@ -11708,7 +11708,7 @@ mod tests { .with_inactive_limit(false); let snapshot = DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2023-05-08 15:00:00".to_string()), day_open: 5.86, open: 5.86, @@ -11756,7 +11756,7 @@ mod tests { Vec::new(), vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, diff --git a/crates/fidc-core/src/data.rs b/crates/fidc-core/src/data.rs index 5192a44..c0a02ef 100644 --- a/crates/fidc-core/src/data.rs +++ b/crates/fidc-core/src/data.rs @@ -5,6 +5,7 @@ use std::sync::{Arc, OnceLock}; use ahash::AHashMap; use chrono::{NaiveDate, NaiveDateTime}; +use compact_str::CompactString; use rayon::prelude::*; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -122,7 +123,7 @@ pub enum PriceField { pub struct DailyMarketSnapshot { #[serde(with = "date_format")] pub date: NaiveDate, - pub symbol: String, + pub symbol: CompactString, pub timestamp: Option, pub day_open: f64, pub open: f64, @@ -199,13 +200,13 @@ impl DailyMarketSnapshot { } } -pub type NumericFactorMap = BTreeMap, f64>; +pub use crate::numeric_factors::NumericFactorMap; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DailyFactorSnapshot { #[serde(with = "date_format")] pub date: NaiveDate, - pub symbol: String, + pub symbol: CompactString, pub market_cap_bn: f64, pub free_float_cap_bn: f64, pub pe_ttm: f64, @@ -232,7 +233,7 @@ pub struct BenchmarkSnapshot { pub struct CandidateEligibility { #[serde(with = "date_format")] pub date: NaiveDate, - pub symbol: String, + pub symbol: CompactString, pub is_st: bool, #[serde(default)] pub is_star_st: bool, @@ -1204,7 +1205,7 @@ impl SymbolPriceSeries { fn snapshot_at(&self, index: usize) -> DailyMarketSnapshot { DailyMarketSnapshot { date: self.dates[index], - symbol: self.symbol.clone(), + symbol: self.symbol.as_str().into(), timestamp: self.timestamps[index].clone(), day_open: self.day_opens[index], open: self.opens[index], @@ -2865,7 +2866,7 @@ impl DataSet { .filter_map(|snapshot| { factor_numeric_value(snapshot, &field).map(|value| FactorValue { date: snapshot.date, - symbol: snapshot.symbol.clone(), + symbol: snapshot.symbol.to_string(), field: field.clone(), value, }) @@ -2959,7 +2960,7 @@ impl DataSet { .or_else(|| row.extra_factors.get("margin_all")) .is_some_and(|value| *value > 0.0) }) - .map(|row| row.symbol.clone()) + .map(|row| row.symbol.to_string()) .collect::>() }) .unwrap_or_default(); @@ -3051,7 +3052,7 @@ impl DataSet { if snapshot.prev_close.is_finite() && snapshot.prev_close > 0.0 { Some(FactorValue { date: snapshot.date, - symbol: snapshot.symbol.clone(), + symbol: snapshot.symbol.to_string(), field: "price_change_rate".to_string(), value: snapshot.close / snapshot.prev_close - 1.0, }) @@ -3173,7 +3174,7 @@ impl DataSet { if let Some(value) = factor_numeric_value(snapshot, field) { return Some(FactorValue { date: *factor_date, - symbol: snapshot.symbol.clone(), + symbol: snapshot.symbol.to_string(), field: field.clone(), value, }); @@ -3524,7 +3525,7 @@ impl DataSet { if let Some(value) = factor_numeric_value(snapshot, field) { rows.push(FactorValue { date: snapshot.date, - symbol: snapshot.symbol.clone(), + symbol: snapshot.symbol.to_string(), field: output_field.clone(), value, }); @@ -4322,7 +4323,7 @@ fn daily_market_price_bar(snapshot: &DailyMarketSnapshot) -> PriceBar { PriceBar { date: snapshot.date, timestamp: snapshot.timestamp.clone(), - symbol: snapshot.symbol.clone(), + symbol: snapshot.symbol.to_string(), frequency: "1d".to_string(), open: snapshot.open, high: snapshot.high, @@ -4383,7 +4384,7 @@ fn normalize_factor_snapshots( { return Err(DataSetError::ReservedTypedFactorInExtraMap { date: snapshot.date, - symbol: snapshot.symbol, + symbol: snapshot.symbol.to_string(), field: BACKWARD_ADJUSTMENT_FACTOR_FIELD, }); } @@ -4392,7 +4393,7 @@ fn normalize_factor_snapshots( { return Err(DataSetError::InvalidBackwardAdjustmentFactor { date: snapshot.date, - symbol: snapshot.symbol, + symbol: snapshot.symbol.to_string(), value, }); } @@ -4428,7 +4429,7 @@ fn normalize_factor_snapshots( { return Err(DataSetError::ReservedTypedFactorInExtraMap { date: snapshot.date, - symbol: snapshot.symbol, + symbol: snapshot.symbol.to_string(), field: BACKWARD_ADJUSTMENT_FACTOR_FIELD, }); } @@ -4510,21 +4511,21 @@ fn build_symbol_id_index( for rows in market_by_date.values() { for row in rows { if !symbols.contains(row.symbol.as_str()) { - symbols.insert(row.symbol.clone()); + symbols.insert(row.symbol.to_string()); } } } for rows in factor_by_date.values() { for row in rows { if !symbols.contains(row.symbol.as_str()) { - symbols.insert(row.symbol.clone()); + symbols.insert(row.symbol.to_string()); } } } for rows in candidate_by_date.values() { for row in rows { if !symbols.contains(row.symbol.as_str()) { - symbols.insert(row.symbol.clone()); + symbols.insert(row.symbol.to_string()); } } } @@ -4942,7 +4943,7 @@ fn build_fundamental_universe_for_date( continue; } rows.push(EligibleUniverseSnapshot { - symbol: factor.symbol.clone(), + symbol: factor.symbol.to_string(), market_cap_bn, free_float_cap_bn: decision_free_float_cap_bn(factor), }); @@ -5012,7 +5013,7 @@ fn build_eligible_universe_for_date_from_factors( date, candidate, market, - instruments.get(&factor.symbol), + instruments.get(factor.symbol.as_str()), risk_config, ) .is_some() @@ -5025,7 +5026,7 @@ fn build_eligible_universe_for_date_from_factors( } let free_float_cap_bn = decision_free_float_cap_bn(factor); rows.push(EligibleUniverseSnapshot { - symbol: factor.symbol.clone(), + symbol: factor.symbol.to_string(), market_cap_bn, free_float_cap_bn, }); @@ -5042,7 +5043,7 @@ fn build_eligible_universe_for_date_from_factors( pub(crate) fn missing_candidate_risk_state(date: NaiveDate, symbol: &str) -> CandidateEligibility { CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -5070,7 +5071,7 @@ mod tests { fn market_row(date: &str, prev_close: f64, volume: u64) -> DailyMarketSnapshot { DailyMarketSnapshot { date: NaiveDate::parse_from_str(date, "%Y-%m-%d").unwrap(), - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: None, day_open: prev_close, open: prev_close, @@ -5352,10 +5353,10 @@ mod tests { for (symbol_index, symbol) in symbols.into_iter().enumerate().rev() { let close = 10.0 + date_index as f64 + symbol_index as f64; let mut market_row = market_row(&date_text, close, 1_000_000); - market_row.symbol = symbol.to_string(); + market_row.symbol = symbol.into(); let factor_row = DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 100.0 + close, free_float_cap_bn: 80.0 + close, pe_ttm: 0.0, @@ -5366,7 +5367,7 @@ mod tests { }; let candidate_row = CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -5534,12 +5535,12 @@ mod tests { }; let market = |symbol: &str, close: f64| { let mut row = market_row("2025-01-02", close, 1_000_000); - row.symbol = symbol.to_string(); + row.symbol = symbol.into(); row }; let factor = |symbol: &str, market_cap_bn: f64| DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn, free_float_cap_bn: market_cap_bn, pe_ttm: 0.0, @@ -5550,7 +5551,7 @@ mod tests { }; let candidate = |symbol: &str| CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -5773,7 +5774,7 @@ mod tests { .iter() .map(|date| DailyFactorSnapshot { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 8.0, pe_ttm: 10.0, @@ -5977,7 +5978,7 @@ mod tests { .enumerate() .map(|(index, symbol)| { let mut row = market_row("2025-01-02", 10.0 + index as f64 / 1000.0, 1_000_000); - row.symbol = symbol.clone(); + row.symbol = symbol.clone().into(); row }) .collect::>(); @@ -5986,7 +5987,7 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: symbol.clone(), + symbol: symbol.clone().into(), market_cap_bn: 10.0 + index as f64 / 1000.0, free_float_cap_bn: 8.0, pe_ttm: 10.0, @@ -6000,7 +6001,7 @@ mod tests { .iter() .map(|symbol| CandidateEligibility { date, - symbol: symbol.clone(), + symbol: symbol.clone().into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -6289,14 +6290,14 @@ mod tests { fn factor_numeric_value_normalizes_fields_without_changing_aliases() { let snapshot = DailyFactorSnapshot { date: NaiveDate::parse_from_str("2025-01-02", "%Y-%m-%d").unwrap(), - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.5, free_float_cap_bn: 8.0, pe_ttm: 10.0, turnover_ratio: None, effective_turnover_ratio: None, adjustment_factor_backward1: Some(1.25), - extra_factors: BTreeMap::from([("custom_factor".into(), 3.5)]), + extra_factors: From::from([("custom_factor".into(), 3.5)]), }; assert_eq!(factor_numeric_value(&snapshot, " MARKET_CAP "), Some(12.5)); @@ -6312,14 +6313,14 @@ mod tests { let date = NaiveDate::parse_from_str("2025-01-02", "%Y-%m-%d").unwrap(); let clean = normalize_factor_snapshots(vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 1.0, free_float_cap_bn: 1.0, pe_ttm: 1.0, turnover_ratio: None, effective_turnover_ratio: None, adjustment_factor_backward1: None, - extra_factors: BTreeMap::from([(Cow::Borrowed("amount"), 10.0)]), + extra_factors: From::from([(Cow::Borrowed("amount"), 10.0)]), }]) .expect("normalize clean factor snapshot"); assert!(matches!( @@ -6329,14 +6330,14 @@ mod tests { let dirty = normalize_factor_snapshots(vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 1.0, free_float_cap_bn: 1.0, pe_ttm: 1.0, turnover_ratio: None, effective_turnover_ratio: None, adjustment_factor_backward1: None, - extra_factors: BTreeMap::from([ + extra_factors: From::from([ (Cow::Owned(" CUSTOM_FACTOR ".to_string()), 2.0), (Cow::Borrowed("bad_nan"), f64::NAN), ]), @@ -6351,7 +6352,7 @@ mod tests { let date = NaiveDate::parse_from_str("2025-01-02", "%Y-%m-%d").unwrap(); let snapshot = |adjustment_factor_backward1, extra_factors| DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 1.0, free_float_cap_bn: 1.0, pe_ttm: 1.0, @@ -6364,12 +6365,12 @@ mod tests { assert!(matches!( normalize_factor_snapshots(vec![snapshot( Some(1.0), - BTreeMap::from([(Cow::Borrowed(BACKWARD_ADJUSTMENT_FACTOR_FIELD), 1.0)]), + BTreeMap::from([(Cow::Borrowed(BACKWARD_ADJUSTMENT_FACTOR_FIELD), 1.0)]).into(), )]), Err(DataSetError::ReservedTypedFactorInExtraMap { .. }) )); assert!(matches!( - normalize_factor_snapshots(vec![snapshot(Some(0.0), BTreeMap::new())]), + normalize_factor_snapshots(vec![snapshot(Some(0.0), BTreeMap::new().into())]), Err(DataSetError::InvalidBackwardAdjustmentFactor { .. }) )); for field in [ @@ -6382,7 +6383,7 @@ mod tests { matches!( normalize_factor_snapshots(vec![snapshot( typed_value, - BTreeMap::from([(Cow::Borrowed(field), 2.0)]), + BTreeMap::from([(Cow::Borrowed(field), 2.0)]).into(), )]), Err(DataSetError::ReservedTypedFactorInExtraMap { .. }) ), @@ -6478,14 +6479,14 @@ mod tests { } DailyFactorSnapshot { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 8.0, pe_ttm: 10.0, turnover_ratio: None, effective_turnover_ratio: None, adjustment_factor_backward1: None, - extra_factors, + extra_factors: extra_factors.into(), } }) .collect(), @@ -6537,14 +6538,14 @@ mod tests { .iter() .map(|date| DailyFactorSnapshot { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 8.0, pe_ttm: 10.0, turnover_ratio: None, effective_turnover_ratio: None, adjustment_factor_backward1: Some(1.0), - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), Vec::new(), @@ -6831,14 +6832,14 @@ mod tests { .zip(factors) .map(|(date, factor)| DailyFactorSnapshot { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 8.0, pe_ttm: 10.0, turnover_ratio: None, effective_turnover_ratio: None, adjustment_factor_backward1: Some(factor), - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), Vec::new(), @@ -6929,14 +6930,14 @@ mod tests { .iter() .map(|date| DailyFactorSnapshot { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 8.0, pe_ttm: 10.0, turnover_ratio: None, effective_turnover_ratio: None, adjustment_factor_backward1: (*date != dates[3]).then_some(1.0), - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), Vec::new(), @@ -7008,7 +7009,7 @@ mod tests { }; let market = |symbol: &str, prev_close: f64, close: f64| DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-01-06 10:18:00".to_string()), day_open: prev_close, open: prev_close, @@ -7032,18 +7033,18 @@ mod tests { let factor = |symbol: &str, market_cap_bn: f64, free_float_cap_bn: f64| DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn, free_float_cap_bn, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }; let candidate = |symbol: &str| CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -7108,7 +7109,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-01-06 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -7131,14 +7132,14 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 9.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], Vec::new(), vec![BenchmarkSnapshot { @@ -7193,7 +7194,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-01-06 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -7216,18 +7217,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 9.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -7268,14 +7269,14 @@ mod tests { let date = NaiveDate::parse_from_str("2025-01-06", "%Y-%m-%d").unwrap(); let factor = DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 4.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }; assert!((decision_market_cap_bn(&factor) - 12.0).abs() < 1e-9); diff --git a/crates/fidc-core/src/engine.rs b/crates/fidc-core/src/engine.rs index ff90a7f..1518635 100644 --- a/crates/fidc-core/src/engine.rs +++ b/crates/fidc-core/src/engine.rs @@ -5425,7 +5425,7 @@ mod tests { fn market(date: NaiveDate, open: f64, close: f64) -> DailyMarketSnapshot { DailyMarketSnapshot { date, - symbol: SYMBOL.to_string(), + symbol: SYMBOL.into(), timestamp: Some(format!("{date} 15:00:00")), day_open: open, open, @@ -5479,21 +5479,21 @@ mod tests { fn factor(date: NaiveDate) -> DailyFactorSnapshot { DailyFactorSnapshot { date, - symbol: SYMBOL.to_string(), + symbol: SYMBOL.into(), market_cap_bn: 10.0, free_float_cap_bn: 8.0, pe_ttm: 12.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), } } fn candidate(date: NaiveDate) -> CandidateEligibility { CandidateEligibility { date, - symbol: SYMBOL.to_string(), + symbol: SYMBOL.into(), is_st: false, is_star_st: false, is_new_listing: false, diff --git a/crates/fidc-core/src/lib.rs b/crates/fidc-core/src/lib.rs index 78e6161..2d00b2f 100644 --- a/crates/fidc-core/src/lib.rs +++ b/crates/fidc-core/src/lib.rs @@ -2,6 +2,7 @@ pub mod broker; pub mod calendar; pub mod cost; pub mod data; +mod numeric_factors; pub mod daily_patterns; pub mod pattern_context; pub mod session_events; diff --git a/crates/fidc-core/src/numeric_factors.rs b/crates/fidc-core/src/numeric_factors.rs new file mode 100644 index 0000000..75c5c86 --- /dev/null +++ b/crates/fidc-core/src/numeric_factors.rs @@ -0,0 +1,339 @@ +use std::borrow::Cow; +use std::collections::BTreeMap; +use std::fmt; +use std::ops::Index; + +use serde::de::{MapAccess, Visitor}; +use serde::ser::SerializeMap; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +/// Sorted numeric fields stored contiguously, without a tree node per snapshot. +#[derive(Clone, Default, PartialEq)] +pub struct NumericFactorMap { + entries: Vec<(Cow<'static, str>, f64)>, +} + +impl NumericFactorMap { + pub const fn new() -> Self { + Self { + entries: Vec::new(), + } + } + + pub fn len(&self) -> usize { + self.entries.len() + } + pub fn is_empty(&self) -> bool { + self.entries.is_empty() + } + pub fn clear(&mut self) { + self.entries.clear(); + } + + pub fn get(&self, key: &str) -> Option<&f64> { + self.entries + .binary_search_by(|(name, _)| name.as_ref().cmp(key)) + .ok() + .map(|index| &self.entries[index].1) + } + + pub fn get_mut(&mut self, key: &str) -> Option<&mut f64> { + self.entries + .binary_search_by(|(name, _)| name.as_ref().cmp(key)) + .ok() + .map(|index| &mut self.entries[index].1) + } + + pub fn contains_key(&self, key: &str) -> bool { + self.get(key).is_some() + } + + pub fn insert(&mut self, key: Cow<'static, str>, value: f64) -> Option { + if self + .entries + .last() + .is_none_or(|(last, _)| last.as_ref() < key.as_ref()) + { + self.entries.push((key, value)); + return None; + } + match self + .entries + .binary_search_by(|(name, _)| name.as_ref().cmp(key.as_ref())) + { + Ok(index) => Some(std::mem::replace(&mut self.entries[index].1, value)), + Err(index) => { + self.entries.insert(index, (key, value)); + None + } + } + } + + pub fn remove(&mut self, key: &str) -> Option { + self.entries + .binary_search_by(|(name, _)| name.as_ref().cmp(key)) + .ok() + .map(|index| self.entries.remove(index).1) + } + + pub fn retain(&mut self, mut keep: impl FnMut(&Cow<'static, str>, &mut f64) -> bool) { + self.entries.retain_mut(|(key, value)| keep(key, value)); + } + + pub fn iter(&self) -> Iter<'_> { + Iter(self.entries.iter()) + } + pub fn keys(&self) -> impl DoubleEndedIterator> + ExactSizeIterator { + self.entries.iter().map(|(key, _)| key) + } + pub fn values(&self) -> impl DoubleEndedIterator + ExactSizeIterator { + self.entries.iter().map(|(_, value)| value) + } +} + +impl fmt::Debug for NumericFactorMap { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_map().entries(self).finish() + } +} + +impl Index<&str> for NumericFactorMap { + type Output = f64; + fn index(&self, key: &str) -> &Self::Output { + self.get(key).expect("numeric factor key not found") + } +} + +pub struct Iter<'a>(std::slice::Iter<'a, (Cow<'static, str>, f64)>); +impl<'a> Iterator for Iter<'a> { + type Item = (&'a Cow<'static, str>, &'a f64); + fn next(&mut self) -> Option { + self.0.next().map(|(k, v)| (k, v)) + } + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } +} +impl DoubleEndedIterator for Iter<'_> { + fn next_back(&mut self) -> Option { + self.0.next_back().map(|(k, v)| (k, v)) + } +} +impl ExactSizeIterator for Iter<'_> {} +impl<'a> IntoIterator for &'a NumericFactorMap { + type Item = (&'a Cow<'static, str>, &'a f64); + type IntoIter = Iter<'a>; + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} +impl IntoIterator for NumericFactorMap { + type Item = (Cow<'static, str>, f64); + type IntoIter = std::vec::IntoIter; + fn into_iter(self) -> Self::IntoIter { + self.entries.into_iter() + } +} + +impl FromIterator<(Cow<'static, str>, f64)> for NumericFactorMap { + fn from_iter, f64)>>(iter: T) -> Self { + let mut entries: Vec<_> = iter.into_iter().collect(); + // Stable sorting preserves last-value-wins for repeated input keys. + if !entries.windows(2).all(|pair| pair[0].0 <= pair[1].0) { + entries.sort_by(|left, right| left.0.cmp(&right.0)); + } + entries.dedup_by(|later, earlier| { + if later.0 == earlier.0 { + earlier.1 = later.1; + true + } else { + false + } + }); + Self { entries } + } +} +impl Extend<(Cow<'static, str>, f64)> for NumericFactorMap { + fn extend, f64)>>(&mut self, iter: T) { + let mut incoming: Self = iter.into_iter().collect(); + if incoming.is_empty() { + return; + } + if self.is_empty() { + *self = incoming; + return; + } + if self.entries.last().unwrap().0 < incoming.entries[0].0 { + self.entries.append(&mut incoming.entries); + return; + } + // Merge sorted sets in linear time; wide factor batches must not shift + // the existing vector once per field. Existing keys keep their identity. + let mut merged = Vec::with_capacity(self.len() + incoming.len()); + let mut old = std::mem::take(&mut self.entries).into_iter().peekable(); + let mut new = incoming.entries.into_iter().peekable(); + while let (Some(left), Some(right)) = (old.peek(), new.peek()) { + match left.0.cmp(&right.0) { + std::cmp::Ordering::Less => merged.push(old.next().unwrap()), + std::cmp::Ordering::Greater => merged.push(new.next().unwrap()), + std::cmp::Ordering::Equal => { + let (key, _) = old.next().unwrap(); + merged.push((key, new.next().unwrap().1)); + } + } + } + merged.extend(old); + merged.extend(new); + self.entries = merged; + } +} +impl From<[(Cow<'static, str>, f64); N]> for NumericFactorMap { + fn from(entries: [(Cow<'static, str>, f64); N]) -> Self { + entries.into_iter().collect() + } +} +impl From, f64>> for NumericFactorMap { + fn from(entries: BTreeMap, f64>) -> Self { + Self { + entries: entries.into_iter().collect(), + } + } +} + +impl Serialize for NumericFactorMap { + fn serialize(&self, serializer: S) -> Result { + let mut map = serializer.serialize_map(Some(self.len()))?; + for (key, value) in self { + map.serialize_entry(key, value)?; + } + map.end() + } +} +impl<'de> Deserialize<'de> for NumericFactorMap { + fn deserialize>(deserializer: D) -> Result { + struct Fields; + impl<'de> Visitor<'de> for Fields { + type Value = NumericFactorMap; + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("a numeric factor map") + } + fn visit_map>(self, mut map: A) -> Result { + let mut entries = Vec::new(); + while let Some((key, value)) = map.next_entry::()? { + entries.push((Cow::Owned(key), value)); + } + Ok(entries.into_iter().collect()) + } + } + deserializer.deserialize_map(Fields) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn updates_order_removal_and_values_match_tree_map() { + let mut flat = NumericFactorMap::new(); + let mut tree = BTreeMap::new(); + let mut seed = 71_u64; + for index in 0..10000 { + seed = seed.wrapping_mul(6364136223846793005).wrapping_add(1); + let key: Cow<'static, str> = Cow::Owned(format!("factor_{:04}", (seed >> 32) % 1000)); + let value = (index as f64 - 5000.0) / 7.0; + if index % 11 == 0 { + assert_eq!(flat.remove(key.as_ref()), tree.remove(key.as_ref())); + } else { + assert_eq!(flat.insert(key.clone(), value), tree.insert(key, value)); + } + } + assert_eq!( + flat.iter().collect::>(), + tree.iter().collect::>() + ); + flat.retain(|_, value| *value > 100.0); + tree.retain(|_, value| *value > 100.0); + assert_eq!( + flat.iter().collect::>(), + tree.iter().collect::>() + ); + assert_eq!( + std::mem::size_of::(), + std::mem::size_of_val(&tree) + ); + } + + #[test] + fn bulk_load_is_sorted_and_keeps_last_value_for_each_field() { + let input = vec![ + (Cow::Borrowed("z"), 2.0), + (Cow::Borrowed("a"), 1.0), + (Cow::Borrowed("z"), 3.0), + (Cow::Borrowed("z"), 4.0), + ]; + let flat: NumericFactorMap = input.clone().into_iter().collect(); + let tree: BTreeMap<_, _> = input.into_iter().collect(); + assert_eq!( + flat.iter().collect::>(), + tree.iter().collect::>() + ); + assert_eq!(flat["z"], 4.0); + } + + #[test] + fn serialization_keeps_the_map_contract_and_precise_numbers() { + let input = [ + (Cow::Borrowed("zero"), -0.0), + (Cow::Borrowed("tiny"), 1.0000000000000002), + (Cow::Borrowed("large"), 9.123456789123456e20), + ]; + let flat = NumericFactorMap::from(input.clone()); + let tree = BTreeMap::from(input); + let json = serde_json::to_string(&flat).unwrap(); + assert_eq!(json, serde_json::to_string(&tree).unwrap()); + let decoded: NumericFactorMap = serde_json::from_str(&json).unwrap(); + for (key, value) in &flat { + assert_eq!(value.to_bits(), decoded[key.as_ref()].to_bits()); + } + let duplicate: NumericFactorMap = serde_json::from_str(r#"{"x":1,"x":2}"#).unwrap(); + assert_eq!(duplicate["x"], 2.0); + } + + #[test] + fn clone_does_not_share_mutable_values() { + let original = NumericFactorMap::from([(Cow::Borrowed("signal"), 1.0)]); + let mut copy = original.clone(); + *copy.get_mut("signal").unwrap() = 0.0; + copy.insert(Cow::Borrowed("other"), 2.0); + assert_eq!(original["signal"], 1.0); + assert!(!original.contains_key("other")); + } + + #[test] + fn wide_batch_merge_matches_tree_and_preserves_old_key_ownership() { + let entries = (0..4096) + .map(|index| (Cow::Owned(format!("f_{index:05}")), index as f64)) + .collect::>(); + let mut flat: NumericFactorMap = entries.clone().into_iter().collect(); + let mut tree = BTreeMap::from_iter(entries); + flat.insert(Cow::Borrowed("shared"), -0.0); + tree.insert(Cow::Borrowed("shared"), -0.0); + let incoming = (2048..8192) + .rev() + .map(|index| (Cow::Owned(format!("f_{index:05}")), -(index as f64))) + .chain([(Cow::Owned("shared".to_owned()), 1.0)]) + .collect::>(); + flat.extend(incoming.clone()); + tree.extend(incoming); + assert_eq!( + flat.iter().collect::>(), + tree.iter().collect::>() + ); + assert!(matches!(flat.keys().last(), Some(Cow::Borrowed("shared")))); + flat.extend([(Cow::Borrowed("zz"), f64::NAN)]); + assert!(flat["zz"].is_nan()); + flat.extend(std::iter::empty()); + assert_eq!(flat.len(), tree.len() + 1); + } +} diff --git a/crates/fidc-core/src/pattern_context.rs b/crates/fidc-core/src/pattern_context.rs index 033adf6..558e4c1 100644 --- a/crates/fidc-core/src/pattern_context.rs +++ b/crates/fidc-core/src/pattern_context.rs @@ -325,7 +325,7 @@ mod tests { ][n][i]; market.push(DailyMarketSnapshot { date: *d, - symbol: s.to_string(), + symbol: (*s).into(), timestamp: None, day_open: c, open: c, @@ -348,7 +348,7 @@ mod tests { }); factors.push(DailyFactorSnapshot { date: *d, - symbol: s.to_string(), + symbol: (*s).into(), market_cap_bn: 1., free_float_cap_bn: 1., pe_ttm: 10., diff --git a/crates/fidc-core/src/platform_expr_strategy.rs b/crates/fidc-core/src/platform_expr_strategy.rs index 3b87c5a..44e1768 100644 --- a/crates/fidc-core/src/platform_expr_strategy.rs +++ b/crates/fidc-core/src/platform_expr_strategy.rs @@ -9201,7 +9201,7 @@ impl PlatformExprStrategy { let mut map = Map::new(); for snapshot in ctx.data.market_snapshot_rows_on(date) { if let Some(value) = Self::market_scope_value(snapshot, field) { - map.insert(snapshot.symbol.clone().into(), Dynamic::from(value)); + map.insert(snapshot.symbol.as_str().into(), Dynamic::from(value)); } } scope.push_dynamic(name.clone(), Dynamic::from(map)); @@ -10312,7 +10312,7 @@ impl PlatformExprStrategy { .factor(symbol_id) .expect("market-cap order references missing factor row"); EligibleUniverseSnapshot { - symbol: factor.symbol.clone(), + symbol: factor.symbol.to_string(), market_cap_bn: decision_market_cap_bn(factor), free_float_cap_bn: decision_free_float_cap_bn(factor), } @@ -10349,7 +10349,7 @@ impl PlatformExprStrategy { .config .universe_include .as_ref() - .is_some_and(|symbols| !symbols.contains(&factor.symbol)) + .is_some_and(|symbols| !symbols.contains(factor.symbol.as_str())) { continue; } @@ -10358,7 +10358,7 @@ impl PlatformExprStrategy { .config .candidate_symbols_by_date .get(&date) - .is_some_and(|symbols| symbols.contains(&factor.symbol)) + .is_some_and(|symbols| symbols.contains(factor.symbol.as_str())) { continue; } @@ -10919,7 +10919,7 @@ impl PlatformExprStrategy { .config .universe_include .as_ref() - .is_some_and(|symbols| !symbols.contains(&market.symbol)) + .is_some_and(|symbols| !symbols.contains(market.symbol.as_str())) { return Ok(Some("universe_not_included".to_string())); } @@ -11066,7 +11066,7 @@ impl PlatformExprStrategy { &stock, diagnostics, )? { - selected.push(factor.symbol.clone()); + selected.push(factor.symbol.to_string()); if selected.len() >= limit { break; } @@ -11210,7 +11210,7 @@ impl PlatformExprStrategy { )? { continue; } - selected.push(factor.symbol.clone()); + selected.push(factor.symbol.to_string()); if selected.len() >= limit { break; } @@ -11949,7 +11949,7 @@ impl PlatformExprStrategy { continue; } if quote_candidate_symbols.len() < quote_candidate_limit { - quote_candidate_symbols.push(factor.symbol.clone()); + quote_candidate_symbols.push(factor.symbol.to_string()); } if !ctx.is_lagged_execution() && let Some(reason) = self.stock_selection_limit_rejection_reason(&stock) @@ -11967,7 +11967,7 @@ impl PlatformExprStrategy { } continue; } - selected_symbols.push(factor.symbol.clone()); + selected_symbols.push(factor.symbol.to_string()); if selected_symbols.len() >= selection_limit && quote_candidate_symbols.len() >= quote_candidate_limit { @@ -12066,7 +12066,7 @@ impl PlatformExprStrategy { continue; } if quote_candidate_symbols.len() < quote_candidate_limit { - quote_candidate_symbols.push(symbol.clone()); + quote_candidate_symbols.push(symbol.to_string()); } if !ctx.is_lagged_execution() && let Some(reason) = self.stock_selection_limit_rejection_reason(stock) @@ -12084,7 +12084,7 @@ impl PlatformExprStrategy { } continue; } - selected_symbols.push(symbol.clone()); + selected_symbols.push(symbol.to_string()); if selected_symbols.len() >= selection_limit && quote_candidate_symbols.len() >= quote_candidate_limit { @@ -15031,7 +15031,7 @@ mod tests { .copied() .map(|date| DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: None, day_open: 10.0, open: 10.0, @@ -15058,14 +15058,14 @@ mod tests { .copied() .map(|date| DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 9.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), dates @@ -15073,7 +15073,7 @@ mod tests { .copied() .map(|date| CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -15285,7 +15285,7 @@ mod tests { let symbol = "300001.SZ"; let market = |date: NaiveDate, close: f64| DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: None, day_open: close, open: close, @@ -15308,18 +15308,18 @@ mod tests { }; let factor = |date: NaiveDate| DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 9.0, pe_ttm: 12.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: Some(1.0), - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }; let candidate = |date: NaiveDate| CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -15629,7 +15629,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date: execution_date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: None, day_open: 10.0, open: 10.0, @@ -15656,21 +15656,21 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date: execution_date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 9.0 + index as f64, pe_ttm: 12.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), active_symbols .iter() .map(|symbol| CandidateEligibility { date: execution_date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -16007,7 +16007,7 @@ mod tests { let date = d(2025, 1, 2); let market = DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: None, day_open: 10.0, open: 10.0, @@ -16074,7 +16074,7 @@ mod tests { let date = d(2025, 1, 2); let market = DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some(format!("{date} 15:00:00")), day_open: 10.0, open: 10.0, @@ -16137,7 +16137,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 15:00:00")), day_open: 12.0, open: 12.0, @@ -16160,18 +16160,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -16254,7 +16254,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 15:00:00")), day_open: 9.2, open: 9.2, @@ -16277,18 +16277,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 8.0, pe_ttm: 12.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -16362,7 +16362,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: None, day_open: 10.0, open: 10.0, @@ -16385,18 +16385,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 9.0, pe_ttm: 12.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -16529,7 +16529,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: None, day_open: 10.0, open: 10.0, @@ -16552,14 +16552,14 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 9.0, pe_ttm: 12.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], Vec::::new(), vec![BenchmarkSnapshot { @@ -16671,7 +16671,7 @@ mod tests { }; DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: None, day_open: last_price, open: last_price, @@ -16699,21 +16699,21 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 9.0 + index as f64, pe_ttm: 12.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect::>(); let candidate_rows = symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: *symbol == "000003.SZ", @@ -16879,7 +16879,7 @@ mod tests { }; DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: None, day_open: last_price, open: last_price, @@ -16907,21 +16907,21 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 9.0 + index as f64, pe_ttm: 12.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect::>(); let candidate_rows = symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: *symbol == "000003.SZ", @@ -17040,7 +17040,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: None, day_open: 10.0, open: 10.0, @@ -17063,18 +17063,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 9.0, pe_ttm: 12.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -17228,14 +17228,14 @@ mod tests { .into_iter() .map(|(symbol, market_cap_bn)| DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn, free_float_cap_bn: market_cap_bn / 2.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), Vec::new(), @@ -17368,7 +17368,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-05-19 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -17393,25 +17393,25 @@ mod tests { vec![ DailyFactorSnapshot { date, - symbol: missing_symbol.to_string(), + symbol: missing_symbol.into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: None, effective_turnover_ratio: None, adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date, - symbol: present_symbol.to_string(), + symbol: present_symbol.into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(0.0), effective_turnover_ratio: Some(0.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::from([ + extra_factors: From::from([ ("model_score".into(), 2.0), ("unused_factor".into(), 9.0), ]), @@ -17421,7 +17421,7 @@ mod tests { .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -17617,7 +17617,7 @@ mod tests { let market_rows = vec![ DailyMarketSnapshot { date: dates[0], - symbol: "000001.SH".to_string(), + symbol: "000001.SH".into(), timestamp: None, day_open: 10.0, open: 10.0, @@ -17640,7 +17640,7 @@ mod tests { }, DailyMarketSnapshot { date: dates[1], - symbol: "000001.SH".to_string(), + symbol: "000001.SH".into(), timestamp: None, day_open: 1_000.0, open: 1_000.0, @@ -17792,7 +17792,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2023-05-04 10:40:00".to_string()), day_open: 5.10, open: 5.10, @@ -17815,18 +17815,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -17935,7 +17935,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2023-05-04 10:40:00".to_string()), day_open: 5.10, open: 5.10, @@ -17958,18 +17958,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -18056,7 +18056,7 @@ mod tests { let symbol = "603176.SH"; let market = DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: None, day_open: 5.10, open: 5.10, @@ -18155,7 +18155,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2023-05-12 10:40:00".to_string()), day_open: 6.70, open: 6.70, @@ -18178,18 +18178,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -18302,7 +18302,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-06-23 09:33:00".to_string()), day_open: 11.50, open: 11.50, @@ -18325,18 +18325,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -18400,7 +18400,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-06-23 15:00:00".to_string()), day_open: 11.50, open: 11.50, @@ -18423,18 +18423,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -18516,7 +18516,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-02-07 10:18:00".to_string()), day_open: 23.11, open: 23.11, @@ -18539,18 +18539,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 24.90, free_float_cap_bn: 6.10, pe_ttm: 8.0, turnover_ratio: Some(35.77), effective_turnover_ratio: Some(35.77), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -18636,7 +18636,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-02-07 10:18:00".to_string()), day_open: 23.11, open: 23.11, @@ -18659,18 +18659,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 24.90, free_float_cap_bn: 6.10, pe_ttm: 8.0, turnover_ratio: Some(35.77), effective_turnover_ratio: Some(35.77), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -18754,7 +18754,7 @@ mod tests { vec![ DailyMarketSnapshot { date: first_date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-02-07 10:40:00".to_string()), day_open: 23.99, open: 23.99, @@ -18777,7 +18777,7 @@ mod tests { }, DailyMarketSnapshot { date: second_date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-02-10 10:31:00".to_string()), day_open: 23.20, open: 23.20, @@ -18802,31 +18802,31 @@ mod tests { vec![ DailyFactorSnapshot { date: first_date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 24.90, free_float_cap_bn: 6.10, pe_ttm: 8.0, turnover_ratio: Some(35.77), effective_turnover_ratio: Some(35.77), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: second_date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 24.20, free_float_cap_bn: 5.90, pe_ttm: 8.0, turnover_ratio: Some(20.0), effective_turnover_ratio: Some(20.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date: first_date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -18839,7 +18839,7 @@ mod tests { }, CandidateEligibility { date: second_date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -19019,7 +19019,7 @@ mod tests { vec![ DailyMarketSnapshot { date, - symbol: delayed_symbol.to_string(), + symbol: delayed_symbol.into(), timestamp: Some("2024-01-15 10:18:00".to_string()), day_open: 14.63, open: 14.63, @@ -19042,7 +19042,7 @@ mod tests { }, DailyMarketSnapshot { date, - symbol: other_symbol.to_string(), + symbol: other_symbol.into(), timestamp: Some("2024-01-15 10:18:00".to_string()), day_open: 8.00, open: 8.00, @@ -19065,7 +19065,7 @@ mod tests { }, DailyMarketSnapshot { date, - symbol: signal_symbol.to_string(), + symbol: signal_symbol.into(), timestamp: Some("2024-01-15 10:18:00".to_string()), day_open: 2900.0, open: 2900.0, @@ -19090,31 +19090,31 @@ mod tests { vec![ DailyFactorSnapshot { date, - symbol: delayed_symbol.to_string(), + symbol: delayed_symbol.into(), market_cap_bn: 24.0, free_float_cap_bn: 6.0, pe_ttm: 8.0, turnover_ratio: Some(20.0), effective_turnover_ratio: Some(20.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date, - symbol: other_symbol.to_string(), + symbol: other_symbol.into(), market_cap_bn: 23.0, free_float_cap_bn: 5.0, pe_ttm: 8.0, turnover_ratio: Some(20.0), effective_turnover_ratio: Some(20.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date, - symbol: delayed_symbol.to_string(), + symbol: delayed_symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -19127,7 +19127,7 @@ mod tests { }, CandidateEligibility { date, - symbol: other_symbol.to_string(), + symbol: other_symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -19320,7 +19320,7 @@ mod tests { vec![ DailyMarketSnapshot { date, - symbol: delayed_symbol.to_string(), + symbol: delayed_symbol.into(), timestamp: Some("2024-01-15 10:18:00".to_string()), day_open: 14.63, open: 14.63, @@ -19343,7 +19343,7 @@ mod tests { }, DailyMarketSnapshot { date, - symbol: other_symbol.to_string(), + symbol: other_symbol.into(), timestamp: Some("2024-01-15 10:18:00".to_string()), day_open: 8.00, open: 8.00, @@ -19366,7 +19366,7 @@ mod tests { }, DailyMarketSnapshot { date, - symbol: signal_symbol.to_string(), + symbol: signal_symbol.into(), timestamp: Some("2024-01-15 10:18:00".to_string()), day_open: 2900.0, open: 2900.0, @@ -19391,31 +19391,31 @@ mod tests { vec![ DailyFactorSnapshot { date, - symbol: delayed_symbol.to_string(), + symbol: delayed_symbol.into(), market_cap_bn: 24.0, free_float_cap_bn: 6.0, pe_ttm: 8.0, turnover_ratio: Some(20.0), effective_turnover_ratio: Some(20.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date, - symbol: other_symbol.to_string(), + symbol: other_symbol.into(), market_cap_bn: 23.0, free_float_cap_bn: 5.0, pe_ttm: 8.0, turnover_ratio: Some(20.0), effective_turnover_ratio: Some(20.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date, - symbol: delayed_symbol.to_string(), + symbol: delayed_symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -19428,7 +19428,7 @@ mod tests { }, CandidateEligibility { date, - symbol: other_symbol.to_string(), + symbol: other_symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -19582,7 +19582,7 @@ mod tests { vec![ DailyMarketSnapshot { date: first_date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2024-03-07 10:18:00".to_string()), day_open: 47.04, open: 47.04, @@ -19605,7 +19605,7 @@ mod tests { }, DailyMarketSnapshot { date: second_date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2024-03-08 09:31:00".to_string()), day_open: 47.41, open: 47.41, @@ -19630,31 +19630,31 @@ mod tests { vec![ DailyFactorSnapshot { date: first_date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 24.90, free_float_cap_bn: 6.10, pe_ttm: 8.0, turnover_ratio: Some(20.0), effective_turnover_ratio: Some(20.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: second_date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 24.20, free_float_cap_bn: 5.90, pe_ttm: 8.0, turnover_ratio: Some(20.0), effective_turnover_ratio: Some(20.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date: first_date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -19667,7 +19667,7 @@ mod tests { }, CandidateEligibility { date: second_date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -19832,7 +19832,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-03-14 10:18:00".to_string()), day_open: 5.96, open: 5.96, @@ -19855,18 +19855,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 3.2, free_float_cap_bn: 2.1, pe_ttm: 8.0, turnover_ratio: Some(3.0), effective_turnover_ratio: Some(3.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -19946,7 +19946,7 @@ mod tests { vec![ DailyMarketSnapshot { date: prev_date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-03-13 15:00:00".to_string()), day_open: 10.00, open: 10.00, @@ -19969,7 +19969,7 @@ mod tests { }, DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-03-14 10:18:00".to_string()), day_open: 9.30, open: 9.30, @@ -19995,19 +19995,19 @@ mod tests { .into_iter() .map(|factor_date| DailyFactorSnapshot { date: factor_date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 3.2, free_float_cap_bn: 2.1, pe_ttm: 8.0, turnover_ratio: Some(3.0), effective_turnover_ratio: Some(3.0), adjustment_factor_backward1: Some(1.0), - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -20139,7 +20139,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2022-12-22 15:00:00".to_string()), day_open: 5.28, open: 5.28, @@ -20165,18 +20165,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 3.2, free_float_cap_bn: 2.1, pe_ttm: 8.0, turnover_ratio: Some(3.0), effective_turnover_ratio: Some(3.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -20301,7 +20301,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: None, day_open: 9.30, open: 9.30, @@ -20324,18 +20324,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 3.2, free_float_cap_bn: 2.1, pe_ttm: 8.0, turnover_ratio: Some(3.0), effective_turnover_ratio: Some(3.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -20417,7 +20417,7 @@ mod tests { }; let market = DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-10-13 15:00:00".to_string()), day_open: 23.46, open: 23.46, @@ -20440,18 +20440,18 @@ mod tests { }; let factor = DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 8.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }; let candidate = CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -20619,7 +20619,7 @@ mod tests { }; let market = |date: NaiveDate, last_price: f64| DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 10:15:00")), day_open: last_price, open: last_price, @@ -20642,18 +20642,18 @@ mod tests { }; let factor = |date: NaiveDate| DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }; let candidate = |date: NaiveDate| CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -20786,7 +20786,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-03-14 10:18:00".to_string()), day_open: last_price, open: last_price, @@ -20809,18 +20809,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 3.2, free_float_cap_bn: 2.1, pe_ttm: 8.0, turnover_ratio: Some(3.0), effective_turnover_ratio: Some(3.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -20896,7 +20896,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-03-14 10:15:00".to_string()), day_open: last_price, open: last_price, @@ -20919,18 +20919,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 3.2, free_float_cap_bn: 2.1, pe_ttm: 8.0, turnover_ratio: Some(3.0), effective_turnover_ratio: Some(3.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -21003,7 +21003,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-03-14 10:18:00".to_string()), day_open: 14.82, open: 14.82, @@ -21026,18 +21026,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 8.0, free_float_cap_bn: 4.0, pe_ttm: 8.0, turnover_ratio: Some(3.0), effective_turnover_ratio: Some(3.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -21106,7 +21106,7 @@ mod tests { vec![ DailyMarketSnapshot { date: factor_date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-04-03 15:00:00".to_string()), day_open: 9.8, open: 9.8, @@ -21129,7 +21129,7 @@ mod tests { }, DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-04-07 10:18:00".to_string()), day_open: 19.0, open: 19.0, @@ -21154,30 +21154,30 @@ mod tests { vec![ DailyFactorSnapshot { date: factor_date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 8.0, free_float_cap_bn: 4.0, pe_ttm: 8.0, turnover_ratio: Some(1.2), effective_turnover_ratio: Some(1.2), adjustment_factor_backward1: None, - extra_factors: BTreeMap::from([("touched_upper_limit".into(), 1.0)]), + extra_factors: From::from([("touched_upper_limit".into(), 1.0)]), }, DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 9.0, free_float_cap_bn: 5.0, pe_ttm: 8.0, turnover_ratio: Some(2.4), effective_turnover_ratio: Some(2.4), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -21249,7 +21249,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-04-08 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -21272,18 +21272,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 18.0, free_float_cap_bn: 9.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::from([("touched_upper_limit".into(), 1.0)]), + extra_factors: From::from([("touched_upper_limit".into(), 1.0)]), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -21363,7 +21363,7 @@ mod tests { let normal_symbol = "301167.SZ"; let market = |symbol: &str, close: f64| DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 15:00:00")), day_open: close, open: close, @@ -21405,31 +21405,31 @@ mod tests { vec![ DailyFactorSnapshot { date, - symbol: st_symbol.to_string(), + symbol: st_symbol.into(), market_cap_bn: 1.0, free_float_cap_bn: 1.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date, - symbol: normal_symbol.to_string(), + symbol: normal_symbol.into(), market_cap_bn: 2.0, free_float_cap_bn: 2.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date, - symbol: st_symbol.to_string(), + symbol: st_symbol.into(), is_st: true, is_star_st: false, is_new_listing: false, @@ -21442,7 +21442,7 @@ mod tests { }, CandidateEligibility { date, - symbol: normal_symbol.to_string(), + symbol: normal_symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -21524,7 +21524,7 @@ mod tests { let normal_symbol = "301167.SZ"; let market = |symbol: &str, close: f64| DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 15:00:00")), day_open: close, open: close, @@ -21574,20 +21574,20 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 1.0 + index as f64, free_float_cap_bn: 1.0 + index as f64, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), vec![ CandidateEligibility { date, - symbol: star_st_symbol.to_string(), + symbol: star_st_symbol.into(), is_st: true, is_star_st: true, is_new_listing: false, @@ -21600,7 +21600,7 @@ mod tests { }, CandidateEligibility { date, - symbol: bjse_symbol.to_string(), + symbol: bjse_symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -21613,7 +21613,7 @@ mod tests { }, CandidateEligibility { date, - symbol: normal_symbol.to_string(), + symbol: normal_symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -21720,7 +21720,7 @@ mod tests { |date: NaiveDate, code: &str, open: f64, close: f64, upper: f64, lower: f64| { DailyMarketSnapshot { date, - symbol: code.to_string(), + symbol: code.into(), timestamp: Some(format!("{date} 15:00:00")), day_open: open, open, @@ -21763,18 +21763,18 @@ mod tests { ], vec![DailyFactorSnapshot { date: decision_date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 12.0, free_float_cap_bn: 8.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date: decision_date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -21875,7 +21875,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-04-08 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -21901,21 +21901,21 @@ mod tests { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: if *symbol == "003008.SZ" { 20.0 } else { 150.0 }, free_float_cap_bn: if *symbol == "003008.SZ" { 15.0 } else { 120.0 }, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -21988,7 +21988,7 @@ mod tests { let close = 10.0 + idx as f64 * 0.01; DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 10:40:00")), day_open: 10.0, open: 10.0, @@ -22015,14 +22015,14 @@ mod tests { .iter() .map(|row| DailyFactorSnapshot { date: row.date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 33.64, free_float_cap_bn: 33.64, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: Some(1.0), - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(); let benchmark_rows: Vec = market_rows @@ -22050,7 +22050,7 @@ mod tests { factor_rows, vec![CandidateEligibility { date: current, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -22120,7 +22120,7 @@ mod tests { }], vec![DailyMarketSnapshot { date: current, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{current} 10:18:00")), day_open: 10.0, open: 10.0, @@ -22143,18 +22143,18 @@ mod tests { }], vec![DailyFactorSnapshot { date: current, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 33.64, free_float_cap_bn: 33.64, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date: current, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -22231,7 +22231,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 10:40:00")), day_open: 10.0, open: 10.0, @@ -22254,18 +22254,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 20.0, free_float_cap_bn: 20.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -22369,7 +22369,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 10:18:00")), day_open: 10.0, open: 10.0, @@ -22392,18 +22392,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 20.0, free_float_cap_bn: 20.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -22484,7 +22484,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 10:18:00")), day_open: 10.0, open: 10.0, @@ -22507,18 +22507,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 20.0, free_float_cap_bn: 20.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -22616,7 +22616,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 10:18:00")), day_open: 10.0, open: 10.0, @@ -22639,18 +22639,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 20.0, free_float_cap_bn: 20.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -22727,7 +22727,7 @@ mod tests { let symbol = "300621.SZ"; let market = |date: NaiveDate, paused: bool| DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 10:18:00")), day_open: 10.0, open: 10.0, @@ -22750,7 +22750,7 @@ mod tests { }; let candidate = |date: NaiveDate, paused: bool| CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -22763,14 +22763,14 @@ mod tests { }; let factor = |date: NaiveDate| DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 20.0, free_float_cap_bn: 20.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }; let benchmark = |date: NaiveDate| BenchmarkSnapshot { date, @@ -22872,7 +22872,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some(format!("{date} 10:18:00")), day_open: 10.0, open: 10.0, @@ -22899,21 +22899,21 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 10.0 + index as f64, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -23035,7 +23035,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 10:18:00")), day_open: 11.0, open: 11.0, @@ -23058,18 +23058,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 20.0, free_float_cap_bn: 20.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -23192,7 +23192,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 10:18:00")), day_open: 10.8, open: 10.8, @@ -23215,18 +23215,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 20.0, free_float_cap_bn: 20.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -23349,7 +23349,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 10:18:00")), day_open: 11.0, open: 11.0, @@ -23372,18 +23372,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 20.0, free_float_cap_bn: 20.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -23510,7 +23510,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some(format!("{date} 10:18:00")), day_open: 10.0, open: 10.0, @@ -23537,21 +23537,21 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 10.0 + index as f64, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -23675,7 +23675,7 @@ mod tests { .iter() .map(|date| DailyMarketSnapshot { date: *date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 10:40:00")), day_open: 10.0, open: 10.0, @@ -23701,21 +23701,21 @@ mod tests { .iter() .map(|date| DailyFactorSnapshot { date: *date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 20.0, free_float_cap_bn: 20.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), [first_date, second_date] .iter() .map(|date| CandidateEligibility { date: *date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -23835,7 +23835,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2023-05-12 10:40:00".to_string()), day_open: 6.70, open: 6.70, @@ -23858,18 +23858,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -23981,7 +23981,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-04-29 10:15:00".to_string()), day_open: 10.0, open: 10.0, @@ -24008,21 +24008,21 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 10.0 + index as f64, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -24160,7 +24160,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-01-13 10:15:00".to_string()), day_open: 12.5, open: 12.5, @@ -24183,18 +24183,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 2.7567, free_float_cap_bn: 2.7567, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -24318,7 +24318,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2024-01-30 10:18:00".to_string()), day_open: 1.38, open: 1.38, @@ -24341,18 +24341,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 11.6, free_float_cap_bn: 11.6, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: true, is_star_st: false, is_new_listing: false, @@ -24439,7 +24439,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-01-06 10:40:00".to_string()), day_open: 10.0, open: 10.0, @@ -24462,18 +24462,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 8.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -24590,7 +24590,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-01-06 10:40:00".to_string()), day_open: 10.0, open: 10.0, @@ -24613,18 +24613,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 8.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -24689,7 +24689,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2023-05-08 10:40:00".to_string()), day_open: 5.86, open: 5.86, @@ -24712,18 +24712,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 20.0, free_float_cap_bn: 20.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -24818,7 +24818,7 @@ mod tests { |date: NaiveDate, symbol: &str, last_price: f64, upper_limit: f64, lower_limit: f64| { DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{} 09:33:00", date)), day_open: last_price, open: last_price, @@ -24882,69 +24882,69 @@ mod tests { vec![ DailyFactorSnapshot { date: factor_date, - symbol: limit_symbol.to_string(), + symbol: limit_symbol.into(), market_cap_bn: 1.0, free_float_cap_bn: 1.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::from([("amount".into(), 20_000_000.0)]), + extra_factors: From::from([("amount".into(), 20_000_000.0)]), }, DailyFactorSnapshot { date: factor_date, - symbol: fallback_symbol.to_string(), + symbol: fallback_symbol.into(), market_cap_bn: 2.0, free_float_cap_bn: 2.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::from([("amount".into(), 10_000_000.0)]), + extra_factors: From::from([("amount".into(), 10_000_000.0)]), }, DailyFactorSnapshot { date: decision_date, - symbol: limit_symbol.to_string(), + symbol: limit_symbol.into(), market_cap_bn: 1.0, free_float_cap_bn: 1.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::from([("amount".into(), 30_000_000.0)]), + extra_factors: From::from([("amount".into(), 30_000_000.0)]), }, DailyFactorSnapshot { date: decision_date, - symbol: fallback_symbol.to_string(), + symbol: fallback_symbol.into(), market_cap_bn: 2.0, free_float_cap_bn: 2.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: execution_date, - symbol: limit_symbol.to_string(), + symbol: limit_symbol.into(), market_cap_bn: 1.0, free_float_cap_bn: 1.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: execution_date, - symbol: fallback_symbol.to_string(), + symbol: fallback_symbol.into(), market_cap_bn: 2.0, free_float_cap_bn: 2.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], [decision_date, execution_date] @@ -24954,7 +24954,7 @@ mod tests { .into_iter() .map(move |symbol| CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -25120,7 +25120,7 @@ mod tests { let candidate_symbol = "600462.SH"; let market = |date: NaiveDate, symbol: &str, paused: bool| DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{} 09:33:00", date)), day_open: 10.0, open: 10.0, @@ -25143,7 +25143,7 @@ mod tests { }; let candidate = |date: NaiveDate, is_st: bool, is_paused: bool| CandidateEligibility { date, - symbol: candidate_symbol.to_string(), + symbol: candidate_symbol.into(), is_st, is_star_st: false, is_new_listing: false, @@ -25185,36 +25185,36 @@ mod tests { vec![ DailyFactorSnapshot { date: factor_date, - symbol: candidate_symbol.to_string(), + symbol: candidate_symbol.into(), market_cap_bn: 1.0, free_float_cap_bn: 1.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: decision_date, - symbol: candidate_symbol.to_string(), + symbol: candidate_symbol.into(), market_cap_bn: 1.0, free_float_cap_bn: 1.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: execution_date, - symbol: candidate_symbol.to_string(), + symbol: candidate_symbol.into(), market_cap_bn: 1.0, free_float_cap_bn: 1.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ @@ -25335,7 +25335,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-04-07 10:18:00".to_string()), day_open: 20.0, open: 20.0, @@ -25358,18 +25358,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 8.0, free_float_cap_bn: 4.0, pe_ttm: 8.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(2.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -25436,7 +25436,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-04-08 09:33:00".to_string()), day_open: 3.66, open: 3.66, @@ -25459,18 +25459,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 15.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(2.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -25539,7 +25539,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-04-08 10:18:00".to_string()), day_open: 20.0, open: 20.0, @@ -25562,18 +25562,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 15.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(2.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -25643,7 +25643,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-04-08 10:18:00".to_string()), day_open: 5.63, open: 5.63, @@ -25666,18 +25666,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 15.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(2.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -25744,7 +25744,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2024-12-31 09:33:00".to_string()), day_open: 8.0, open: 8.0, @@ -25767,18 +25767,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 12.0, free_float_cap_bn: 8.0, pe_ttm: 10.0, turnover_ratio: Some(0.0), effective_turnover_ratio: Some(0.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -26129,7 +26129,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -26152,18 +26152,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(22.0), effective_turnover_ratio: Some(18.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -26305,7 +26305,7 @@ mod tests { vec![ DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -26328,7 +26328,7 @@ mod tests { }, DailyMarketSnapshot { date, - symbol: "IF2501".to_string(), + symbol: "IF2501".into(), timestamp: Some("10:18:00".to_string()), day_open: 4000.0, open: 4000.0, @@ -26352,14 +26352,14 @@ mod tests { ], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(22.0), effective_turnover_ratio: Some(18.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::from([ + extra_factors: From::from([ ("custom_alpha".into(), 7.0), ("margin_all".into(), 1.0), ("yield_curve_1y".into(), 0.02), @@ -26375,7 +26375,7 @@ mod tests { }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -26513,7 +26513,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -26536,18 +26536,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(22.0), effective_turnover_ratio: Some(18.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -26658,7 +26658,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-02-03 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -26681,18 +26681,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(22.0), effective_turnover_ratio: Some(18.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -26782,7 +26782,7 @@ mod tests { vec![ DailyMarketSnapshot { date: decision_date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-02-03 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -26805,7 +26805,7 @@ mod tests { }, DailyMarketSnapshot { date: execution_date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-02-04 10:18:00".to_string()), day_open: 12.0, open: 12.0, @@ -26830,31 +26830,31 @@ mod tests { vec![ DailyFactorSnapshot { date: decision_date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: execution_date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date: decision_date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -26867,7 +26867,7 @@ mod tests { }, CandidateEligibility { date: execution_date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -26964,7 +26964,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-02-03 09:33:00".to_string()), day_open: 10.0, open: 10.0, @@ -26989,31 +26989,31 @@ mod tests { vec![ DailyFactorSnapshot { date, - symbol: "301001.SZ".to_string(), + symbol: "301001.SZ".into(), market_cap_bn: 8.0, free_float_cap_bn: 7.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date, - symbol: "301001.SZ".to_string(), + symbol: "301001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: true, @@ -27026,7 +27026,7 @@ mod tests { }, CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -27115,7 +27115,7 @@ mod tests { .enumerate() .map(|(index, date)| DailyMarketSnapshot { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: None, day_open: 10.0 + index as f64, open: 10.0 + index as f64, @@ -27142,21 +27142,21 @@ mod tests { .enumerate() .map(|(index, date)| DailyFactorSnapshot { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: Some(1.0), - extra_factors: BTreeMap::from([("Mixed_Factor".into(), index as f64 + 5.0)]), + extra_factors: From::from([("Mixed_Factor".into(), index as f64 + 5.0)]), }) .collect::>(); let candidate_rows = dates .iter() .map(|date| CandidateEligibility { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -27270,7 +27270,7 @@ mod tests { .enumerate() .map(|(index, date)| DailyMarketSnapshot { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: None, day_open: 10.0 + index as f64, open: 10.0 + index as f64, @@ -27296,21 +27296,21 @@ mod tests { .iter() .map(|date| DailyFactorSnapshot { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: Some(1.0), - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect::>(); let candidate_rows = dates .iter() .map(|date| CandidateEligibility { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -27422,7 +27422,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-02-03 09:33:00".to_string()), day_open: 10.0, open: 10.0, @@ -27449,21 +27449,21 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 10.0 + index as f64, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -27560,7 +27560,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-02-03 14:59:00".to_string()), day_open: 10.0, open: 10.0, @@ -27587,21 +27587,21 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -27696,7 +27696,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-02-03 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -27722,7 +27722,7 @@ mod tests { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: match *symbol { "000003.SZ" => 5.0, "000002.SZ" => 6.0, @@ -27733,14 +27733,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -27858,7 +27858,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-02-03 10:40:00".to_string()), day_open: 10.0, open: 10.0, @@ -27885,21 +27885,21 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -28018,7 +28018,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-02-03 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -28044,7 +28044,7 @@ mod tests { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: match *symbol { "000002.SZ" => 8.0, _ => 20.0, @@ -28054,14 +28054,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -28178,7 +28178,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-02-03 10:40:00".to_string()), day_open: 10.0, open: 10.0, @@ -28205,21 +28205,21 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 10.0 + index as f64, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -28351,7 +28351,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-02-03 10:40:00".to_string()), day_open: 10.0, open: 10.0, @@ -28378,21 +28378,21 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 10.0 + index as f64, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -28508,7 +28508,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-02-03 10:40:00".to_string()), day_open: 9.6, open: 9.6, @@ -28535,21 +28535,21 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 10.0 + index as f64, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -28682,7 +28682,7 @@ mod tests { .flat_map(|date| { symbols.iter().map(move |symbol| DailyMarketSnapshot { date: *date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some(format!("{date} 09:33:00")), day_open: 10.0, open: 10.0, @@ -28713,14 +28713,14 @@ mod tests { .enumerate() .map(move |(index, symbol)| DailyFactorSnapshot { date: *date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 10.0 + index as f64, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) }) .collect(), @@ -28729,7 +28729,7 @@ mod tests { .flat_map(|date| { symbols.iter().map(move |symbol| CandidateEligibility { date: *date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -28961,7 +28961,7 @@ mod tests { .flat_map(|date| { symbols.iter().map(move |symbol| DailyMarketSnapshot { date: *date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some(format!("{date} 09:33:00")), day_open: 10.0, open: 10.0, @@ -28992,14 +28992,14 @@ mod tests { .enumerate() .map(move |(index, symbol)| DailyFactorSnapshot { date: *date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 10.0 + index as f64, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) }) .collect(), @@ -29008,7 +29008,7 @@ mod tests { .flat_map(|date| { symbols.iter().map(move |symbol| CandidateEligibility { date: *date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -29130,7 +29130,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-02-26 09:33:00".to_string()), day_open: 10.0, open: 10.0, @@ -29157,21 +29157,21 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 10.0 + index as f64, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -29275,7 +29275,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-02-26 09:33:00".to_string()), day_open: 10.0, open: 10.0, @@ -29301,7 +29301,7 @@ mod tests { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: match *symbol { "000001.SZ" => 8.0, "000003.SZ" => 9.0, @@ -29312,14 +29312,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -29458,7 +29458,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-02-26 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -29484,7 +29484,7 @@ mod tests { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: match *symbol { "000003.SZ" => 8.0, "000002.SZ" => 9.0, @@ -29495,14 +29495,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -29635,7 +29635,7 @@ mod tests { .collect(), std::iter::once(DailyMarketSnapshot { date: prev_date, - symbol: take_profit.to_string(), + symbol: take_profit.into(), timestamp: Some("2025-04-29 15:00:00".to_string()), day_open: 8.0, open: 8.0, @@ -29658,7 +29658,7 @@ mod tests { }) .chain(symbols.iter().map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-04-30 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -29682,18 +29682,18 @@ mod tests { .collect(), std::iter::once(DailyFactorSnapshot { date: prev_date, - symbol: take_profit.to_string(), + symbol: take_profit.into(), market_cap_bn: 100.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: Some(1.0), - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .chain(symbols.iter().map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: match *symbol { s if s == buy_first => 1.0, s if s == buy_second => 2.0, @@ -29706,14 +29706,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: Some(1.0), - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), })) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -29918,7 +29918,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-05-14 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -29944,7 +29944,7 @@ mod tests { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: match *symbol { s if s == buy_first => 1.0, s if s == buy_second => 2.0, @@ -29957,14 +29957,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -30134,7 +30134,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-04-30 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -30160,7 +30160,7 @@ mod tests { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: match *symbol { s if s == buy_first => 1.0, s if s == buy_second => 2.0, @@ -30173,14 +30173,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -30339,7 +30339,7 @@ mod tests { let symbol = "600156.SH"; let market = |date, close, prev_close| DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{} 15:00:00", date)), day_open: close, open: close, @@ -30362,14 +30362,14 @@ mod tests { }; let factor = |date| DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 20.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: Some(1.0), - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }; let data = DataSet::from_components( vec![Instrument { @@ -30388,7 +30388,7 @@ mod tests { vec![factor(entry_date), factor(signal_date)], vec![CandidateEligibility { date: signal_date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -30508,7 +30508,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-02-26 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -30534,21 +30534,21 @@ mod tests { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 8.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -30682,7 +30682,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-02-26 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -30708,7 +30708,7 @@ mod tests { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: if *symbol == buy_symbol { 7.0 } else if *symbol == delayed_symbol { @@ -30721,14 +30721,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -30910,7 +30910,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-05-06 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -30936,7 +30936,7 @@ mod tests { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: if *symbol == buy_symbol { 7.0 } else if *symbol == delayed_symbol { @@ -30949,14 +30949,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -31142,7 +31142,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-05-20 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -31168,7 +31168,7 @@ mod tests { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: match *symbol { s if s == buy_first => 1.0, s if s == buy_second => 2.0, @@ -31182,14 +31182,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -31382,7 +31382,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-05-20 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -31408,7 +31408,7 @@ mod tests { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: match *symbol { s if s == buy_first => 1.0, s if s == buy_second => 2.0, @@ -31422,14 +31422,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -31599,7 +31599,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2026-04-01 09:33:00".to_string()), day_open: 10.0, open: 10.0, @@ -31625,7 +31625,7 @@ mod tests { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: match *symbol { "000003.SZ" => 8.0, "000002.SZ" => 9.0, @@ -31636,14 +31636,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -31753,7 +31753,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2026-04-01 09:33:00".to_string()), day_open: 10.0, open: 10.0, @@ -31779,7 +31779,7 @@ mod tests { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: match *symbol { "000001.SZ" => 8.0, "000003.SZ" => 9.0, @@ -31790,14 +31790,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -31918,7 +31918,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2026-04-01 09:33:00".to_string()), day_open: 10.0, open: 10.0, @@ -31944,7 +31944,7 @@ mod tests { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: match *symbol { "000003.SZ" => 8.0, "000002.SZ" => 9.0, @@ -31955,14 +31955,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -32073,7 +32073,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-05-14 09:33:00".to_string()), day_open: 10.0, open: 10.0, @@ -32100,7 +32100,7 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: if *symbol == "000003.SZ" { 50.0 } else { @@ -32111,14 +32111,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -32363,7 +32363,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-05-14 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -32389,7 +32389,7 @@ mod tests { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: match *symbol { "000001.SZ" => 8.0, "000003.SZ" => 9.0, @@ -32400,14 +32400,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -32573,7 +32573,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: symbol.clone(), + symbol: symbol.clone().into(), timestamp: Some("2025-05-14 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -32600,7 +32600,7 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: symbol.clone(), + symbol: symbol.clone().into(), market_cap_bn: if old_symbols.contains(symbol) { 100.0 + index as f64 } else { @@ -32611,14 +32611,14 @@ mod tests { turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: symbol.clone(), + symbol: symbol.clone().into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -32784,7 +32784,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-05-14 14:59:00".to_string()), day_open: 10.0, open: 10.0, @@ -32811,21 +32811,21 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -32937,7 +32937,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-05-14 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -32960,18 +32960,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -33160,7 +33160,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-05-14 09:33:00".to_string()), day_open: 10.0, open: 10.0, @@ -33183,18 +33183,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -33290,7 +33290,7 @@ mod tests { .into_iter() .map(|item| DailyMarketSnapshot { date, - symbol: item.to_string(), + symbol: item.into(), timestamp: Some("2025-05-14 14:59:00".to_string()), day_open: 10.0, open: 10.0, @@ -33316,21 +33316,21 @@ mod tests { .into_iter() .map(|item| DailyFactorSnapshot { date, - symbol: item.to_string(), + symbol: item.into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), [symbol, other_symbol] .into_iter() .map(|item| CandidateEligibility { date, - symbol: item.to_string(), + symbol: item.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -33431,7 +33431,7 @@ mod tests { .into_iter() .map(|item| DailyMarketSnapshot { date: decision_date, - symbol: item.to_string(), + symbol: item.into(), timestamp: Some("2025-05-14 14:59:00".to_string()), day_open: 10.0, open: 10.0, @@ -33457,21 +33457,21 @@ mod tests { .into_iter() .map(|item| DailyFactorSnapshot { date: decision_date, - symbol: item.to_string(), + symbol: item.into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), [symbol, other_symbol] .into_iter() .map(|item| CandidateEligibility { date: decision_date, - symbol: item.to_string(), + symbol: item.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -33576,7 +33576,7 @@ mod tests { }], vec![DailyMarketSnapshot { date: decision_date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-05-14 14:59:00".to_string()), day_open: 10.0, open: 10.0, @@ -33599,18 +33599,18 @@ mod tests { }], vec![DailyFactorSnapshot { date: decision_date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date: decision_date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -33692,7 +33692,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-03-19 09:31:00".to_string()), day_open: 18.82, open: 18.82, @@ -33715,18 +33715,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(0.0), effective_turnover_ratio: Some(0.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -33796,7 +33796,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2024-04-15 10:18:00".to_string()), day_open: 6.94, open: 6.94, @@ -33819,18 +33819,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 20.0, free_float_cap_bn: 20.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -33911,7 +33911,7 @@ mod tests { .flat_map(|date| { symbols.iter().map(move |symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-01-03 09:33:00".to_string()), day_open: 10.0, open: 10.0, @@ -33937,47 +33937,47 @@ mod tests { vec![ DailyFactorSnapshot { date: prev, - symbol: "300001.SZ".to_string(), + symbol: "300001.SZ".into(), market_cap_bn: 30.0, free_float_cap_bn: 30.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: prev, - symbol: "300002.SZ".to_string(), + symbol: "300002.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: curr, - symbol: "300001.SZ".to_string(), + symbol: "300001.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: curr, - symbol: "300002.SZ".to_string(), + symbol: "300002.SZ".into(), market_cap_bn: 30.0, free_float_cap_bn: 30.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], [prev, curr] @@ -33987,7 +33987,7 @@ mod tests { .into_iter() .map(move |symbol| CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -34089,7 +34089,7 @@ mod tests { .flat_map(|date| { symbols.iter().map(move |symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-01-03 09:33:00".to_string()), day_open: 10.0, open: 10.0, @@ -34115,47 +34115,47 @@ mod tests { vec![ DailyFactorSnapshot { date: prev, - symbol: "300001.SZ".to_string(), + symbol: "300001.SZ".into(), market_cap_bn: 30.0, free_float_cap_bn: 30.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: prev, - symbol: "300002.SZ".to_string(), + symbol: "300002.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: curr, - symbol: "300001.SZ".to_string(), + symbol: "300001.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: curr, - symbol: "300002.SZ".to_string(), + symbol: "300002.SZ".into(), market_cap_bn: 30.0, free_float_cap_bn: 30.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], [prev, curr] @@ -34165,7 +34165,7 @@ mod tests { .into_iter() .map(move |symbol| CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -34333,7 +34333,7 @@ mod tests { .into_iter() .map(|trade_date| DailyMarketSnapshot { date: trade_date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: None, day_open: 10.0, open: 10.0, @@ -34359,19 +34359,19 @@ mod tests { .into_iter() .map(|factor_date| DailyFactorSnapshot { date: factor_date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 20.0, free_float_cap_bn: 20.0, pe_ttm: 0.0, turnover_ratio: None, effective_turnover_ratio: None, adjustment_factor_backward1: Some(1.0), - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -34485,7 +34485,7 @@ mod tests { .into_iter() .map(|date| DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: None, day_open: 10.0, open: 10.0, @@ -34512,14 +34512,14 @@ mod tests { .map( |(date, current_close, current_volume)| DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 20.0, free_float_cap_bn: 20.0, pe_ttm: 0.0, turnover_ratio: None, effective_turnover_ratio: None, adjustment_factor_backward1: Some(1.0), - extra_factors: BTreeMap::from([ + extra_factors: From::from([ ("ma5_current_back_adjusted_close".into(), current_close), ("avg_volume5_current".into(), current_volume), ]), @@ -34540,7 +34540,7 @@ mod tests { factor_rows, vec![CandidateEligibility { date: decision_date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -34617,7 +34617,7 @@ mod tests { let date = start + chrono::Duration::days(idx); DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 10:15:00")), day_open: 10.0, open: 10.0, @@ -34664,18 +34664,18 @@ mod tests { market_rows, vec![DailyFactorSnapshot { date: current, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 20.0, free_float_cap_bn: 20.0, pe_ttm: 0.0, turnover_ratio: None, effective_turnover_ratio: None, adjustment_factor_backward1: None, - extra_factors: BTreeMap::from([("ma5_prev_close".into(), 10.0)]), + extra_factors: From::from([("ma5_prev_close".into(), 10.0)]), }], vec![CandidateEligibility { date: current, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -34757,7 +34757,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-02-03 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -34780,18 +34780,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 10.0, turnover_ratio: Some(1.2), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -34886,7 +34886,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-02-03 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -34909,18 +34909,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 10.0, turnover_ratio: Some(1.2), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -35034,7 +35034,7 @@ mod tests { vec![], vec![DailyMarketSnapshot { date, - symbol: "000001.SH".to_string(), + symbol: "000001.SH".into(), timestamp: Some("2025-02-03 10:18:00".to_string()), day_open: 1000.0, open: 1000.0, @@ -35157,7 +35157,7 @@ mod tests { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-02-03 09:30:00".to_string()), day_open: 10.0, open: 10.0, @@ -35184,21 +35184,21 @@ mod tests { .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 10.0 + index as f64, free_float_cap_bn: 10.0 + index as f64, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -35290,7 +35290,7 @@ mod tests { vec![], vec![DailyMarketSnapshot { date, - symbol: "000001.SH".to_string(), + symbol: "000001.SH".into(), timestamp: Some("2023-01-03 10:18:00".to_string()), day_open: 1000.0, open: 1000.0, @@ -35395,7 +35395,7 @@ mod tests { vec![ DailyMarketSnapshot { date: decision_date, - symbol: signal.to_string(), + symbol: signal.into(), timestamp: Some("2023-01-03 10:18:00".to_string()), day_open: 1000.0, open: 1000.0, @@ -35418,7 +35418,7 @@ mod tests { }, DailyMarketSnapshot { date: execution_date, - symbol: signal.to_string(), + symbol: signal.into(), timestamp: Some("2023-01-04 10:18:00".to_string()), day_open: 1002.0, open: 1002.0, @@ -35441,7 +35441,7 @@ mod tests { }, DailyMarketSnapshot { date: execution_date, - symbol: "000521.SZ".to_string(), + symbol: "000521.SZ".into(), timestamp: Some("2023-01-04 09:30:00".to_string()), day_open: 12.34, open: 12.31, @@ -35464,7 +35464,7 @@ mod tests { }, DailyMarketSnapshot { date: execution_date, - symbol: "000333.SZ".to_string(), + symbol: "000333.SZ".into(), timestamp: Some("2023-01-04 09:30:00".to_string()), day_open: 55.60, open: 55.50, @@ -35587,7 +35587,7 @@ mod tests { vec![], vec![DailyMarketSnapshot { date, - symbol: "000001.SH".to_string(), + symbol: "000001.SH".into(), timestamp: Some("2025-02-03 10:18:00".to_string()), day_open: 1000.0, open: 1000.0, @@ -35690,7 +35690,7 @@ mod tests { vec![], vec![DailyMarketSnapshot { date, - symbol: "000001.SH".to_string(), + symbol: "000001.SH".into(), timestamp: Some("2025-02-03 10:18:00".to_string()), day_open: 1000.0, open: 1000.0, @@ -35792,7 +35792,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("09:25:00".to_string()), day_open: 10.0, open: 10.0, @@ -35815,18 +35815,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(22.0), effective_turnover_ratio: Some(18.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -35937,7 +35937,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("09:25:00".to_string()), day_open: 10.0, open: 10.0, @@ -35960,18 +35960,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(22.0), effective_turnover_ratio: Some(18.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -36072,7 +36072,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -36095,18 +36095,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(22.0), effective_turnover_ratio: Some(18.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -36219,7 +36219,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -36242,18 +36242,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(22.0), effective_turnover_ratio: Some(18.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -36362,7 +36362,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -36385,18 +36385,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(22.0), effective_turnover_ratio: Some(18.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -36492,7 +36492,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -36515,18 +36515,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(22.0), effective_turnover_ratio: Some(18.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -36618,7 +36618,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -36641,18 +36641,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(22.0), effective_turnover_ratio: Some(18.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -36738,7 +36738,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -36761,18 +36761,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(22.0), effective_turnover_ratio: Some(18.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -37128,7 +37128,7 @@ let target_exposure = csi_ready ? dynamic_exposure : 0.0; .enumerate() .map(|(index, date)| DailyMarketSnapshot { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("10:18:00".to_string()), day_open: 10.0 + index as f64, open: 10.0 + index as f64, @@ -37154,21 +37154,21 @@ let target_exposure = csi_ready ? dynamic_exposure : 0.0; .iter() .map(|date| DailyFactorSnapshot { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(22.0), effective_turnover_ratio: Some(18.0), adjustment_factor_backward1: Some(1.0), - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), dates .iter() .map(|date| CandidateEligibility { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -37326,7 +37326,7 @@ let target_exposure = csi_ready ? dynamic_exposure : 0.0; let reference_price = if low_close { 4.0 } else { 10.0 }; DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-01-03 10:18:00".to_string()), day_open: if is_upper { 11.0 } else { reference_price }, open: if is_upper { 11.0 } else { reference_price }, @@ -37366,7 +37366,7 @@ let target_exposure = csi_ready ? dynamic_exposure : 0.0; .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: index as f64 + 1.0, free_float_cap_bn: index as f64 + 1.0, pe_ttm: 8.0, @@ -37374,9 +37374,9 @@ let target_exposure = csi_ready ? dynamic_exposure : 0.0; effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, extra_factors: if *symbol == "000002.SZ" { - BTreeMap::new() + BTreeMap::new().into() } else { - BTreeMap::from([("model_score".into(), 4.0 - index as f64)]) + BTreeMap::from([("model_score".into(), 4.0 - index as f64)]).into() }, }) .collect(), @@ -37384,7 +37384,7 @@ let target_exposure = csi_ready ? dynamic_exposure : 0.0; .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -37509,7 +37509,7 @@ let target_exposure = csi_ready ? dynamic_exposure : 0.0; let paused = *symbol == "000002.SZ"; DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2025-01-03 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -37537,14 +37537,14 @@ let target_exposure = csi_ready ? dynamic_exposure : 0.0; .enumerate() .map(|(index, symbol)| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: index as f64 + 1.0, free_float_cap_bn: index as f64 + 1.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect(), symbols @@ -37553,7 +37553,7 @@ let target_exposure = csi_ready ? dynamic_exposure : 0.0; let paused = *symbol == "000002.SZ"; CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -37755,7 +37755,7 @@ let target_exposure = csi_ready ? dynamic_exposure : 0.0; }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: None, day_open: 10.0, open: 10.0, @@ -37778,18 +37778,18 @@ let target_exposure = csi_ready ? dynamic_exposure : 0.0; }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 8.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::from([("reduce_signal".into(), 1.0)]), + extra_factors: From::from([("reduce_signal".into(), 1.0)]), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, diff --git a/crates/fidc-core/src/portfolio.rs b/crates/fidc-core/src/portfolio.rs index 2444a26..9f851f0 100644 --- a/crates/fidc-core/src/portfolio.rs +++ b/crates/fidc-core/src/portfolio.rs @@ -1641,7 +1641,7 @@ mod tests { vec![ DailyMarketSnapshot { date: prev_date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: None, day_open: 10.0, open: 10.0, @@ -1664,7 +1664,7 @@ mod tests { }, DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: None, day_open: 10.5, open: 10.5, @@ -1688,18 +1688,18 @@ mod tests { ], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -1754,7 +1754,7 @@ mod tests { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: None, day_open: 10.5, open: 10.5, @@ -1777,18 +1777,18 @@ mod tests { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -1840,7 +1840,7 @@ mod tests { }], vec![DailyMarketSnapshot { date: prev_date, - symbol: "601028.SH".to_string(), + symbol: "601028.SH".into(), timestamp: None, day_open: 10.2, open: 10.2, @@ -1923,7 +1923,7 @@ mod tests { vec![ DailyMarketSnapshot { date: buy_date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: None, day_open: 2.99, open: 2.99, @@ -1946,7 +1946,7 @@ mod tests { }, DailyMarketSnapshot { date: next_date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: None, day_open: 3.03, open: 3.03, diff --git a/crates/fidc-core/src/risk_control.rs b/crates/fidc-core/src/risk_control.rs index 0cbf474..bfc159e 100644 --- a/crates/fidc-core/src/risk_control.rs +++ b/crates/fidc-core/src/risk_control.rs @@ -869,7 +869,7 @@ mod tests { fn candidate(date: NaiveDate) -> CandidateEligibility { CandidateEligibility { date, - symbol: "002633.SZ".to_string(), + symbol: "002633.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -885,7 +885,7 @@ mod tests { fn market(date: NaiveDate, last_price: f64, lower_limit: f64) -> DailyMarketSnapshot { DailyMarketSnapshot { date, - symbol: "002633.SZ".to_string(), + symbol: "002633.SZ".into(), timestamp: Some(format!("{date} 10:18:00")), day_open: last_price, open: last_price, @@ -944,7 +944,7 @@ mod tests { let mut candidate=candidate(day); let mut snapshot=market(day,1.2,0.5); snapshot.lower_limit=0.01;snapshot.upper_limit=10.; - let instrument=Instrument{symbol:candidate.symbol.clone(),name:"fixture fund".into(),board:"ETF".into(),round_lot:100,listed_at:Some(d(2024,1,2)),delisted_at:None,status:"active".into()}; + let instrument=Instrument{symbol:candidate.symbol.to_string(),name:"fixture fund".into(),board:"ETF".into(),round_lot:100,listed_at:Some(d(2024,1,2)),delisted_at:None,status:"active".into()}; let config=FidcRiskControlConfig::default(); assert_eq!(ChinaAShareRiskControl::buy_rejection_reason_with_config(day,&candidate,&snapshot,Some(&instrument),0.9,&config),None); assert_eq!(ChinaAShareRiskControl::buy_rejection_reason_with_config(day,&candidate,&snapshot,Some(&instrument),0.,&config),Some("invalid execution price")); @@ -1047,7 +1047,7 @@ mod tests { config .static_rules .blacklisted_symbols - .insert(candidate.symbol.clone()); + .insert(candidate.symbol.to_string()); let selection_reason = ChinaAShareRiskControl::selection_rejection_reason_with_config( date, &candidate, &market, None, &config, @@ -1092,7 +1092,7 @@ mod tests { let mut candidate = candidate(date); let config = FidcRiskControlConfig::default(); for symbol in ["688001.SH", "689001.SH", "000001.SZ"] { - candidate.symbol = symbol.to_string(); + candidate.symbol = symbol.into(); for is_kcb in [false, true] { candidate.is_kcb = is_kcb; let reason = ChinaAShareRiskControl::buy_rejection_reason_with_config( @@ -1200,7 +1200,7 @@ mod tests { fn configurable_bjse_filter_can_be_disabled() { let date = d(2025, 1, 2); let mut candidate = candidate(date); - candidate.symbol = "430047.BJ".to_string(); + candidate.symbol = "430047.BJ".into(); candidate.allow_sell = true; let market = market(date, 6.27, 5.63); let default_selection = @@ -1232,7 +1232,7 @@ mod tests { fn concrete_kcb_reason_wins_over_generic_missing_risk_state() { let date = d(2025, 1, 2); let mut candidate = candidate(date); - candidate.symbol = "688506.SH".to_string(); + candidate.symbol = "688506.SH".into(); candidate.is_kcb = true; candidate.risk_level_code = Some("missing_risk_state".to_string()); let market = market(date, 6.27, 5.63); diff --git a/crates/fidc-core/src/strategy.rs b/crates/fidc-core/src/strategy.rs index 5a3e85e..7907eae 100644 --- a/crates/fidc-core/src/strategy.rs +++ b/crates/fidc-core/src/strategy.rs @@ -3184,7 +3184,7 @@ mod tests { .enumerate() .map(|(index, date)| DailyMarketSnapshot { date: *date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 10:18:00")), day_open: 10.0 + index as f64, open: 10.0 + index as f64, @@ -3210,21 +3210,21 @@ mod tests { .iter() .map(|date| DailyFactorSnapshot { date: *date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 10.0, free_float_cap_bn: 9.0, pe_ttm: 12.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect::>(); let candidate_rows = dates .iter() .map(|date| CandidateEligibility { date: *date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, diff --git a/crates/fidc-core/src/universe.rs b/crates/fidc-core/src/universe.rs index 13a0ed2..3550cbe 100644 --- a/crates/fidc-core/src/universe.rs +++ b/crates/fidc-core/src/universe.rs @@ -83,7 +83,7 @@ impl SelectionContext<'_> { for factor in self.data.factor_snapshot_rows_on(self.decision_date) { if self .dynamic_universe - .is_some_and(|symbols| !symbols.is_empty() && !symbols.contains(&factor.symbol)) + .is_some_and(|symbols| !symbols.is_empty() && !symbols.contains(factor.symbol.as_str())) { continue; } @@ -307,7 +307,7 @@ mod tests { fn market(symbol: &str, price: f64) -> DailyMarketSnapshot { DailyMarketSnapshot { date: d(), - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-01-02 10:00:00".to_string()), day_open: price, open: price, @@ -333,7 +333,7 @@ mod tests { fn factor(symbol: &str, market_cap_bn: f64) -> DailyFactorSnapshot { DailyFactorSnapshot { date: d(), - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn, free_float_cap_bn: market_cap_bn, pe_ttm: 10.0, @@ -347,7 +347,7 @@ mod tests { fn candidate(symbol: &str, is_st: bool, is_kcb: bool) -> CandidateEligibility { CandidateEligibility { date: d(), - symbol: symbol.to_string(), + symbol: symbol.into(), is_st, is_star_st: false, is_new_listing: false, diff --git a/crates/fidc-core/tests/core_rules.rs b/crates/fidc-core/tests/core_rules.rs index 0d7e08e..62ccf84 100644 --- a/crates/fidc-core/tests/core_rules.rs +++ b/crates/fidc-core/tests/core_rules.rs @@ -15,7 +15,7 @@ fn d(year: i32, month: u32, day: u32) -> NaiveDate { fn candidate() -> CandidateEligibility { CandidateEligibility { date: d(2024, 1, 3), - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -31,7 +31,7 @@ fn candidate() -> CandidateEligibility { fn snapshot(open: f64, upper_limit: f64, lower_limit: f64) -> DailyMarketSnapshot { DailyMarketSnapshot { date: d(2024, 1, 3), - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2024-01-03 10:18:00".to_string()), day_open: open, open, @@ -256,7 +256,7 @@ fn china_rule_hooks_allow_sell_when_last_price_is_above_lower_limit() { let snapshot = DailyMarketSnapshot { date: d(2024, 4, 7), - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2024-04-07 10:18:00".to_string()), day_open: 2.53, open: 2.53, diff --git a/crates/fidc-core/tests/corporate_actions.rs b/crates/fidc-core/tests/corporate_actions.rs index 0d5d37d..0c641f3 100644 --- a/crates/fidc-core/tests/corporate_actions.rs +++ b/crates/fidc-core/tests/corporate_actions.rs @@ -113,7 +113,7 @@ impl Strategy for BuyAndHoldStrategy { fn stock_market_snapshot(date: NaiveDate) -> DailyMarketSnapshot { DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some(format!("{date} 10:18:00")), day_open: 10.0, open: 10.0, @@ -139,21 +139,21 @@ fn stock_market_snapshot(date: NaiveDate) -> DailyMarketSnapshot { fn stock_factor_snapshot(date: NaiveDate) -> DailyFactorSnapshot { DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), } } fn stock_candidate(date: NaiveDate) -> CandidateEligibility { CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -195,7 +195,7 @@ fn engine_reinvests_dividend_receivable_in_round_lots() { vec![ DailyMarketSnapshot { date: buy_date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-01 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -218,7 +218,7 @@ fn engine_reinvests_dividend_receivable_in_round_lots() { }, DailyMarketSnapshot { date: ex_date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-02 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -241,7 +241,7 @@ fn engine_reinvests_dividend_receivable_in_round_lots() { }, DailyMarketSnapshot { date: payable_date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-03 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -266,42 +266,42 @@ fn engine_reinvests_dividend_receivable_in_round_lots() { vec![ DailyFactorSnapshot { date: buy_date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: ex_date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: payable_date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date: buy_date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -314,7 +314,7 @@ fn engine_reinvests_dividend_receivable_in_round_lots() { }, CandidateEligibility { date: ex_date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -327,7 +327,7 @@ fn engine_reinvests_dividend_receivable_in_round_lots() { }, CandidateEligibility { date: payable_date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, diff --git a/crates/fidc-core/tests/decision_quote_preload.rs b/crates/fidc-core/tests/decision_quote_preload.rs index 07802bf..12309db 100644 --- a/crates/fidc-core/tests/decision_quote_preload.rs +++ b/crates/fidc-core/tests/decision_quote_preload.rs @@ -105,7 +105,7 @@ fn single_day_quote_plan_data(date: NaiveDate) -> DataSet { fixture_instruments(), vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some(format!("{date} 15:00:00")), day_open: 10.0, open: 10.0, @@ -128,7 +128,7 @@ fn single_day_quote_plan_data(date: NaiveDate) -> DataSet { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 10.0, @@ -139,7 +139,7 @@ fn single_day_quote_plan_data(date: NaiveDate) -> DataSet { }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -269,7 +269,7 @@ fn engine_preloads_declared_decision_quotes_for_current_positions() { vec![ DailyMarketSnapshot { date: first, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2026-01-05 15:00:00".to_string()), day_open: 10.0, open: 10.0, @@ -292,7 +292,7 @@ fn engine_preloads_declared_decision_quotes_for_current_positions() { }, DailyMarketSnapshot { date: second, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2026-01-06 15:00:00".to_string()), day_open: 10.5, open: 10.5, @@ -317,7 +317,7 @@ fn engine_preloads_declared_decision_quotes_for_current_positions() { vec![ DailyFactorSnapshot { date: first, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 10.0, @@ -328,7 +328,7 @@ fn engine_preloads_declared_decision_quotes_for_current_positions() { }, DailyFactorSnapshot { date: second, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 10.0, @@ -341,7 +341,7 @@ fn engine_preloads_declared_decision_quotes_for_current_positions() { vec![ CandidateEligibility { date: first, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -354,7 +354,7 @@ fn engine_preloads_declared_decision_quotes_for_current_positions() { }, CandidateEligibility { date: second, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -439,7 +439,7 @@ fn engine_reuses_preloaded_decision_quotes_without_loader_call() { vec![ DailyMarketSnapshot { date: first, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2026-01-05 15:00:00".to_string()), day_open: 10.0, open: 10.0, @@ -462,7 +462,7 @@ fn engine_reuses_preloaded_decision_quotes_without_loader_call() { }, DailyMarketSnapshot { date: second, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2026-01-06 15:00:00".to_string()), day_open: 10.5, open: 10.5, @@ -487,7 +487,7 @@ fn engine_reuses_preloaded_decision_quotes_without_loader_call() { vec![ DailyFactorSnapshot { date: first, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 10.0, @@ -498,7 +498,7 @@ fn engine_reuses_preloaded_decision_quotes_without_loader_call() { }, DailyFactorSnapshot { date: second, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 10.0, @@ -511,7 +511,7 @@ fn engine_reuses_preloaded_decision_quotes_without_loader_call() { vec![ CandidateEligibility { date: first, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -524,7 +524,7 @@ fn engine_reuses_preloaded_decision_quotes_without_loader_call() { }, CandidateEligibility { date: second, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -674,7 +674,7 @@ fn engine_loads_distinct_decision_quote_times_on_same_day() { vec![ DailyMarketSnapshot { date: first, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2026-01-05 15:00:00".to_string()), day_open: 10.0, open: 10.0, @@ -697,7 +697,7 @@ fn engine_loads_distinct_decision_quote_times_on_same_day() { }, DailyMarketSnapshot { date: second, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2026-01-06 15:00:00".to_string()), day_open: 10.5, open: 10.5, @@ -722,7 +722,7 @@ fn engine_loads_distinct_decision_quote_times_on_same_day() { vec![ DailyFactorSnapshot { date: first, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 10.0, @@ -733,7 +733,7 @@ fn engine_loads_distinct_decision_quote_times_on_same_day() { }, DailyFactorSnapshot { date: second, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 10.0, pe_ttm: 10.0, @@ -746,7 +746,7 @@ fn engine_loads_distinct_decision_quote_times_on_same_day() { vec![ CandidateEligibility { date: first, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -759,7 +759,7 @@ fn engine_loads_distinct_decision_quote_times_on_same_day() { }, CandidateEligibility { date: second, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, diff --git a/crates/fidc-core/tests/delisting.rs b/crates/fidc-core/tests/delisting.rs index 55fcaf0..e452769 100644 --- a/crates/fidc-core/tests/delisting.rs +++ b/crates/fidc-core/tests/delisting.rs @@ -71,7 +71,7 @@ fn engine_keeps_unresolved_delisted_position_without_fabricating_a_fill() { vec![ DailyMarketSnapshot { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-02 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -94,7 +94,7 @@ fn engine_keeps_unresolved_delisted_position_without_fabricating_a_fill() { }, DailyMarketSnapshot { date: date1, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2025-01-02 10:18:00".to_string()), day_open: 5.0, open: 5.0, @@ -117,7 +117,7 @@ fn engine_keeps_unresolved_delisted_position_without_fabricating_a_fill() { }, DailyMarketSnapshot { date: delist_date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2025-01-03 10:18:00".to_string()), day_open: 5.05, open: 5.05, @@ -140,7 +140,7 @@ fn engine_keeps_unresolved_delisted_position_without_fabricating_a_fill() { }, DailyMarketSnapshot { date: date2, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2025-01-06 10:18:00".to_string()), day_open: 5.1, open: 5.1, @@ -165,53 +165,53 @@ fn engine_keeps_unresolved_delisted_position_without_fabricating_a_fill() { vec![ DailyFactorSnapshot { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: date1, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 30.0, free_float_cap_bn: 28.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: delist_date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 30.5, free_float_cap_bn: 28.5, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: date2, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 31.0, free_float_cap_bn: 29.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -224,7 +224,7 @@ fn engine_keeps_unresolved_delisted_position_without_fabricating_a_fill() { }, CandidateEligibility { date: date1, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -237,7 +237,7 @@ fn engine_keeps_unresolved_delisted_position_without_fabricating_a_fill() { }, CandidateEligibility { date: delist_date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -250,7 +250,7 @@ fn engine_keeps_unresolved_delisted_position_without_fabricating_a_fill() { }, CandidateEligibility { date: date2, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -364,7 +364,7 @@ fn engine_applies_successor_conversion_before_unresolved_delisting_audit() { vec![ DailyMarketSnapshot { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-02 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -387,7 +387,7 @@ fn engine_applies_successor_conversion_before_unresolved_delisting_audit() { }, DailyMarketSnapshot { date: date1, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2025-01-02 10:18:00".to_string()), day_open: 20.0, open: 20.0, @@ -410,7 +410,7 @@ fn engine_applies_successor_conversion_before_unresolved_delisting_audit() { }, DailyMarketSnapshot { date: date2, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2025-01-03 10:18:00".to_string()), day_open: 21.0, open: 21.0, @@ -435,42 +435,42 @@ fn engine_applies_successor_conversion_before_unresolved_delisting_audit() { vec![ DailyFactorSnapshot { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: date1, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 30.0, free_float_cap_bn: 28.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: date2, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 31.0, free_float_cap_bn: 29.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -483,7 +483,7 @@ fn engine_applies_successor_conversion_before_unresolved_delisting_audit() { }, CandidateEligibility { date: date1, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -496,7 +496,7 @@ fn engine_applies_successor_conversion_before_unresolved_delisting_audit() { }, CandidateEligibility { date: date2, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, diff --git a/crates/fidc-core/tests/engine_hooks.rs b/crates/fidc-core/tests/engine_hooks.rs index 5baf98e..7ffe2c5 100644 --- a/crates/fidc-core/tests/engine_hooks.rs +++ b/crates/fidc-core/tests/engine_hooks.rs @@ -49,7 +49,7 @@ fn single_day_anchor_data(date: NaiveDate) -> DataSet { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-02 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -72,18 +72,18 @@ fn single_day_anchor_data(date: NaiveDate) -> DataSet { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 100.0, free_float_cap_bn: 80.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -109,7 +109,7 @@ fn single_day_anchor_data(date: NaiveDate) -> DataSet { fn market_row(date: NaiveDate, symbol: &str, open: f64, close: f64) -> DailyMarketSnapshot { DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 10:18:00")), day_open: open, open, @@ -139,7 +139,7 @@ fn factor_row( ) -> DailyFactorSnapshot { DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 100.0, free_float_cap_bn: 80.0, pe_ttm: 10.0, @@ -153,7 +153,7 @@ fn factor_row( fn candidate_row(date: NaiveDate, symbol: &str) -> CandidateEligibility { CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -219,7 +219,7 @@ fn two_day_futures_data() -> DataSet { ("stock_connect_north_bound".into(), 1.0), ("industry_citics_l1".into(), 10.0), ("fundamental_net_profit".into(), 99.0), - ]), + ]).into(), ), factor_row( d2, @@ -232,7 +232,7 @@ fn two_day_futures_data() -> DataSet { ("stock_connect_north_bound".into(), 1.0), ("industry_citics_l1".into(), 10.0), ("fundamental_net_profit".into(), 101.0), - ]), + ]).into(), ), ], vec![ @@ -1094,7 +1094,7 @@ fn engine_runs_strategy_hooks_in_daily_order() { vec![ DailyMarketSnapshot { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-02 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -1117,7 +1117,7 @@ fn engine_runs_strategy_hooks_in_daily_order() { }, DailyMarketSnapshot { date: date2, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-03 10:18:00".to_string()), day_open: 10.1, open: 10.1, @@ -1142,31 +1142,31 @@ fn engine_runs_strategy_hooks_in_daily_order() { vec![ DailyFactorSnapshot { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: date2, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 21.0, free_float_cap_bn: 19.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -1179,7 +1179,7 @@ fn engine_runs_strategy_hooks_in_daily_order() { }, CandidateEligibility { date: date2, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -1337,7 +1337,7 @@ fn engine_executes_open_auction_decisions_before_on_day() { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-02 09:25:00".to_string()), day_open: 10.0, open: 10.0, @@ -1360,18 +1360,18 @@ fn engine_executes_open_auction_decisions_before_on_day() { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -1438,7 +1438,7 @@ fn engine_executes_futures_order_intents_against_future_account() { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-02 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -1461,18 +1461,18 @@ fn engine_executes_futures_order_intents_against_future_account() { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 100.0, free_float_cap_bn: 80.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -1935,7 +1935,7 @@ fn engine_rejects_futures_orders_when_trading_phase_is_closed() { }, ], vec![market_row(date, "000001.SZ", 10.0, 10.0), future_market], - vec![factor_row(date, "000001.SZ", BTreeMap::new())], + vec![factor_row(date, "000001.SZ", BTreeMap::new().into())], vec![candidate_row(date, "000001.SZ")], vec![benchmark_row(date)], Vec::new(), @@ -2011,7 +2011,7 @@ fn engine_sweeps_futures_order_book_depth_when_available() { market_row(date, "000001.SZ", 10.0, 10.0), market_row(date, "IF2501", 4000.0, 4000.0), ], - vec![factor_row(date, "000001.SZ", BTreeMap::new())], + vec![factor_row(date, "000001.SZ", BTreeMap::new().into())], vec![candidate_row(date, "000001.SZ")], vec![benchmark_row(date)], Vec::new(), @@ -2154,7 +2154,7 @@ fn engine_runs_minute_hooks_and_executes_minute_orders() { }).collect(), vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-02 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -2177,18 +2177,18 @@ fn engine_runs_minute_hooks_and_executes_minute_orders() { }, market_row(date, "000002.SZ", 20.0, 20.4)], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -2446,7 +2446,7 @@ fn strategy_context_exposes_engine_native_data_helpers() { .map( |(date, open, close, prev_close, volume)| DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some(format!("{date} 10:18:00")), day_open: open, open, @@ -2473,14 +2473,14 @@ fn strategy_context_exposes_engine_native_data_helpers() { .into_iter() .map(|date| DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect::>(); let candidates = [ @@ -2491,7 +2491,7 @@ fn strategy_context_exposes_engine_native_data_helpers() { .into_iter() .map(|(date, is_paused, is_st)| CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st, is_star_st: false, is_new_listing: false, @@ -2619,7 +2619,7 @@ fn strategy_context_exposes_final_order_runtime_view() { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-02 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -2642,18 +2642,18 @@ fn strategy_context_exposes_final_order_runtime_view() { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -2838,7 +2838,7 @@ fn engine_applies_account_cash_flow_and_financing_intents() { vec![ DailyMarketSnapshot { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-02 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -2861,7 +2861,7 @@ fn engine_applies_account_cash_flow_and_financing_intents() { }, DailyMarketSnapshot { date: date2, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-03 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -2886,31 +2886,31 @@ fn engine_applies_account_cash_flow_and_financing_intents() { vec![ DailyFactorSnapshot { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: date2, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -2923,7 +2923,7 @@ fn engine_applies_account_cash_flow_and_financing_intents() { }, CandidateEligibility { date: date2, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3035,7 +3035,7 @@ fn engine_expires_pending_day_limit_orders_at_market_close() { vec![ DailyMarketSnapshot { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-02 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -3058,7 +3058,7 @@ fn engine_expires_pending_day_limit_orders_at_market_close() { }, DailyMarketSnapshot { date: date2, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-03 10:18:00".to_string()), day_open: 9.7, open: 9.7, @@ -3083,31 +3083,31 @@ fn engine_expires_pending_day_limit_orders_at_market_close() { vec![ DailyFactorSnapshot { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: date2, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 21.0, free_float_cap_bn: 19.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3120,7 +3120,7 @@ fn engine_expires_pending_day_limit_orders_at_market_close() { }, CandidateEligibility { date: date2, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3211,7 +3211,7 @@ fn engine_runs_scheduled_rules_for_daily_weekly_and_monthly_triggers() { vec![ DailyMarketSnapshot { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-30 09:25:00".to_string()), day_open: 10.0, open: 10.0, @@ -3234,7 +3234,7 @@ fn engine_runs_scheduled_rules_for_daily_weekly_and_monthly_triggers() { }, DailyMarketSnapshot { date: date2, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-31 09:25:00".to_string()), day_open: 10.1, open: 10.1, @@ -3257,7 +3257,7 @@ fn engine_runs_scheduled_rules_for_daily_weekly_and_monthly_triggers() { }, DailyMarketSnapshot { date: date3, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-02-03 09:25:00".to_string()), day_open: 10.2, open: 10.2, @@ -3282,42 +3282,42 @@ fn engine_runs_scheduled_rules_for_daily_weekly_and_monthly_triggers() { vec![ DailyFactorSnapshot { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: date2, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 21.0, free_float_cap_bn: 19.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: date3, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 22.0, free_float_cap_bn: 20.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3330,7 +3330,7 @@ fn engine_runs_scheduled_rules_for_daily_weekly_and_monthly_triggers() { }, CandidateEligibility { date: date2, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3343,7 +3343,7 @@ fn engine_runs_scheduled_rules_for_daily_weekly_and_monthly_triggers() { }, CandidateEligibility { date: date3, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3469,7 +3469,7 @@ fn engine_dispatches_process_events_to_external_bus_listeners() { vec![ DailyMarketSnapshot { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-30 09:25:00".to_string()), day_open: 10.0, open: 10.0, @@ -3492,7 +3492,7 @@ fn engine_dispatches_process_events_to_external_bus_listeners() { }, DailyMarketSnapshot { date: date2, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-31 09:25:00".to_string()), day_open: 10.1, open: 10.1, @@ -3515,7 +3515,7 @@ fn engine_dispatches_process_events_to_external_bus_listeners() { }, DailyMarketSnapshot { date: date3, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-02-03 09:25:00".to_string()), day_open: 10.2, open: 10.2, @@ -3540,42 +3540,42 @@ fn engine_dispatches_process_events_to_external_bus_listeners() { vec![ DailyFactorSnapshot { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: date2, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 21.0, free_float_cap_bn: 19.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: date3, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 22.0, free_float_cap_bn: 20.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date: date1, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3588,7 +3588,7 @@ fn engine_dispatches_process_events_to_external_bus_listeners() { }, CandidateEligibility { date: date2, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3601,7 +3601,7 @@ fn engine_dispatches_process_events_to_external_bus_listeners() { }, CandidateEligibility { date: date3, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3855,7 +3855,7 @@ fn engine_applies_dynamic_universe_and_subscription_directives() { [ DailyMarketSnapshot { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some(format!("{date} 10:18:00")), day_open: 10.0, open: 10.0, @@ -3878,7 +3878,7 @@ fn engine_applies_dynamic_universe_and_subscription_directives() { }, DailyMarketSnapshot { date: *date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some(format!("{date} 10:18:00")), day_open: 20.0, open: 20.0, @@ -3908,25 +3908,25 @@ fn engine_applies_dynamic_universe_and_subscription_directives() { [ DailyFactorSnapshot { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 10.0, free_float_cap_bn: 8.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: *date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 12.0, free_float_cap_bn: 10.0, pe_ttm: 12.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ] }) @@ -3937,7 +3937,7 @@ fn engine_applies_dynamic_universe_and_subscription_directives() { [ CandidateEligibility { date: *date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3950,7 +3950,7 @@ fn engine_applies_dynamic_universe_and_subscription_directives() { }, CandidateEligibility { date: *date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -4041,7 +4041,7 @@ fn engine_exposes_current_process_context_to_strategies() { }], vec![DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2025-01-02 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -4064,18 +4064,18 @@ fn engine_exposes_current_process_context_to_strategies() { }], vec![DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -4191,8 +4191,8 @@ fn engine_rejects_an_unexplained_missing_holding_close() { market_row(date2, "000001.SZ", 20.0, 20.2), ], vec![ - factor_row(date1, "601028.SH", BTreeMap::new()), - factor_row(date2, "000001.SZ", BTreeMap::new()), + factor_row(date1, "601028.SH", BTreeMap::new().into()), + factor_row(date2, "000001.SZ", BTreeMap::new().into()), ], vec![ candidate_row(date1, "601028.SH"), @@ -4269,8 +4269,8 @@ fn platform_strategy_cannot_hide_missing_valuation_by_skipping_stop_take() { market_row(date2, "000001.SZ", 20.0, 20.2), ], vec![ - factor_row(date1, "601028.SH", BTreeMap::new()), - factor_row(date2, "000001.SZ", BTreeMap::new()), + factor_row(date1, "601028.SH", BTreeMap::new().into()), + factor_row(date2, "000001.SZ", BTreeMap::new().into()), ], vec![ candidate_row(date1, "601028.SH"), diff --git a/crates/fidc-core/tests/explicit_order_flow.rs b/crates/fidc-core/tests/explicit_order_flow.rs index 790294d..eaf4212 100644 --- a/crates/fidc-core/tests/explicit_order_flow.rs +++ b/crates/fidc-core/tests/explicit_order_flow.rs @@ -21,7 +21,7 @@ fn order_value_rounding_data(date: NaiveDate, symbol: &str, price: f64) -> DataS }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 09:33:00")), day_open: price, open: price, @@ -44,18 +44,18 @@ fn order_value_rounding_data(date: NaiveDate, symbol: &str, price: f64) -> DataS }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -91,7 +91,7 @@ fn intraday_liquidity_data(date: NaiveDate, symbol: &str) -> DataSet { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 10:19:00")), day_open: 10.0, open: 10.0, @@ -114,18 +114,18 @@ fn intraday_liquidity_data(date: NaiveDate, symbol: &str) -> DataSet { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -247,7 +247,7 @@ fn single_symbol_limit_price_data( }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some(format!("{date} 10:18:00")), day_open: price, open: price, @@ -270,18 +270,18 @@ fn single_symbol_limit_price_data( }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -319,7 +319,7 @@ fn broker_executes_explicit_order_value_buy() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -342,18 +342,18 @@ fn broker_executes_explicit_order_value_buy() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -473,7 +473,7 @@ fn broker_delayed_limit_open_sell_uses_minute_price() { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2025-06-27 09:31:00".to_string()), day_open: 12.55, open: 12.55, @@ -496,18 +496,18 @@ fn broker_delayed_limit_open_sell_uses_minute_price() { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -609,7 +609,7 @@ fn broker_executes_order_shares_and_order_lots() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -632,18 +632,18 @@ fn broker_executes_order_shares_and_order_lots() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -739,7 +739,7 @@ fn broker_executes_target_shares_like_order_to() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -762,18 +762,18 @@ fn broker_executes_target_shares_like_order_to() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -863,7 +863,7 @@ fn broker_executes_target_portfolio_smart_with_custom_prices() { vec![ DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -886,7 +886,7 @@ fn broker_executes_target_portfolio_smart_with_custom_prices() { }, DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -911,31 +911,31 @@ fn broker_executes_target_portfolio_smart_with_custom_prices() { vec![ DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 45.0, free_float_cap_bn: 40.0, pe_ttm: 14.0, turnover_ratio: Some(2.2), effective_turnover_ratio: Some(2.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -948,7 +948,7 @@ fn broker_executes_target_portfolio_smart_with_custom_prices() { }, CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -1049,7 +1049,7 @@ fn broker_executes_target_portfolio_smart_with_algo_order_style() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -1072,18 +1072,18 @@ fn broker_executes_target_portfolio_smart_with_algo_order_style() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 45.0, free_float_cap_bn: 40.0, pe_ttm: 14.0, turnover_ratio: Some(2.2), effective_turnover_ratio: Some(2.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -1194,7 +1194,7 @@ fn broker_executes_order_percent_and_target_percent() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -1217,18 +1217,18 @@ fn broker_executes_order_percent_and_target_percent() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -1321,7 +1321,7 @@ fn broker_uses_day_open_price_for_open_auction_matching() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 09:25:00".to_string()), day_open: 9.8, open: 10.0, @@ -1344,18 +1344,18 @@ fn broker_uses_day_open_price_for_open_auction_matching() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -1429,7 +1429,7 @@ fn broker_rejects_unproven_auction_capacity_in_a_daily_snapshot() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 09:25:00".to_string()), day_open: 9.8, open: 10.0, @@ -1452,18 +1452,18 @@ fn broker_rejects_unproven_auction_capacity_in_a_daily_snapshot() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -1533,7 +1533,7 @@ fn broker_cancels_buy_when_open_hits_upper_limit() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 09:30:00".to_string()), day_open: 11.0, open: 11.0, @@ -1556,18 +1556,18 @@ fn broker_cancels_buy_when_open_hits_upper_limit() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -1650,7 +1650,7 @@ fn broker_applies_price_ratio_slippage_on_snapshot_fills() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -1673,18 +1673,18 @@ fn broker_applies_price_ratio_slippage_on_snapshot_fills() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -1755,7 +1755,7 @@ fn broker_applies_explicit_historical_slippage_on_snapshot_fills() { }], [previous_date, date].into_iter().map(|day| DailyMarketSnapshot { date: day, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some(format!("{day} 15:00:00")), day_open: 10.0, open: 10.0, @@ -1778,18 +1778,18 @@ fn broker_applies_explicit_historical_slippage_on_snapshot_fills() { }).collect(), vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], [previous_date, date].into_iter().map(|day| CandidateEligibility { date: day, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -1866,7 +1866,7 @@ fn broker_applies_tick_size_slippage_on_intraday_last_fills() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -1889,18 +1889,18 @@ fn broker_applies_tick_size_slippage_on_intraday_last_fills() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -1988,7 +1988,7 @@ fn broker_rejects_intraday_last_order_without_execution_quotes() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -2011,18 +2011,18 @@ fn broker_rejects_intraday_last_order_without_execution_quotes() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -2099,7 +2099,7 @@ fn broker_executes_intraday_last_on_start_quote_with_trade_delta() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 09:33:00".to_string()), day_open: 15.0, open: 15.0, @@ -2122,18 +2122,18 @@ fn broker_executes_intraday_last_on_start_quote_with_trade_delta() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -2219,7 +2219,7 @@ fn broker_cancels_market_order_remainder_when_intraday_quote_liquidity_exhausted }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -2242,18 +2242,18 @@ fn broker_cancels_market_order_remainder_when_intraday_quote_liquidity_exhausted }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -2351,7 +2351,7 @@ fn broker_rejects_missing_execution_capacity_instead_of_declaring_suspension() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -2374,18 +2374,18 @@ fn broker_rejects_missing_execution_capacity_instead_of_declaring_suspension() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -2454,7 +2454,7 @@ fn broker_splits_intraday_quote_fills_and_tracks_commission_by_order() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -2477,18 +2477,18 @@ fn broker_splits_intraday_quote_fills_and_tracks_commission_by_order() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -2627,7 +2627,7 @@ fn broker_aggregates_intraday_quote_fills_into_vwap_leg() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -2650,18 +2650,18 @@ fn broker_aggregates_intraday_quote_fills_into_vwap_leg() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -2784,7 +2784,7 @@ fn broker_executes_algo_vwap_value_with_time_window() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -2807,18 +2807,18 @@ fn broker_executes_algo_vwap_value_with_time_window() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -2946,7 +2946,7 @@ fn broker_executes_algo_twap_percent_across_window_quotes() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 12.0, open: 12.0, @@ -2969,18 +2969,18 @@ fn broker_executes_algo_twap_percent_across_window_quotes() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3111,7 +3111,7 @@ fn broker_uses_best_own_price_for_intraday_matching() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -3134,18 +3134,18 @@ fn broker_uses_best_own_price_for_intraday_matching() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3230,7 +3230,7 @@ fn broker_uses_best_counterparty_price_for_intraday_matching() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -3253,18 +3253,18 @@ fn broker_uses_best_counterparty_price_for_intraday_matching() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3362,7 +3362,7 @@ fn rebalance_optimizer_skips_unfunded_buy_when_existing_position_cannot_sell() { vec![ DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -3385,7 +3385,7 @@ fn rebalance_optimizer_skips_unfunded_buy_when_existing_position_cannot_sell() { }, DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -3410,31 +3410,31 @@ fn rebalance_optimizer_skips_unfunded_buy_when_existing_position_cannot_sell() { vec![ DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 60.0, free_float_cap_bn: 50.0, pe_ttm: 18.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3447,7 +3447,7 @@ fn rebalance_optimizer_skips_unfunded_buy_when_existing_position_cannot_sell() { }, CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3558,7 +3558,7 @@ fn rebalance_uses_day_open_for_open_auction_valuation() { vec![ DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2024-01-10 09:25:00".to_string()), day_open: 20.0, open: 20.0, @@ -3581,7 +3581,7 @@ fn rebalance_uses_day_open_for_open_auction_valuation() { }, DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 09:25:00".to_string()), day_open: 10.0, open: 10.0, @@ -3606,31 +3606,31 @@ fn rebalance_uses_day_open_for_open_auction_valuation() { vec![ DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 20.0, free_float_cap_bn: 18.0, pe_ttm: 10.0, turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3643,7 +3643,7 @@ fn rebalance_uses_day_open_for_open_auction_valuation() { }, CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3747,7 +3747,7 @@ fn rebalance_optimizer_prioritizes_higher_target_weight_when_cash_is_tight() { vec![ DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -3770,7 +3770,7 @@ fn rebalance_optimizer_prioritizes_higher_target_weight_when_cash_is_tight() { }, DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -3795,31 +3795,31 @@ fn rebalance_optimizer_prioritizes_higher_target_weight_when_cash_is_tight() { vec![ DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 60.0, free_float_cap_bn: 50.0, pe_ttm: 18.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3832,7 +3832,7 @@ fn rebalance_optimizer_prioritizes_higher_target_weight_when_cash_is_tight() { }, CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -3932,7 +3932,7 @@ fn rebalance_optimizer_does_not_scale_targets_above_requested_weight() { vec![ DailyMarketSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 82.0, open: 82.0, @@ -3955,7 +3955,7 @@ fn rebalance_optimizer_does_not_scale_targets_above_requested_weight() { }, DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 82.0, open: 82.0, @@ -3980,31 +3980,31 @@ fn rebalance_optimizer_does_not_scale_targets_above_requested_weight() { vec![ DailyFactorSnapshot { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 60.0, free_float_cap_bn: 50.0, pe_ttm: 18.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date, - symbol: "000001.SZ".to_string(), + symbol: "000001.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -4017,7 +4017,7 @@ fn rebalance_optimizer_does_not_scale_targets_above_requested_weight() { }, CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -4096,7 +4096,7 @@ fn broker_uses_board_specific_min_quantity_and_step_size_for_buy_sizing() { }], vec![DailyMarketSnapshot { date, - symbol: "688001.SH".to_string(), + symbol: "688001.SH".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -4119,18 +4119,18 @@ fn broker_uses_board_specific_min_quantity_and_step_size_for_buy_sizing() { }], vec![DailyFactorSnapshot { date, - symbol: "688001.SH".to_string(), + symbol: "688001.SH".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 20.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "688001.SH".to_string(), + symbol: "688001.SH".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -4202,7 +4202,7 @@ fn broker_allows_bjse_quantities_above_minimum_without_round_lot_step() { }], vec![DailyMarketSnapshot { date, - symbol: "430001.BJ".to_string(), + symbol: "430001.BJ".into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -4225,18 +4225,18 @@ fn broker_allows_bjse_quantities_above_minimum_without_round_lot_step() { }], vec![DailyFactorSnapshot { date, - symbol: "430001.BJ".to_string(), + symbol: "430001.BJ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 20.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "430001.BJ".to_string(), + symbol: "430001.BJ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -4310,7 +4310,7 @@ fn broker_allows_full_odd_lot_sell_when_liquidating_position() { }], vec![DailyMarketSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -4333,18 +4333,18 @@ fn broker_allows_full_odd_lot_sell_when_liquidating_position() { }], vec![DailyFactorSnapshot { date, - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -4423,7 +4423,7 @@ fn same_day_sell_then_rebuy_is_rejected_by_default() { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -4449,21 +4449,21 @@ fn same_day_sell_then_rebuy_is_rejected_by_default() { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect::>(); let candidates = symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -4565,7 +4565,7 @@ fn same_day_sell_then_rebuy_can_be_allowed_by_policy() { .iter() .map(|symbol| DailyMarketSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), timestamp: Some("2024-01-10 10:18:00".to_string()), day_open: 10.0, open: 10.0, @@ -4591,21 +4591,21 @@ fn same_day_sell_then_rebuy_can_be_allowed_by_policy() { .iter() .map(|symbol| DailyFactorSnapshot { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }) .collect::>(); let candidates = symbols .iter() .map(|symbol| CandidateEligibility { date, - symbol: (*symbol).to_string(), + symbol: (*symbol).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -4799,7 +4799,7 @@ fn two_day_limit_order_data(day1_open: f64, day2_open: f64) -> DataSet { vec![ DailyMarketSnapshot { date: day1, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 09:30:00".to_string()), day_open: day1_open, open: day1_open, @@ -4822,7 +4822,7 @@ fn two_day_limit_order_data(day1_open: f64, day2_open: f64) -> DataSet { }, DailyMarketSnapshot { date: day2, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-11 09:30:00".to_string()), day_open: day2_open, open: day2_open, @@ -4847,31 +4847,31 @@ fn two_day_limit_order_data(day1_open: f64, day2_open: f64) -> DataSet { vec![ DailyFactorSnapshot { date: day1, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, DailyFactorSnapshot { date: day2, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }, ], vec![ CandidateEligibility { date: day1, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -4884,7 +4884,7 @@ fn two_day_limit_order_data(day1_open: f64, day2_open: f64) -> DataSet { }, CandidateEligibility { date: day2, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -6170,7 +6170,7 @@ fn broker_reserves_sellable_quantity_for_open_limit_sells() { }], vec![DailyMarketSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), timestamp: Some("2024-01-10 09:30:00".to_string()), day_open: 10.0, open: 10.0, @@ -6193,18 +6193,18 @@ fn broker_reserves_sellable_quantity_for_open_limit_sells() { }], vec![DailyFactorSnapshot { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), market_cap_bn: 50.0, free_float_cap_bn: 45.0, pe_ttm: 15.0, turnover_ratio: Some(2.0), effective_turnover_ratio: Some(1.8), adjustment_factor_backward1: None, - extra_factors: BTreeMap::new(), + extra_factors: Default::default(), }], vec![CandidateEligibility { date, - symbol: "000002.SZ".to_string(), + symbol: "000002.SZ".into(), is_st: false, is_star_st: false, is_new_listing: false, diff --git a/crates/fidc-core/tests/intraday_history_performance.rs b/crates/fidc-core/tests/intraday_history_performance.rs index f83179a..786a658 100644 --- a/crates/fidc-core/tests/intraday_history_performance.rs +++ b/crates/fidc-core/tests/intraday_history_performance.rs @@ -17,7 +17,7 @@ fn dataset(day_count: usize, bars_per_day: usize) -> (DataSet, Vec) { .iter() .map(|date| DailyMarketSnapshot { date: *date, - symbol: SYMBOL.to_string(), + symbol: SYMBOL.into(), timestamp: None, day_open: 10.0, open: 10.0, diff --git a/crates/fidc-core/tests/stock_pool_execution_contract.rs b/crates/fidc-core/tests/stock_pool_execution_contract.rs index a831790..e9ba489 100644 --- a/crates/fidc-core/tests/stock_pool_execution_contract.rs +++ b/crates/fidc-core/tests/stock_pool_execution_contract.rs @@ -66,7 +66,7 @@ fn data_with_fund_rules( }; market.push(DailyMarketSnapshot { date, - symbol: code(n), + symbol: code(n).into(), timestamp: None, day_open: price, open: price, @@ -89,7 +89,7 @@ fn data_with_fund_rules( }); candidates.push(CandidateEligibility { date, - symbol: code(n), + symbol: code(n).into(), is_st: false, is_star_st: false, is_new_listing: false, @@ -131,7 +131,7 @@ fn data_with_fund_rules( .flat_map(|date| { (1..=2).map(move |n| DailyFactorSnapshot { date, - symbol: code(n), + symbol: code(n).into(), market_cap_bn: 10., free_float_cap_bn: 10., pe_ttm: 10., @@ -143,7 +143,7 @@ fn data_with_fund_rules( }) .collect(); let quotes = market.iter().filter(|row| row.symbol != "000300.SH").map(|row| fidc_core::IntradayExecutionQuote { - date: row.date, symbol: row.symbol.clone(), timestamp: row.date.and_hms_opt(9, 30, 0).unwrap(), + date: row.date, symbol: row.symbol.to_string(), timestamp: row.date.and_hms_opt(9, 30, 0).unwrap(), last_price: row.open, bid1: row.open, ask1: row.open, bid1_volume: 0, ask1_volume: 0, volume_delta: row.volume, amount_delta: row.open * row.volume as f64, trading_phase: Some("synthetic_observation_fixture".into()), diff --git a/crates/fidc-core/tests/strategy_selection.rs b/crates/fidc-core/tests/strategy_selection.rs index 29b61cc..048a8fb 100644 --- a/crates/fidc-core/tests/strategy_selection.rs +++ b/crates/fidc-core/tests/strategy_selection.rs @@ -35,7 +35,7 @@ fn market( ) -> DailyMarketSnapshot { DailyMarketSnapshot { date: d(date), - symbol: symbol.to_string(), + symbol: symbol.into(), timestamp: None, day_open: open, open, @@ -66,7 +66,7 @@ fn factor( ) -> DailyFactorSnapshot { DailyFactorSnapshot { date: d(date), - symbol: symbol.to_string(), + symbol: symbol.into(), market_cap_bn, free_float_cap_bn, pe_ttm: 18.0, @@ -87,7 +87,7 @@ fn candidate( ) -> CandidateEligibility { CandidateEligibility { date: d(date), - symbol: symbol.to_string(), + symbol: symbol.into(), is_st: false, is_star_st: false, is_new_listing,