共享按日期市值排序索引

This commit is contained in:
boris
2026-08-29 20:16:53 +08:00
parent 8bbd2ebf7a
commit bb721ab258
2 changed files with 56 additions and 7 deletions
+31
View File
@@ -1312,6 +1312,7 @@ pub struct DataSet {
market_row_positions_by_date: Arc<Option<DenseRowPositionIndex>>,
factor_by_date: Arc<BTreeMap<NaiveDate, Vec<DailyFactorSnapshot>>>,
factor_symbol_ids_by_date: Arc<BTreeMap<NaiveDate, Vec<u32>>>,
factor_market_cap_order_by_date: Arc<OnceLock<BTreeMap<NaiveDate, Vec<usize>>>>,
factor_row_positions_by_date: Arc<Option<DenseRowPositionIndex>>,
factor_text_by_date: Arc<BTreeMap<NaiveDate, Vec<FactorTextValue>>>,
factor_text_symbol_indices_by_date:
@@ -1794,6 +1795,7 @@ impl DataSet {
market_row_positions_by_date: Arc::new(market_row_positions_by_date),
factor_by_date: Arc::new(factor_by_date),
factor_symbol_ids_by_date: Arc::new(factor_symbol_ids_by_date),
factor_market_cap_order_by_date: Arc::new(OnceLock::new()),
factor_row_positions_by_date: Arc::new(factor_row_positions_by_date),
factor_text_by_date: Arc::new(factor_text_by_date),
factor_text_symbol_indices_by_date: Arc::new(factor_text_symbol_indices_by_date),
@@ -2899,6 +2901,15 @@ impl DataSet {
.unwrap_or(&[])
}
/// Returns the immutable factor-row order for ascending decision market cap.
/// The index is built once per DataSet and shared by all cloned run views.
pub fn factor_market_cap_order_on(&self, date: NaiveDate) -> Option<&[usize]> {
self.factor_market_cap_order_by_date
.get_or_init(|| build_factor_market_cap_order(&self.factor_by_date))
.get(&date)
.map(Vec::as_slice)
}
pub fn factor_text_snapshots_on(&self, date: NaiveDate) -> Vec<&FactorTextValue> {
self.factor_text_by_date
.get(&date)
@@ -4037,6 +4048,26 @@ where
.collect()
}
fn build_factor_market_cap_order(
factor_by_date: &BTreeMap<NaiveDate, Vec<DailyFactorSnapshot>>,
) -> BTreeMap<NaiveDate, Vec<usize>> {
factor_by_date
.iter()
.map(|(date, rows)| {
let mut indices = (0..rows.len()).collect::<Vec<_>>();
indices.sort_unstable_by(|left, right| {
rows[*left]
.market_cap_bn
.partial_cmp(&rows[*right].market_cap_bn)
.unwrap_or(std::cmp::Ordering::Equal)
.then_with(|| rows[*left].symbol.cmp(&rows[*right].symbol))
.then_with(|| left.cmp(right))
});
(*date, indices)
})
.collect()
}
fn build_dense_row_positions<T>(
groups: &BTreeMap<NaiveDate, Vec<T>>,
symbol_ids_by_date: &BTreeMap<NaiveDate, Vec<u32>>,
+25 -7
View File
@@ -8991,7 +8991,23 @@ impl PlatformExprStrategy {
};
let factor_symbol_ids = ctx.data.factor_symbol_ids_on(factor_date);
debug_assert_eq!(factor_rows.len(), factor_symbol_ids.len());
for (factor, symbol_id) in factor_rows.iter().zip(factor_symbol_ids.iter().copied()) {
let market_cap_order = ctx.data.factor_market_cap_order_on(factor_date);
let mut fallback_factor_rows =
factor_rows.iter().zip(factor_symbol_ids.iter().copied());
let mut ordered_factor_row_index = 0usize;
let factor_rows = std::iter::from_fn(|| {
if let Some(indices) = market_cap_order {
let row_index = *indices.get(ordered_factor_row_index)?;
ordered_factor_row_index += 1;
Some((
factor_rows.get(row_index)?,
*factor_symbol_ids.get(row_index)?,
))
} else {
fallback_factor_rows.next()
}
});
for (factor, symbol_id) in factor_rows {
if ctx.has_dynamic_universe() && !ctx.dynamic_universe_contains(&factor.symbol) {
continue;
}
@@ -9059,12 +9075,14 @@ impl PlatformExprStrategy {
free_float_cap_bn,
});
}
rows.sort_unstable_by(|left, right| {
left.market_cap_bn
.partial_cmp(&right.market_cap_bn)
.unwrap_or(std::cmp::Ordering::Equal)
.then_with(|| left.symbol.cmp(&right.symbol))
});
if market_cap_order.is_none() {
rows.sort_unstable_by(|left, right| {
left.market_cap_bn
.partial_cmp(&right.market_cap_bn)
.unwrap_or(std::cmp::Ordering::Equal)
.then_with(|| left.symbol.cmp(&right.symbol))
});
}
(rows, decisions)
}