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; const MAX_DENSE_ROW_INDEX_BYTES: usize = 256 * 1024 * 1024;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct SymbolSeriesEndPositions { struct CalendarSeriesEndPositions {
decision: Vec<u32>, decision: Vec<Vec<u32>>,
current: Vec<u32>, current: Vec<Vec<u32>>,
} }
type SymbolSeriesEndPositionIndex = Vec<Option<SymbolSeriesEndPositions>>;
const MAX_SERIES_END_POSITION_INDEX_BYTES: usize = 256 * 1024 * 1024; const MAX_SERIES_END_POSITION_INDEX_BYTES: usize = 256 * 1024 * 1024;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -1324,7 +1322,7 @@ pub struct DataSet {
adjusted_close_series_by_symbol: Arc<AHashMap<String, Arc<AdjustedCloseSeries>>>, adjusted_close_series_by_symbol: Arc<AHashMap<String, Arc<AdjustedCloseSeries>>>,
market_series_by_symbol_id: Arc<Vec<Option<Arc<SymbolPriceSeries>>>>, market_series_by_symbol_id: Arc<Vec<Option<Arc<SymbolPriceSeries>>>>,
adjusted_close_series_by_symbol_id: Arc<Vec<Option<Arc<AdjustedCloseSeries>>>>, 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>, benchmark_series_cache: Arc<BenchmarkPriceSeries>,
symbol_id_by_code: Arc<AHashMap<String, u32>>, symbol_id_by_code: Arc<AHashMap<String, u32>>,
symbol_by_id: Arc<Vec<Arc<str>>>, symbol_by_id: Arc<Vec<Arc<str>>>,
@@ -1399,8 +1397,8 @@ impl DataSet {
let mut calendar_dates = self.calendar.days().to_vec(); let mut calendar_dates = self.calendar.days().to_vec();
calendar_dates.extend(dates); calendar_dates.extend(dates);
let calendar = Arc::new(TradingCalendar::new(calendar_dates)); let calendar = Arc::new(TradingCalendar::new(calendar_dates));
self.market_series_end_positions_by_symbol_id = Arc::new( self.market_series_end_positions_by_calendar_index = Arc::new(
build_symbol_series_end_positions(&self.market_series_by_symbol_id, &calendar), build_calendar_series_end_positions(&self.market_series_by_symbol_id, &calendar),
); );
self.calendar = calendar; self.calendar = calendar;
self self
@@ -1823,8 +1821,8 @@ impl DataSet {
adjusted_close_series_by_symbol_id[symbol_id as usize] = Some(Arc::clone(series)); adjusted_close_series_by_symbol_id[symbol_id as usize] = Some(Arc::clone(series));
} }
} }
let market_series_end_positions_by_symbol_id = let market_series_end_positions_by_calendar_index =
build_symbol_series_end_positions(&market_series_by_symbol_id, &calendar); build_calendar_series_end_positions(&market_series_by_symbol_id, &calendar);
let execution_quotes_by_date = build_execution_quote_index(execution_quotes); let execution_quotes_by_date = build_execution_quote_index(execution_quotes);
let mut execution_quote_dates = let mut execution_quote_dates =
execution_quotes_by_date.keys().copied().collect::<Vec<_>>(); 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), adjusted_close_series_by_symbol: Arc::new(adjusted_close_series_by_symbol),
market_series_by_symbol_id: Arc::new(market_series_by_symbol_id), 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), 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_calendar_index: Arc::new(
market_series_end_positions_by_symbol_id, market_series_end_positions_by_calendar_index,
), ),
benchmark_series_cache: Arc::new(benchmark_series_cache), benchmark_series_cache: Arc::new(benchmark_series_cache),
symbol_id_by_code: Arc::new(symbol_id_by_code), symbol_id_by_code: Arc::new(symbol_id_by_code),
@@ -2041,17 +2039,21 @@ impl DataSet {
include_now: bool, include_now: bool,
) -> Option<usize> { ) -> Option<usize> {
let positions = self let positions = self
.market_series_end_positions_by_symbol_id .market_series_end_positions_by_calendar_index
.as_ref() .as_ref()
.as_ref()?
.get(symbol_id as usize)?
.as_ref()?; .as_ref()?;
let end = if include_now { let end = if include_now {
positions.current.get(calendar_index) positions
.current
.get(calendar_index)?
.get(symbol_id as usize)
} else { } 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( 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) Some(positions_by_date)
} }
fn build_symbol_series_end_positions( fn build_calendar_series_end_positions(
series_by_symbol_id: &[Option<Arc<SymbolPriceSeries>>], series_by_symbol_id: &[Option<Arc<SymbolPriceSeries>>],
calendar: &TradingCalendar, calendar: &TradingCalendar,
) -> Option<SymbolSeriesEndPositionIndex> { ) -> Option<CalendarSeriesEndPositions> {
let entries = series_by_symbol_id.len().checked_mul(calendar.len())?; let entries = series_by_symbol_id.len().checked_mul(calendar.len())?;
let bytes = entries let bytes = entries
.checked_mul(2)? .checked_mul(2)?
@@ -4316,7 +4318,7 @@ fn build_symbol_series_end_positions(
} }
let calendar_days = calendar.days(); let calendar_days = calendar.days();
let positions = series_by_symbol_id let positions_by_symbol = series_by_symbol_id
.par_iter() .par_iter()
.map(|series| { .map(|series| {
let series = series.as_deref()?; let series = series.as_deref()?;
@@ -4339,10 +4341,28 @@ fn build_symbol_series_end_positions(
}; };
current.push(current_index as u32); current.push(current_index as u32);
} }
Some(SymbolSeriesEndPositions { decision, current }) Some((decision, current))
}) })
.collect::<Vec<_>>(); .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( fn dense_row_position(
@@ -6000,7 +6020,7 @@ mod tests {
let dates = data.calendar().days(); let dates = data.calendar().days();
assert!( assert!(
data.market_series_end_positions_by_symbol_id data.market_series_end_positions_by_calendar_index
.as_ref() .as_ref()
.is_some() .is_some()
); );