跳过无业务分钟回调

This commit is contained in:
boris
2026-08-25 04:02:33 +08:00
parent 85c9d03b99
commit 81d70f18b3
6 changed files with 154 additions and 21 deletions
+52 -21
View File
@@ -1,6 +1,6 @@
use std::collections::{BTreeMap, BTreeSet};
use chrono::{Datelike, Duration, NaiveDate, NaiveTime};
use chrono::{Datelike, Duration, NaiveDate, NaiveTime, Timelike};
use serde::Serialize;
use thiserror::Error;
@@ -1086,6 +1086,10 @@ where
views
}
fn has_open_orders(&self) -> bool {
self.broker.has_open_orders() || !self.futures_open_orders.is_empty()
}
fn aggregate_initial_cash(&self) -> f64 {
self.config.initial_cash
+ self
@@ -2486,6 +2490,20 @@ where
!filter_by_subscription || self.subscriptions.contains(&quote.symbol)
})
.collect::<Vec<_>>();
let requires_minute_callbacks = self.strategy.requires_minute_callbacks();
let has_minute_process_listeners = self.process_event_bus.has_listeners_for(&[
ProcessEventKind::PreMinute,
ProcessEventKind::Minute,
ProcessEventKind::PostMinute,
]);
let minute_schedule_all_times = schedule_rules
.iter()
.any(|rule| rule.stage == ScheduleStage::Minute && rule.time_rule.is_none());
let minute_schedule_minutes = schedule_rules
.iter()
.filter(|rule| rule.stage == ScheduleStage::Minute)
.filter_map(|rule| rule.time_rule.as_ref()?.minute_of_day())
.collect::<BTreeSet<_>>();
let mut minute_cursor = 0usize;
while minute_cursor < minute_quotes.len() {
let minute_timestamp = minute_quotes[minute_cursor].timestamp;
@@ -2497,6 +2515,17 @@ where
minute_end += 1;
}
let minute_group = &minute_quotes[minute_cursor..minute_end];
let schedule_candidate = minute_schedule_all_times
|| minute_schedule_minutes
.contains(&(minute_time.hour() * 60 + minute_time.minute()));
if !requires_minute_callbacks
&& !has_minute_process_listeners
&& !schedule_candidate
&& !self.has_open_orders()
{
minute_cursor = minute_end;
continue;
}
let minute_open_orders = self.open_order_views();
publish_phase_event(
&mut self.strategy,
@@ -2535,26 +2564,28 @@ where
result.order_events.as_slice(),
result.fills.as_slice(),
)?;
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,
)?);
if requires_minute_callbacks {
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,