perf(data): type adjustment factor snapshots

This commit is contained in:
boris
2026-09-07 17:53:36 +08:00
parent 9714c051c5
commit 04b45adf98
12 changed files with 371 additions and 52 deletions
+98 -28
View File
@@ -14,7 +14,7 @@ use crate::futures::FuturesTradingParameter;
use crate::instrument::Instrument;
use crate::risk_control::{ChinaAShareRiskControl, FidcRiskControlConfig};
const BACKWARD_ADJUSTMENT_FACTOR_FIELD: &str = "adjustment_factor_backward1";
pub(crate) const BACKWARD_ADJUSTMENT_FACTOR_FIELD: &str = "adjustment_factor_backward1";
mod date_format {
use chrono::NaiveDate;
@@ -96,6 +96,18 @@ pub enum DataSetError {
row_count: usize,
symbol_id_count: usize,
},
#[error("factor field {field} must use its typed column on {date} / {symbol}")]
ReservedTypedFactorInExtraMap {
date: NaiveDate,
symbol: String,
field: &'static str,
},
#[error("invalid backward adjustment factor {value} on {date} / {symbol}")]
InvalidBackwardAdjustmentFactor {
date: NaiveDate,
symbol: String,
value: f64,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -200,6 +212,8 @@ pub struct DailyFactorSnapshot {
pub turnover_ratio: Option<f64>,
pub effective_turnover_ratio: Option<f64>,
#[serde(default)]
pub adjustment_factor_backward1: Option<f64>,
#[serde(default)]
pub extra_factors: NumericFactorMap,
}
@@ -659,12 +673,7 @@ impl AdjustedCloseSeries {
let factor = factor_rows
.get(factor_index)
.filter(|snapshot| snapshot.date == *date)
.and_then(|snapshot| {
snapshot
.extra_factors
.get(BACKWARD_ADJUSTMENT_FACTOR_FIELD)
.copied()
})
.and_then(|snapshot| snapshot.adjustment_factor_backward1)
.filter(|factor| factor.is_finite() && *factor > 0.0);
let back_adjusted_close = factor
.filter(|_| close.is_finite() && *close > 0.0)
@@ -1602,7 +1611,7 @@ impl DataSet {
|row| row.symbol.as_str(),
)?;
sort_rows_by_symbol_if_needed(&mut bundle.market, |row| row.symbol.as_str());
bundle.factors = normalize_factor_snapshots(bundle.factors);
bundle.factors = normalize_factor_snapshots(bundle.factors)?;
sort_rows_by_symbol_if_needed(&mut bundle.factors, |row| row.symbol.as_str());
sort_rows_by_symbol_if_needed(&mut bundle.candidates, |row| row.symbol.as_str());
if !bundle.market.is_empty() {
@@ -1764,7 +1773,7 @@ impl DataSet {
} else {
let mut market_by_date = group_by_date(market, |item| item.date);
sort_groups_by_symbol(&mut market_by_date, |item| item.symbol.as_str());
let factors = normalize_factor_snapshots(factors);
let factors = normalize_factor_snapshots(factors)?;
let mut factor_by_date = group_by_date(factors, |item| item.date);
sort_groups_by_symbol(&mut factor_by_date, |item| item.symbol.as_str());
let mut candidate_by_date = group_by_date(candidates, |item| item.date);
@@ -4230,6 +4239,7 @@ fn factor_numeric_value(snapshot: &DailyFactorSnapshot, field: &str) -> Option<f
"pe_ttm" => Some(snapshot.pe_ttm),
"turnover_ratio" => snapshot.turnover_ratio,
"effective_turnover_ratio" => snapshot.effective_turnover_ratio,
BACKWARD_ADJUSTMENT_FACTOR_FIELD => snapshot.adjustment_factor_backward1,
"ths_market_value_stock" | "ths_market_value_stock_bn" => snapshot
.extra_factors
.get(field.as_ref())
@@ -4342,10 +4352,31 @@ fn normalized_field(field: &str) -> Cow<'_, str> {
}
}
fn normalize_factor_snapshots(factors: Vec<DailyFactorSnapshot>) -> Vec<DailyFactorSnapshot> {
fn normalize_factor_snapshots(
factors: Vec<DailyFactorSnapshot>,
) -> Result<Vec<DailyFactorSnapshot>, DataSetError> {
factors
.into_iter()
.map(|mut snapshot| {
if snapshot
.extra_factors
.contains_key(BACKWARD_ADJUSTMENT_FACTOR_FIELD)
{
return Err(DataSetError::ReservedTypedFactorInExtraMap {
date: snapshot.date,
symbol: snapshot.symbol,
field: BACKWARD_ADJUSTMENT_FACTOR_FIELD,
});
}
if let Some(value) = snapshot.adjustment_factor_backward1
&& (!value.is_finite() || value <= 0.0)
{
return Err(DataSetError::InvalidBackwardAdjustmentFactor {
date: snapshot.date,
symbol: snapshot.symbol,
value,
});
}
let already_normalized = snapshot.extra_factors.iter().all(|(field, value)| {
let trimmed = field.as_ref().trim().trim_matches('"').trim_matches('\'');
!trimmed.is_empty()
@@ -4354,7 +4385,7 @@ fn normalize_factor_snapshots(factors: Vec<DailyFactorSnapshot>) -> Vec<DailyFac
&& value.is_finite()
});
if already_normalized {
return snapshot;
return Ok(snapshot);
}
snapshot.extra_factors = snapshot
.extra_factors
@@ -4372,7 +4403,7 @@ fn normalize_factor_snapshots(factors: Vec<DailyFactorSnapshot>) -> Vec<DailyFac
}
})
.collect();
snapshot
Ok(snapshot)
})
.collect()
}
@@ -5304,6 +5335,7 @@ mod tests {
pe_ttm: 0.0,
turnover_ratio: Some(0.02),
effective_turnover_ratio: Some(0.01),
adjustment_factor_backward1: None,
extra_factors: NumericFactorMap::from([(Cow::Borrowed("quality"), close)]),
};
let candidate_row = CandidateEligibility {
@@ -5487,6 +5519,7 @@ mod tests {
pe_ttm: 0.0,
turnover_ratio: None,
effective_turnover_ratio: None,
adjustment_factor_backward1: None,
extra_factors: NumericFactorMap::new(),
};
let candidate = |symbol: &str| CandidateEligibility {
@@ -5720,10 +5753,8 @@ mod tests {
pe_ttm: 10.0,
turnover_ratio: None,
effective_turnover_ratio: None,
extra_factors: NumericFactorMap::from([(
Cow::Borrowed(BACKWARD_ADJUSTMENT_FACTOR_FIELD),
1.0,
)]),
adjustment_factor_backward1: Some(1.0),
extra_factors: NumericFactorMap::new(),
})
.collect(),
Vec::new(),
@@ -5935,6 +5966,7 @@ mod tests {
pe_ttm: 10.0,
turnover_ratio: None,
effective_turnover_ratio: None,
adjustment_factor_backward1: None,
extra_factors: NumericFactorMap::new(),
})
.collect::<Vec<_>>();
@@ -6240,11 +6272,16 @@ mod tests {
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)]),
};
assert_eq!(factor_numeric_value(&snapshot, " MARKET_CAP "), Some(12.5));
assert_eq!(factor_numeric_value(&snapshot, "CUSTOM_FACTOR"), Some(3.5));
assert_eq!(
factor_numeric_value(&snapshot, "ADJUSTMENT_FACTOR_BACKWARD1"),
Some(1.25)
);
}
#[test]
@@ -6258,8 +6295,10 @@ mod tests {
pe_ttm: 1.0,
turnover_ratio: None,
effective_turnover_ratio: None,
adjustment_factor_backward1: None,
extra_factors: BTreeMap::from([(Cow::Borrowed("amount"), 10.0)]),
}]);
}])
.expect("normalize clean factor snapshot");
assert!(matches!(
clean[0].extra_factors.keys().next(),
Some(Cow::Borrowed("amount"))
@@ -6273,15 +6312,45 @@ mod tests {
pe_ttm: 1.0,
turnover_ratio: None,
effective_turnover_ratio: None,
adjustment_factor_backward1: None,
extra_factors: BTreeMap::from([
(Cow::Owned(" CUSTOM_FACTOR ".to_string()), 2.0),
(Cow::Borrowed("bad_nan"), f64::NAN),
]),
}]);
}])
.expect("normalize dirty factor snapshot");
assert_eq!(dirty[0].extra_factors.get("custom_factor"), Some(&2.0));
assert!(!dirty[0].extra_factors.contains_key("bad_nan"));
}
#[test]
fn factor_snapshot_rejects_legacy_or_invalid_adjustment_storage() {
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(),
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,
extra_factors,
};
assert!(matches!(
normalize_factor_snapshots(vec![snapshot(
Some(1.0),
BTreeMap::from([(Cow::Borrowed(BACKWARD_ADJUSTMENT_FACTOR_FIELD), 1.0)]),
)]),
Err(DataSetError::ReservedTypedFactorInExtraMap { .. })
));
assert!(matches!(
normalize_factor_snapshots(vec![snapshot(Some(0.0), BTreeMap::new())]),
Err(DataSetError::InvalidBackwardAdjustmentFactor { .. })
));
}
#[test]
fn symbol_price_series_test_constructor_sorts_unsorted_rows() {
let series = SymbolPriceSeries::new(
@@ -6374,6 +6443,7 @@ mod tests {
pe_ttm: 10.0,
turnover_ratio: None,
effective_turnover_ratio: None,
adjustment_factor_backward1: None,
extra_factors,
}
})
@@ -6432,10 +6502,8 @@ mod tests {
pe_ttm: 10.0,
turnover_ratio: None,
effective_turnover_ratio: None,
extra_factors: BTreeMap::from([(
Cow::Borrowed(BACKWARD_ADJUSTMENT_FACTOR_FIELD),
1.0,
)]),
adjustment_factor_backward1: Some(1.0),
extra_factors: BTreeMap::new(),
})
.collect(),
Vec::new(),
@@ -6728,7 +6796,8 @@ mod tests {
pe_ttm: 10.0,
turnover_ratio: None,
effective_turnover_ratio: None,
extra_factors: BTreeMap::from([("adjustment_factor_backward1".into(), factor)]),
adjustment_factor_backward1: Some(factor),
extra_factors: BTreeMap::new(),
})
.collect(),
Vec::new(),
@@ -6825,11 +6894,8 @@ mod tests {
pe_ttm: 10.0,
turnover_ratio: None,
effective_turnover_ratio: None,
extra_factors: if *date == dates[3] {
BTreeMap::new()
} else {
BTreeMap::from([("adjustment_factor_backward1".into(), 1.0)])
},
adjustment_factor_backward1: (*date != dates[3]).then_some(1.0),
extra_factors: BTreeMap::new(),
})
.collect(),
Vec::new(),
@@ -6931,6 +6997,7 @@ mod tests {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
};
let candidate = |symbol: &str| CandidateEligibility {
@@ -7029,6 +7096,7 @@ mod tests {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
Vec::new(),
@@ -7113,6 +7181,7 @@ mod tests {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -7164,6 +7233,7 @@ mod tests {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
};
+1
View File
@@ -5354,6 +5354,7 @@ mod tests {
pe_ttm: 12.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}
}
File diff suppressed because it is too large Load Diff
+2
View File
@@ -1648,6 +1648,7 @@ mod tests {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -1736,6 +1737,7 @@ mod tests {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
+1
View File
@@ -3154,6 +3154,7 @@ mod tests {
pe_ttm: 12.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
})
.collect::<Vec<_>>();
+1
View File
@@ -339,6 +339,7 @@ mod tests {
pe_ttm: 10.0,
turnover_ratio: Some(0.01),
effective_turnover_ratio: Some(0.01),
adjustment_factor_backward1: None,
extra_factors: Default::default(),
}
}
@@ -144,6 +144,7 @@ fn stock_factor_snapshot(date: NaiveDate) -> DailyFactorSnapshot {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}
}
@@ -270,6 +271,7 @@ fn engine_reinvests_dividend_receivable_in_round_lots() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -280,6 +282,7 @@ fn engine_reinvests_dividend_receivable_in_round_lots() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -290,6 +293,7 @@ fn engine_reinvests_dividend_receivable_in_round_lots() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
],
@@ -122,6 +122,7 @@ fn single_day_quote_plan_data(date: NaiveDate) -> DataSet {
pe_ttm: 10.0,
turnover_ratio: None,
effective_turnover_ratio: None,
adjustment_factor_backward1: None,
extra_factors: Default::default(),
}],
vec![CandidateEligibility {
@@ -310,6 +311,7 @@ fn engine_preloads_declared_decision_quotes_for_current_positions() {
pe_ttm: 10.0,
turnover_ratio: None,
effective_turnover_ratio: None,
adjustment_factor_backward1: None,
extra_factors: Default::default(),
},
DailyFactorSnapshot {
@@ -320,6 +322,7 @@ fn engine_preloads_declared_decision_quotes_for_current_positions() {
pe_ttm: 10.0,
turnover_ratio: None,
effective_turnover_ratio: None,
adjustment_factor_backward1: None,
extra_factors: Default::default(),
},
],
@@ -478,6 +481,7 @@ fn engine_reuses_preloaded_decision_quotes_without_loader_call() {
pe_ttm: 10.0,
turnover_ratio: None,
effective_turnover_ratio: None,
adjustment_factor_backward1: None,
extra_factors: Default::default(),
},
DailyFactorSnapshot {
@@ -488,6 +492,7 @@ fn engine_reuses_preloaded_decision_quotes_without_loader_call() {
pe_ttm: 10.0,
turnover_ratio: None,
effective_turnover_ratio: None,
adjustment_factor_backward1: None,
extra_factors: Default::default(),
},
],
@@ -711,6 +716,7 @@ fn engine_loads_distinct_decision_quote_times_on_same_day() {
pe_ttm: 10.0,
turnover_ratio: None,
effective_turnover_ratio: None,
adjustment_factor_backward1: None,
extra_factors: Default::default(),
},
DailyFactorSnapshot {
@@ -721,6 +727,7 @@ fn engine_loads_distinct_decision_quote_times_on_same_day() {
pe_ttm: 10.0,
turnover_ratio: None,
effective_turnover_ratio: None,
adjustment_factor_backward1: None,
extra_factors: Default::default(),
},
],
+7
View File
@@ -170,6 +170,7 @@ fn engine_keeps_unresolved_delisted_position_without_fabricating_a_fill() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -180,6 +181,7 @@ fn engine_keeps_unresolved_delisted_position_without_fabricating_a_fill() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -190,6 +192,7 @@ fn engine_keeps_unresolved_delisted_position_without_fabricating_a_fill() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -200,6 +203,7 @@ fn engine_keeps_unresolved_delisted_position_without_fabricating_a_fill() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
],
@@ -436,6 +440,7 @@ fn engine_applies_successor_conversion_before_unresolved_delisting_audit() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -446,6 +451,7 @@ fn engine_applies_successor_conversion_before_unresolved_delisting_audit() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -456,6 +462,7 @@ fn engine_applies_successor_conversion_before_unresolved_delisting_audit() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
],
+22
View File
@@ -78,6 +78,7 @@ fn single_day_anchor_data(date: NaiveDate) -> DataSet {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -144,6 +145,7 @@ fn factor_row(
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors,
}
}
@@ -1137,6 +1139,7 @@ fn engine_runs_strategy_hooks_in_daily_order() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -1147,6 +1150,7 @@ fn engine_runs_strategy_hooks_in_daily_order() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
],
@@ -1353,6 +1357,7 @@ fn engine_executes_open_auction_decisions_before_on_day() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -1453,6 +1458,7 @@ fn engine_executes_futures_order_intents_against_future_account() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -2168,6 +2174,7 @@ fn engine_runs_minute_hooks_and_executes_minute_orders() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -2463,6 +2470,7 @@ fn strategy_context_exposes_engine_native_data_helpers() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
})
.collect::<Vec<_>>();
@@ -2631,6 +2639,7 @@ fn strategy_context_exposes_final_order_runtime_view() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -2874,6 +2883,7 @@ fn engine_applies_account_cash_flow_and_financing_intents() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -2884,6 +2894,7 @@ fn engine_applies_account_cash_flow_and_financing_intents() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
],
@@ -3069,6 +3080,7 @@ fn engine_expires_pending_day_limit_orders_at_market_close() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -3079,6 +3091,7 @@ fn engine_expires_pending_day_limit_orders_at_market_close() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
],
@@ -3266,6 +3279,7 @@ fn engine_runs_scheduled_rules_for_daily_weekly_and_monthly_triggers() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -3276,6 +3290,7 @@ fn engine_runs_scheduled_rules_for_daily_weekly_and_monthly_triggers() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -3286,6 +3301,7 @@ fn engine_runs_scheduled_rules_for_daily_weekly_and_monthly_triggers() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
],
@@ -3521,6 +3537,7 @@ fn engine_dispatches_process_events_to_external_bus_listeners() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -3531,6 +3548,7 @@ fn engine_dispatches_process_events_to_external_bus_listeners() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -3541,6 +3559,7 @@ fn engine_dispatches_process_events_to_external_bus_listeners() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
],
@@ -3886,6 +3905,7 @@ fn engine_applies_dynamic_universe_and_subscription_directives() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -3896,6 +3916,7 @@ fn engine_applies_dynamic_universe_and_subscription_directives() {
pe_ttm: 12.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
]
@@ -4040,6 +4061,7 @@ fn engine_exposes_current_process_context_to_strategies() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -50,6 +50,7 @@ fn order_value_rounding_data(date: NaiveDate, symbol: &str, price: f64) -> DataS
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -119,6 +120,7 @@ fn intraday_liquidity_data(date: NaiveDate, symbol: &str) -> DataSet {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -272,6 +274,7 @@ fn single_symbol_limit_price_data(
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -343,6 +346,7 @@ fn broker_executes_explicit_order_value_buy() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -495,6 +499,7 @@ fn broker_delayed_limit_open_sell_uses_minute_price() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -629,6 +634,7 @@ fn broker_executes_order_shares_and_order_lots() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -757,6 +763,7 @@ fn broker_executes_target_shares_like_order_to() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -904,6 +911,7 @@ fn broker_executes_target_portfolio_smart_with_custom_prices() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -914,6 +922,7 @@ fn broker_executes_target_portfolio_smart_with_custom_prices() {
pe_ttm: 14.0,
turnover_ratio: Some(2.2),
effective_turnover_ratio: Some(2.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
],
@@ -1062,6 +1071,7 @@ fn broker_executes_target_portfolio_smart_with_algo_order_style() {
pe_ttm: 14.0,
turnover_ratio: Some(2.2),
effective_turnover_ratio: Some(2.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -1205,6 +1215,7 @@ fn broker_executes_order_percent_and_target_percent() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -1329,6 +1340,7 @@ fn broker_uses_day_open_price_for_open_auction_matching() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -1435,6 +1447,7 @@ fn broker_open_auction_uses_auction_volume_without_quote_liquidity() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -1538,6 +1551,7 @@ fn broker_cancels_buy_when_open_hits_upper_limit() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -1653,6 +1667,7 @@ fn broker_applies_price_ratio_slippage_on_snapshot_fills() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -1755,6 +1770,7 @@ fn broker_applies_dynamic_slippage_on_snapshot_fills() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -1862,6 +1878,7 @@ fn broker_applies_tick_size_slippage_on_intraday_last_fills() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -1982,6 +1999,7 @@ fn broker_rejects_intraday_last_order_without_execution_quotes() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -2091,6 +2109,7 @@ fn broker_executes_intraday_last_on_start_quote_with_trade_delta() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -2209,6 +2228,7 @@ fn broker_cancels_market_order_remainder_when_intraday_quote_liquidity_exhausted
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -2339,6 +2359,7 @@ fn broker_cancels_market_buy_when_minute_has_no_volume() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -2445,6 +2466,7 @@ fn broker_splits_intraday_quote_fills_and_tracks_commission_by_order() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -2616,6 +2638,7 @@ fn broker_aggregates_intraday_quote_fills_into_vwap_leg() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -2771,6 +2794,7 @@ fn broker_executes_algo_vwap_value_with_time_window() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -2931,6 +2955,7 @@ fn broker_executes_algo_twap_percent_across_window_quotes() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -3093,6 +3118,7 @@ fn broker_uses_best_own_price_for_intraday_matching() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -3210,6 +3236,7 @@ fn broker_uses_best_counterparty_price_for_intraday_matching() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -3365,6 +3392,7 @@ fn rebalance_optimizer_skips_unfunded_buy_when_existing_position_cannot_sell() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -3375,6 +3403,7 @@ fn rebalance_optimizer_skips_unfunded_buy_when_existing_position_cannot_sell() {
pe_ttm: 18.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
],
@@ -3558,6 +3587,7 @@ fn rebalance_uses_day_open_for_open_auction_valuation() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -3568,6 +3598,7 @@ fn rebalance_uses_day_open_for_open_auction_valuation() {
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
],
@@ -3744,6 +3775,7 @@ fn rebalance_optimizer_prioritizes_higher_target_weight_when_cash_is_tight() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -3754,6 +3786,7 @@ fn rebalance_optimizer_prioritizes_higher_target_weight_when_cash_is_tight() {
pe_ttm: 18.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
],
@@ -3926,6 +3959,7 @@ fn rebalance_optimizer_does_not_scale_targets_above_requested_weight() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -3936,6 +3970,7 @@ fn rebalance_optimizer_does_not_scale_targets_above_requested_weight() {
pe_ttm: 18.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
],
@@ -4062,6 +4097,7 @@ fn broker_uses_board_specific_min_quantity_and_step_size_for_buy_sizing() {
pe_ttm: 20.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -4166,6 +4202,7 @@ fn broker_allows_bjse_quantities_above_minimum_without_round_lot_step() {
pe_ttm: 20.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -4272,6 +4309,7 @@ fn broker_allows_full_odd_lot_sell_when_liquidating_position() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -4386,6 +4424,7 @@ fn same_day_sell_then_rebuy_is_rejected_by_default() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
})
.collect::<Vec<_>>();
@@ -4526,6 +4565,7 @@ fn same_day_sell_then_rebuy_can_be_allowed_by_policy() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
})
.collect::<Vec<_>>();
@@ -4778,6 +4818,7 @@ fn two_day_limit_order_data(day1_open: f64, day2_open: f64) -> DataSet {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot {
@@ -4788,6 +4829,7 @@ fn two_day_limit_order_data(day1_open: f64, day2_open: f64) -> DataSet {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
},
],
@@ -6104,6 +6146,7 @@ fn broker_reserves_sellable_quantity_for_open_limit_sells() {
pe_ttm: 15.0,
turnover_ratio: Some(2.0),
effective_turnover_ratio: Some(1.8),
adjustment_factor_backward1: None,
extra_factors: BTreeMap::new(),
}],
vec![CandidateEligibility {
@@ -72,6 +72,7 @@ fn factor(
pe_ttm: 18.0,
turnover_ratio: None,
effective_turnover_ratio: None,
adjustment_factor_backward1: None,
extra_factors: Default::default(),
}
}