重构分钟线事件流与订阅加载

This commit is contained in:
boris
2026-08-25 01:41:50 +08:00
parent 4cf0224d2d
commit a147c495af
6 changed files with 316 additions and 47 deletions
+50 -24
View File
@@ -578,6 +578,9 @@ where
if self.execution_quote_request_cache.contains(&request_key) {
return false;
}
if start_time.is_none() && end_time.is_none() {
return true;
}
if start_time.is_some() && end_time.is_none() {
return !has_execution_quote_near_start_time(
&self.data,
@@ -1666,6 +1669,7 @@ where
F: FnMut(&BacktestDayProgress),
{
let mut portfolio = PortfolioState::new(self.config.initial_cash);
self.subscriptions = self.strategy.initial_subscriptions();
let scheduler_calendar = self.data.calendar().clone();
let scheduler = Scheduler::new(&scheduler_calendar);
let calendar_dates = self
@@ -2410,6 +2414,15 @@ where
)?;
if should_run_minute_events(&schedule_rules, &self.subscriptions) {
if self.execution_quote_loader.is_some() && !self.subscriptions.is_empty() {
let mut minute_symbols = self.subscriptions.clone();
self.load_missing_execution_quotes(
execution_date,
None,
None,
&mut minute_symbols,
)?;
}
let filter_by_subscription = !self.subscriptions.is_empty();
let minute_quotes = self
.data
@@ -2419,8 +2432,17 @@ where
!filter_by_subscription || self.subscriptions.contains(&quote.symbol)
})
.collect::<Vec<_>>();
for quote in minute_quotes {
let minute_time = quote.timestamp.time();
let mut minute_cursor = 0usize;
while minute_cursor < minute_quotes.len() {
let minute_timestamp = minute_quotes[minute_cursor].timestamp;
let minute_time = minute_timestamp.time();
let mut minute_end = minute_cursor + 1;
while minute_end < minute_quotes.len()
&& minute_quotes[minute_end].timestamp == minute_timestamp
{
minute_end += 1;
}
let minute_group = &minute_quotes[minute_cursor..minute_end];
let minute_open_orders = self.open_order_views();
publish_phase_event(
&mut self.strategy,
@@ -2437,7 +2459,7 @@ where
&mut process_events,
execution_date,
ProcessEventKind::PreMinute,
format!("minute:{}:{}:pre", quote.symbol, quote.timestamp),
format!("minute:{minute_timestamp}:pre"),
)?;
let mut minute_decision = collect_scheduled_decisions(
&mut self.strategy,
@@ -2459,25 +2481,27 @@ where
result.order_events.as_slice(),
result.fills.as_slice(),
)?;
minute_decision.merge_from(self.strategy.on_minute(
&StrategyContext {
execution_date,
decision_date,
decision_index,
data: &self.data,
portfolio: &portfolio,
futures_account: self.futures_account.as_ref(),
open_orders: &minute_open_orders,
dynamic_universe: self.dynamic_universe.as_ref(),
subscriptions: &self.subscriptions,
process_events: &process_events,
active_process_event: None,
active_datetime: Some(quote.timestamp),
order_events: result.order_events.as_slice(),
fills: result.fills.as_slice(),
},
&quote,
)?);
for quote in minute_group {
minute_decision.merge_from(self.strategy.on_minute(
&StrategyContext {
execution_date,
decision_date,
decision_index,
data: &self.data,
portfolio: &portfolio,
futures_account: self.futures_account.as_ref(),
open_orders: &minute_open_orders,
dynamic_universe: self.dynamic_universe.as_ref(),
subscriptions: &self.subscriptions,
process_events: &process_events,
active_process_event: None,
active_datetime: Some(minute_timestamp),
order_events: result.order_events.as_slice(),
fills: result.fills.as_slice(),
},
quote,
)?);
}
publish_phase_event(
&mut self.strategy,
&mut self.process_event_bus,
@@ -2493,7 +2517,7 @@ where
&mut process_events,
execution_date,
ProcessEventKind::Minute,
format!("minute:{}:{}", quote.symbol, quote.timestamp),
format!("minute:{minute_timestamp}"),
)?;
self.apply_strategy_directives(
execution_date,
@@ -2559,9 +2583,11 @@ where
&mut process_events,
execution_date,
ProcessEventKind::PostMinute,
format!("minute:{}:{}:post", quote.symbol, quote.timestamp),
format!("minute:{minute_timestamp}:post"),
)?;
minute_cursor = minute_end;
}
self.data.remove_execution_quotes_on_date(execution_date);
}
portfolio.update_prices_with_options(