复用预计算行情证券范围

This commit is contained in:
boris
2026-09-07 09:41:10 +08:00
parent e542e52bdb
commit 1aa7c28616
2 changed files with 174 additions and 33 deletions
+51 -23
View File
@@ -1,4 +1,5 @@
use std::collections::{BTreeMap, BTreeSet};
use std::sync::Arc;
use chrono::{Datelike, Duration, NaiveDate, NaiveTime};
use serde::{Deserialize, Serialize};
@@ -453,6 +454,8 @@ pub struct BacktestEngine<S, C, R> {
futures_cost_model: FuturesTransactionCostModel,
futures_validation_config: FuturesValidationConfig,
execution_quote_loader: Option<ExecutionQuoteLoader>,
preplanned_decision_quote_symbols_by_date:
Option<Arc<BTreeMap<NaiveDate, BTreeSet<String>>>>,
execution_quote_request_cache:
BTreeSet<(NaiveDate, String, Option<NaiveTime>, Option<NaiveTime>)>,
risk_free_rate_contract: Option<RiskFreeRateContract>,
@@ -539,6 +542,7 @@ impl<S, C, R> BacktestEngine<S, C, R> {
futures_cost_model: FuturesTransactionCostModel::default(),
futures_validation_config: FuturesValidationConfig::default(),
execution_quote_loader: None,
preplanned_decision_quote_symbols_by_date: None,
execution_quote_request_cache: BTreeSet::new(),
risk_free_rate_contract: None,
}
@@ -563,6 +567,14 @@ impl<S, C, R> BacktestEngine<S, C, R> {
self
}
pub fn with_preplanned_decision_quote_symbols_by_date(
mut self,
symbols_by_date: Arc<BTreeMap<NaiveDate, BTreeSet<String>>>,
) -> Self {
self.preplanned_decision_quote_symbols_by_date = Some(symbols_by_date);
self
}
pub fn with_dividend_reinvestment(mut self, enabled: bool) -> Self {
self.dividend_reinvestment = enabled;
self
@@ -2520,31 +2532,47 @@ where
let on_day_open_orders = self.open_order_views();
let decision_quote_times = self.strategy.decision_quote_times();
if self.execution_quote_loader.is_some() && !decision_quote_times.is_empty() {
let decision_quote_symbols =
self.strategy.decision_quote_symbols(&StrategyContext {
if let Some(preplanned) = self
.preplanned_decision_quote_symbols_by_date
.as_ref()
.map(Arc::clone)
{
let empty_symbols = BTreeSet::new();
let decision_quote_symbols = preplanned
.get(&execution_date)
.unwrap_or(&empty_symbols);
self.ensure_execution_quotes_for_symbols_at_times(
execution_date,
decision_date,
decision_index,
data: &self.data,
portfolio: &portfolio,
futures_account: self.futures_account.as_ref(),
open_orders: &on_day_open_orders,
dynamic_universe: self.dynamic_universe.as_ref(),
subscriptions: &self.subscriptions,
process_events: &process_events,
active_process_event: None,
active_datetime: stage_datetime(
decision_quote_symbols,
&decision_quote_times,
)?;
} else {
let decision_quote_symbols =
self.strategy.decision_quote_symbols(&StrategyContext {
execution_date,
decision_date,
default_stage_time(ScheduleStage::OnDay),
),
order_events: result.order_events.as_slice(),
fills: result.fills.as_slice(),
})?;
self.ensure_execution_quotes_for_symbols_at_times(
execution_date,
&decision_quote_symbols,
&decision_quote_times,
)?;
decision_index,
data: &self.data,
portfolio: &portfolio,
futures_account: self.futures_account.as_ref(),
open_orders: &on_day_open_orders,
dynamic_universe: self.dynamic_universe.as_ref(),
subscriptions: &self.subscriptions,
process_events: &process_events,
active_process_event: None,
active_datetime: stage_datetime(
decision_date,
default_stage_time(ScheduleStage::OnDay),
),
order_events: result.order_events.as_slice(),
fills: result.fills.as_slice(),
})?;
self.ensure_execution_quotes_for_symbols_at_times(
execution_date,
&decision_quote_symbols,
&decision_quote_times,
)?;
}
}
self.ensure_execution_quotes_for_portfolio_times(
execution_date,