跳过干净因子映射重复规范化
This commit is contained in:
@@ -3311,6 +3311,16 @@ fn normalize_factor_snapshots(factors: Vec<DailyFactorSnapshot>) -> Vec<DailyFac
|
||||
factors
|
||||
.into_iter()
|
||||
.map(|mut snapshot| {
|
||||
let already_normalized = snapshot.extra_factors.iter().all(|(field, value)| {
|
||||
let trimmed = field.as_ref().trim().trim_matches('"').trim_matches('\'');
|
||||
!trimmed.is_empty()
|
||||
&& trimmed == field.as_ref()
|
||||
&& trimmed.bytes().all(|byte| !byte.is_ascii_uppercase())
|
||||
&& value.is_finite()
|
||||
});
|
||||
if already_normalized {
|
||||
return snapshot;
|
||||
}
|
||||
snapshot.extra_factors = snapshot
|
||||
.extra_factors
|
||||
.into_iter()
|
||||
@@ -3970,6 +3980,41 @@ mod tests {
|
||||
assert_eq!(factor_numeric_value(&snapshot, "CUSTOM_FACTOR"), Some(3.5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn factor_snapshot_normalization_moves_clean_maps_and_repairs_dirty_maps() {
|
||||
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(),
|
||||
market_cap_bn: 1.0,
|
||||
free_float_cap_bn: 1.0,
|
||||
pe_ttm: 1.0,
|
||||
turnover_ratio: None,
|
||||
effective_turnover_ratio: None,
|
||||
extra_factors: BTreeMap::from([(Cow::Borrowed("amount"), 10.0)]),
|
||||
}]);
|
||||
assert!(matches!(
|
||||
clean[0].extra_factors.keys().next(),
|
||||
Some(Cow::Borrowed("amount"))
|
||||
));
|
||||
|
||||
let dirty = normalize_factor_snapshots(vec![DailyFactorSnapshot {
|
||||
date,
|
||||
symbol: "000001.SZ".to_string(),
|
||||
market_cap_bn: 1.0,
|
||||
free_float_cap_bn: 1.0,
|
||||
pe_ttm: 1.0,
|
||||
turnover_ratio: None,
|
||||
effective_turnover_ratio: None,
|
||||
extra_factors: BTreeMap::from([
|
||||
(Cow::Owned(" CUSTOM_FACTOR ".to_string()), 2.0),
|
||||
(Cow::Borrowed("bad_nan"), f64::NAN),
|
||||
]),
|
||||
}]);
|
||||
assert_eq!(dirty[0].extra_factors.get("custom_factor"), Some(&2.0));
|
||||
assert!(!dirty[0].extra_factors.contains_key("bad_nan"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn symbol_price_series_test_constructor_sorts_unsorted_rows() {
|
||||
let series = SymbolPriceSeries::new(
|
||||
|
||||
Reference in New Issue
Block a user