切换回测执行价为分钟线语义

This commit is contained in:
boris
2026-06-26 13:27:49 +08:00
parent 6db480b91d
commit 7f40cfdab0
14 changed files with 129 additions and 132 deletions
+41 -41
View File
@@ -1444,7 +1444,7 @@ where
let snapshot = self.data.market(date, &intent.symbol);
if matches!(
self.broker.matching_type(),
MatchingType::NextTickBestCounterparty | MatchingType::CounterpartyOffer
MatchingType::NextMinuteBestCounterparty | MatchingType::CounterpartyOffer
) {
let depth = self.data.order_book_depth_on(date, &intent.symbol);
if !depth.is_empty() {
@@ -1454,7 +1454,7 @@ where
let quotes = self.data.execution_quotes_on(date, &intent.symbol);
for quote in quotes {
let price = match self.broker.matching_type() {
MatchingType::NextTickBestOwn => match intent.side() {
MatchingType::NextMinuteBestOwn => match intent.side() {
OrderSide::Buy => {
if quote.bid1.is_finite() && quote.bid1 > 0.0 {
quote.bid1
@@ -1470,7 +1470,7 @@ where
}
}
},
MatchingType::NextTickBestCounterparty | MatchingType::CounterpartyOffer => {
MatchingType::NextMinuteBestCounterparty | MatchingType::CounterpartyOffer => {
match intent.side() {
OrderSide::Buy => quote.buy_price().unwrap_or(quote.last_price),
OrderSide::Sell => quote.sell_price().unwrap_or(quote.last_price),
@@ -2233,9 +2233,9 @@ where
"bar:post",
)?;
if should_run_tick_events(&schedule_rules, &self.subscriptions) {
if should_run_minute_events(&schedule_rules, &self.subscriptions) {
let filter_by_subscription = !self.subscriptions.is_empty();
let tick_quotes = self
let minute_quotes = self
.data
.execution_quotes_on_date(execution_date)
.into_iter()
@@ -2243,9 +2243,9 @@ where
!filter_by_subscription || self.subscriptions.contains(&quote.symbol)
})
.collect::<Vec<_>>();
for quote in tick_quotes {
let tick_time = quote.timestamp.time();
let tick_open_orders = self.open_order_views();
for quote in minute_quotes {
let minute_time = quote.timestamp.time();
let minute_open_orders = self.open_order_views();
publish_phase_event(
&mut self.strategy,
&mut self.process_event_bus,
@@ -2255,35 +2255,35 @@ where
&self.data,
&portfolio,
self.futures_account.as_ref(),
&tick_open_orders,
&minute_open_orders,
self.dynamic_universe.as_ref(),
&self.subscriptions,
&mut process_events,
execution_date,
ProcessEventKind::PreTick,
format!("tick:{}:{}:pre", quote.symbol, quote.timestamp),
ProcessEventKind::PreMinute,
format!("minute:{}:{}:pre", quote.symbol, quote.timestamp),
)?;
let mut tick_decision = collect_scheduled_decisions(
let mut minute_decision = collect_scheduled_decisions(
&mut self.strategy,
&scheduler,
execution_date,
ScheduleStage::Tick,
ScheduleStage::Minute,
&schedule_rules,
decision_date,
decision_index,
&self.data,
&portfolio,
self.futures_account.as_ref(),
&tick_open_orders,
&minute_open_orders,
self.dynamic_universe.as_ref(),
&self.subscriptions,
&mut process_events,
&mut self.process_event_bus,
Some(tick_time),
Some(minute_time),
result.order_events.as_slice(),
result.fills.as_slice(),
)?;
tick_decision.merge_from(self.strategy.on_tick(
minute_decision.merge_from(self.strategy.on_minute(
&StrategyContext {
execution_date,
decision_date,
@@ -2291,7 +2291,7 @@ where
data: &self.data,
portfolio: &portfolio,
futures_account: self.futures_account.as_ref(),
open_orders: &tick_open_orders,
open_orders: &minute_open_orders,
dynamic_universe: self.dynamic_universe.as_ref(),
subscriptions: &self.subscriptions,
process_events: &process_events,
@@ -2311,42 +2311,42 @@ where
&self.data,
&portfolio,
self.futures_account.as_ref(),
&tick_open_orders,
&minute_open_orders,
self.dynamic_universe.as_ref(),
&self.subscriptions,
&mut process_events,
execution_date,
ProcessEventKind::Tick,
format!("tick:{}:{}", quote.symbol, quote.timestamp),
ProcessEventKind::Minute,
format!("minute:{}:{}", quote.symbol, quote.timestamp),
)?;
self.apply_strategy_directives(
execution_date,
decision_date,
decision_index,
&mut portfolio,
&tick_open_orders,
&minute_open_orders,
&mut process_events,
&mut tick_decision,
&mut minute_decision,
&mut directive_report,
)?;
let pre_tick_execution_orders = self.open_order_views();
let pre_minute_execution_orders = self.open_order_views();
self.ensure_execution_quotes_for_decision(
execution_date,
&portfolio,
&pre_tick_execution_orders,
&tick_decision,
Some(tick_time),
Some(tick_time),
&pre_minute_execution_orders,
&minute_decision,
Some(minute_time),
Some(minute_time),
)?;
let mut tick_report = self.broker.execute_between(
let mut minute_report = self.broker.execute_between(
execution_date,
&mut portfolio,
&self.data,
&tick_decision,
Some(tick_time),
Some(tick_time),
&minute_decision,
Some(minute_time),
Some(minute_time),
)?;
let post_tick_open_orders = self.open_order_views();
let post_minute_open_orders = self.open_order_views();
publish_process_events(
&mut self.strategy,
&mut self.process_event_bus,
@@ -2356,13 +2356,13 @@ where
&self.data,
&portfolio,
self.futures_account.as_ref(),
&post_tick_open_orders,
&post_minute_open_orders,
self.dynamic_universe.as_ref(),
&self.subscriptions,
&mut process_events,
&mut tick_report.process_events,
&mut minute_report.process_events,
)?;
merge_broker_report(&mut report, tick_report);
merge_broker_report(&mut report, minute_report);
publish_phase_event(
&mut self.strategy,
&mut self.process_event_bus,
@@ -2372,13 +2372,13 @@ where
&self.data,
&portfolio,
self.futures_account.as_ref(),
&post_tick_open_orders,
&post_minute_open_orders,
self.dynamic_universe.as_ref(),
&self.subscriptions,
&mut process_events,
execution_date,
ProcessEventKind::PostTick,
format!("tick:{}:{}:post", quote.symbol, quote.timestamp),
ProcessEventKind::PostMinute,
format!("minute:{}:{}:post", quote.symbol, quote.timestamp),
)?;
}
}
@@ -3709,7 +3709,7 @@ fn stage_label(stage: ScheduleStage) -> &'static str {
ScheduleStage::BeforeTrading => "before_trading",
ScheduleStage::OpenAuction => "open_auction",
ScheduleStage::Bar => "bar",
ScheduleStage::Tick => "tick",
ScheduleStage::Minute => "minute",
ScheduleStage::OnDay => "on_day",
ScheduleStage::AfterTrading => "after_trading",
ScheduleStage::Settlement => "settlement",
@@ -3723,8 +3723,8 @@ fn stage_datetime(
time.map(|value| date.and_time(value))
}
fn should_run_tick_events(rules: &[ScheduleRule], subscriptions: &BTreeSet<String>) -> bool {
!subscriptions.is_empty() || rules.iter().any(|rule| rule.stage == ScheduleStage::Tick)
fn should_run_minute_events(rules: &[ScheduleRule], subscriptions: &BTreeSet<String>) -> bool {
!subscriptions.is_empty() || rules.iter().any(|rule| rule.stage == ScheduleStage::Minute)
}
fn merge_broker_report(target: &mut BrokerExecutionReport, incoming: BrokerExecutionReport) {