让分钟行情按流式迭代器处理
This commit is contained in:
@@ -321,6 +321,57 @@ impl IntradayExecutionQuote {
|
||||
}
|
||||
}
|
||||
|
||||
/// A borrowed, timestamp-ordered merge of the execution-quote streams for one
|
||||
/// trading day. The iterator keeps only stream cursors and never clones quote
|
||||
/// payloads; callers decide how much of the day they need to retain.
|
||||
pub struct ExecutionQuoteIterator<'a> {
|
||||
streams: Vec<(&'a str, &'a [IntradayExecutionQuote])>,
|
||||
heap: BinaryHeap<Reverse<(NaiveDateTime, usize, usize)>>,
|
||||
}
|
||||
|
||||
impl<'a> ExecutionQuoteIterator<'a> {
|
||||
fn new(
|
||||
rows_by_symbol: Option<&'a HashMap<String, Vec<IntradayExecutionQuote>>>,
|
||||
symbols: Option<&BTreeSet<String>>,
|
||||
) -> Self {
|
||||
let mut streams = rows_by_symbol
|
||||
.into_iter()
|
||||
.flat_map(|rows_by_symbol| rows_by_symbol.iter())
|
||||
.filter(|(symbol, _)| {
|
||||
symbols
|
||||
.map(|allowed_symbols| allowed_symbols.contains(*symbol))
|
||||
.unwrap_or(true)
|
||||
})
|
||||
.map(|(symbol, rows)| (symbol.as_str(), rows.as_slice()))
|
||||
.collect::<Vec<_>>();
|
||||
streams.sort_by_key(|(symbol, _)| *symbol);
|
||||
|
||||
let mut heap = BinaryHeap::with_capacity(streams.len());
|
||||
for (stream_index, (_, rows)) in streams.iter().enumerate() {
|
||||
if let Some(first) = rows.first() {
|
||||
heap.push(Reverse((first.timestamp, stream_index, 0)));
|
||||
}
|
||||
}
|
||||
Self { streams, heap }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for ExecutionQuoteIterator<'a> {
|
||||
type Item = &'a IntradayExecutionQuote;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let Reverse((_timestamp, stream_index, row_index)) = self.heap.pop()?;
|
||||
let rows = self.streams.get(stream_index)?.1;
|
||||
let quote = rows.get(row_index)?;
|
||||
let next_index = row_index + 1;
|
||||
if let Some(next) = rows.get(next_index) {
|
||||
self.heap
|
||||
.push(Reverse((next.timestamp, stream_index, next_index)));
|
||||
}
|
||||
Some(quote)
|
||||
}
|
||||
}
|
||||
|
||||
impl CorporateAction {
|
||||
pub fn split_ratio(&self) -> f64 {
|
||||
1.0 + self.share_bonus.max(0.0) + self.share_gift.max(0.0)
|
||||
@@ -1723,41 +1774,22 @@ impl DataSet {
|
||||
self.execution_quotes_on_date_for_symbols(date, None)
|
||||
}
|
||||
|
||||
pub fn execution_quotes_iter_on_date_for_symbols(
|
||||
&self,
|
||||
date: NaiveDate,
|
||||
symbols: Option<&BTreeSet<String>>,
|
||||
) -> ExecutionQuoteIterator<'_> {
|
||||
ExecutionQuoteIterator::new(self.execution_quotes_by_date.get(&date), symbols)
|
||||
}
|
||||
|
||||
pub fn execution_quotes_on_date_for_symbols(
|
||||
&self,
|
||||
date: NaiveDate,
|
||||
symbols: Option<&BTreeSet<String>>,
|
||||
) -> Vec<IntradayExecutionQuote> {
|
||||
let Some(rows_by_symbol) = self.execution_quotes_by_date.get(&date) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let mut streams = rows_by_symbol
|
||||
.iter()
|
||||
.filter(|(symbol, _)| {
|
||||
symbols
|
||||
.map(|allowed_symbols| allowed_symbols.contains(*symbol))
|
||||
.unwrap_or(true)
|
||||
})
|
||||
.map(|(symbol, rows)| (symbol.as_str(), rows.as_slice()))
|
||||
.collect::<Vec<_>>();
|
||||
streams.sort_by_key(|(symbol, _)| *symbol);
|
||||
let total_rows = streams.iter().map(|(_, rows)| rows.len()).sum();
|
||||
let mut heap = BinaryHeap::<Reverse<(NaiveDateTime, usize, usize)>>::new();
|
||||
for (stream_index, (_, rows)) in streams.iter().enumerate() {
|
||||
if let Some(first) = rows.first() {
|
||||
heap.push(Reverse((first.timestamp, stream_index, 0)));
|
||||
}
|
||||
}
|
||||
let mut merged = Vec::with_capacity(total_rows);
|
||||
while let Some(Reverse((_timestamp, stream_index, row_index))) = heap.pop() {
|
||||
let (_, rows) = streams[stream_index];
|
||||
merged.push(rows[row_index].clone());
|
||||
let next_index = row_index + 1;
|
||||
if let Some(next) = rows.get(next_index) {
|
||||
heap.push(Reverse((next.timestamp, stream_index, next_index)));
|
||||
}
|
||||
}
|
||||
merged
|
||||
self.execution_quotes_iter_on_date_for_symbols(date, symbols)
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn remove_execution_quotes_on_date(&mut self, date: NaiveDate) -> usize {
|
||||
@@ -4030,6 +4062,11 @@ mod tests {
|
||||
("09:32:00".to_string(), "000001.SZ".to_string()),
|
||||
]
|
||||
);
|
||||
let streamed_keys = run_data
|
||||
.execution_quotes_iter_on_date_for_symbols(date, None)
|
||||
.map(|row| (row.timestamp.time().to_string(), row.symbol.clone()))
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(streamed_keys, keys);
|
||||
assert_eq!(merged[2].last_price, 10.0);
|
||||
let allowed_symbols = BTreeSet::from(["000001.SZ".to_string()]);
|
||||
let filtered = run_data.execution_quotes_on_date_for_symbols(date, Some(&allowed_symbols));
|
||||
|
||||
Reference in New Issue
Block a user