支持策略决策前批量加载执行价

This commit is contained in:
boris
2026-06-18 17:08:36 +08:00
parent 2265a5dc67
commit 3633905459
3 changed files with 83 additions and 0 deletions
+56
View File
@@ -622,6 +622,35 @@ where
Ok(()) Ok(())
} }
fn ensure_execution_quotes_for_symbols_at_times(
&mut self,
execution_date: NaiveDate,
symbols: &BTreeSet<String>,
quote_times: &[NaiveTime],
) -> Result<(), BacktestError> {
if self.execution_quote_loader.is_none() || quote_times.is_empty() || symbols.is_empty() {
return Ok(());
}
let base_symbols = symbols
.iter()
.filter(|symbol| !symbol.trim().is_empty())
.cloned()
.collect::<BTreeSet<_>>();
if base_symbols.is_empty() {
return Ok(());
}
for quote_time in quote_times {
let mut symbols = base_symbols.clone();
self.load_missing_execution_quotes(
execution_date,
Some(*quote_time),
None,
&mut symbols,
)?;
}
Ok(())
}
fn apply_strategy_directives( fn apply_strategy_directives(
&mut self, &mut self,
execution_date: NaiveDate, execution_date: NaiveDate,
@@ -1951,6 +1980,33 @@ where
)?; )?;
let on_day_open_orders = self.open_order_views(); let on_day_open_orders = self.open_order_views();
let decision_quote_times = self.strategy.decision_quote_times(); let decision_quote_times = self.strategy.decision_quote_times();
if !decision_quote_times.is_empty() {
let decision_quote_symbols =
self.strategy.decision_quote_symbols(&StrategyContext {
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(
execution_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( self.ensure_execution_quotes_for_portfolio_times(
execution_date, execution_date,
&portfolio, &portfolio,
@@ -6362,6 +6362,27 @@ impl Strategy for PlatformExprStrategy {
times.into_iter().collect() times.into_iter().collect()
} }
fn decision_quote_symbols(
&mut self,
ctx: &StrategyContext<'_>,
) -> Result<BTreeSet<String>, BacktestError> {
let mut symbols = ctx
.portfolio
.positions()
.keys()
.filter(|symbol| !symbol.trim().is_empty())
.cloned()
.collect::<BTreeSet<_>>();
if self.config.rotation_enabled && !self.config.in_skip_window(ctx.execution_date) {
let plan = self.selection_quote_plan(ctx, 0)?;
symbols.extend(plan.order_symbols);
if plan.requires_intraday_selection_quotes {
symbols.extend(plan.candidate_symbols);
}
}
Ok(symbols)
}
fn open_auction( fn open_auction(
&mut self, &mut self,
ctx: &StrategyContext<'_>, ctx: &StrategyContext<'_>,
+6
View File
@@ -43,6 +43,12 @@ pub trait Strategy {
fn decision_quote_times(&self) -> Vec<NaiveTime> { fn decision_quote_times(&self) -> Vec<NaiveTime> {
Vec::new() Vec::new()
} }
fn decision_quote_symbols(
&mut self,
_ctx: &StrategyContext<'_>,
) -> Result<BTreeSet<String>, BacktestError> {
Ok(BTreeSet::new())
}
fn on_scheduled( fn on_scheduled(
&mut self, &mut self,
_ctx: &StrategyContext<'_>, _ctx: &StrategyContext<'_>,