perf: transpose rolling boundary index by date

This commit is contained in:
boris
2026-09-05 02:17:24 +08:00
parent a35137ed1c
commit abe4fed452
+44 -24
View File
@@ -572,13 +572,11 @@ const MISSING_ROW_POSITION: u32 = u32::MAX;
const MAX_DENSE_ROW_INDEX_BYTES: usize = 256 * 1024 * 1024;
#[derive(Debug, Clone)]
struct SymbolSeriesEndPositions {
decision: Vec<u32>,
current: Vec<u32>,
struct CalendarSeriesEndPositions {
decision: Vec<Vec<u32>>,
current: Vec<Vec<u32>>,
}
type SymbolSeriesEndPositionIndex = Vec<Option<SymbolSeriesEndPositions>>;
const MAX_SERIES_END_POSITION_INDEX_BYTES: usize = 256 * 1024 * 1024;
#[derive(Debug, Clone)]
@@ -1324,7 +1322,7 @@ pub struct DataSet {
adjusted_close_series_by_symbol: Arc<AHashMap<String, Arc<AdjustedCloseSeries>>>,
market_series_by_symbol_id: Arc<Vec<Option<Arc<SymbolPriceSeries>>>>,
adjusted_close_series_by_symbol_id: Arc<Vec<Option<Arc<AdjustedCloseSeries>>>>,
market_series_end_positions_by_symbol_id: Arc<Option<SymbolSeriesEndPositionIndex>>,
market_series_end_positions_by_calendar_index: Arc<Option<CalendarSeriesEndPositions>>,
benchmark_series_cache: Arc<BenchmarkPriceSeries>,
symbol_id_by_code: Arc<AHashMap<String, u32>>,
symbol_by_id: Arc<Vec<Arc<str>>>,
@@ -1399,8 +1397,8 @@ impl DataSet {
let mut calendar_dates = self.calendar.days().to_vec();
calendar_dates.extend(dates);
let calendar = Arc::new(TradingCalendar::new(calendar_dates));
self.market_series_end_positions_by_symbol_id = Arc::new(
build_symbol_series_end_positions(&self.market_series_by_symbol_id, &calendar),
self.market_series_end_positions_by_calendar_index = Arc::new(
build_calendar_series_end_positions(&self.market_series_by_symbol_id, &calendar),
);
self.calendar = calendar;
self
@@ -1823,8 +1821,8 @@ impl DataSet {
adjusted_close_series_by_symbol_id[symbol_id as usize] = Some(Arc::clone(series));
}
}
let market_series_end_positions_by_symbol_id =
build_symbol_series_end_positions(&market_series_by_symbol_id, &calendar);
let market_series_end_positions_by_calendar_index =
build_calendar_series_end_positions(&market_series_by_symbol_id, &calendar);
let execution_quotes_by_date = build_execution_quote_index(execution_quotes);
let mut execution_quote_dates =
execution_quotes_by_date.keys().copied().collect::<Vec<_>>();
@@ -1859,8 +1857,8 @@ impl DataSet {
adjusted_close_series_by_symbol: Arc::new(adjusted_close_series_by_symbol),
market_series_by_symbol_id: Arc::new(market_series_by_symbol_id),
adjusted_close_series_by_symbol_id: Arc::new(adjusted_close_series_by_symbol_id),
market_series_end_positions_by_symbol_id: Arc::new(
market_series_end_positions_by_symbol_id,
market_series_end_positions_by_calendar_index: Arc::new(
market_series_end_positions_by_calendar_index,
),
benchmark_series_cache: Arc::new(benchmark_series_cache),
symbol_id_by_code: Arc::new(symbol_id_by_code),
@@ -2041,17 +2039,21 @@ impl DataSet {
include_now: bool,
) -> Option<usize> {
let positions = self
.market_series_end_positions_by_symbol_id
.market_series_end_positions_by_calendar_index
.as_ref()
.as_ref()?
.get(symbol_id as usize)?
.as_ref()?;
let end = if include_now {
positions.current.get(calendar_index)
positions
.current
.get(calendar_index)?
.get(symbol_id as usize)
} else {
positions.decision.get(calendar_index)
positions
.decision
.get(calendar_index)?
.get(symbol_id as usize)
}?;
Some(*end as usize)
(*end != MISSING_ROW_POSITION).then_some(*end as usize)
}
pub(crate) fn market_current_series_end_index_by_symbol_id(
@@ -4299,10 +4301,10 @@ fn build_dense_row_positions<T>(
Some(positions_by_date)
}
fn build_symbol_series_end_positions(
fn build_calendar_series_end_positions(
series_by_symbol_id: &[Option<Arc<SymbolPriceSeries>>],
calendar: &TradingCalendar,
) -> Option<SymbolSeriesEndPositionIndex> {
) -> Option<CalendarSeriesEndPositions> {
let entries = series_by_symbol_id.len().checked_mul(calendar.len())?;
let bytes = entries
.checked_mul(2)?
@@ -4316,7 +4318,7 @@ fn build_symbol_series_end_positions(
}
let calendar_days = calendar.days();
let positions = series_by_symbol_id
let positions_by_symbol = series_by_symbol_id
.par_iter()
.map(|series| {
let series = series.as_deref()?;
@@ -4339,10 +4341,28 @@ fn build_symbol_series_end_positions(
};
current.push(current_index as u32);
}
Some(SymbolSeriesEndPositions { decision, current })
Some((decision, current))
})
.collect::<Vec<_>>();
Some(positions)
let positions_by_calendar = (0..calendar_days.len())
.into_par_iter()
.map(|calendar_index| {
let mut decision = Vec::with_capacity(series_by_symbol_id.len());
let mut current = Vec::with_capacity(series_by_symbol_id.len());
for positions in &positions_by_symbol {
if let Some((symbol_decision, symbol_current)) = positions {
decision.push(symbol_decision[calendar_index]);
current.push(symbol_current[calendar_index]);
} else {
decision.push(MISSING_ROW_POSITION);
current.push(MISSING_ROW_POSITION);
}
}
(decision, current)
})
.collect::<Vec<_>>();
let (decision, current) = positions_by_calendar.into_iter().unzip();
Some(CalendarSeriesEndPositions { decision, current })
}
fn dense_row_position(
@@ -6000,7 +6020,7 @@ mod tests {
let dates = data.calendar().days();
assert!(
data.market_series_end_positions_by_symbol_id
data.market_series_end_positions_by_calendar_index
.as_ref()
.is_some()
);