修复回报上下文与盘前意图并在提交前采用最新完整目标

This commit is contained in:
boris
2026-09-14 06:06:57 +08:00
parent 600808b171
commit 81acc54228
7 changed files with 1366 additions and 63 deletions
+98 -11
View File
@@ -228,6 +228,13 @@ struct RestingOrderOrigin {
accepted_date: NaiveDate,
}
#[derive(Clone, Copy, PartialEq, Eq)]
enum BrokerCallbackPhase {
Normal,
ControlsOnly,
BeforeStrategy,
}
#[derive(Debug, Default)]
struct BrokerExecutionSession {
date: Option<NaiveDate>,
@@ -463,6 +470,7 @@ pub struct BrokerSimulator<C, R> {
runtime_intraday_start_time: Cell<Option<NaiveTime>>,
runtime_intraday_end_time: Cell<Option<NaiveTime>>,
runtime_execution_clock: Cell<Option<NaiveTime>>,
runtime_callback_phase: Cell<BrokerCallbackPhase>,
runtime_algo_schedule: Cell<Option<AlgoExecutionRequest>>,
runtime_unprocessed_algorithm_cash: Cell<FixedMoney>,
runtime_decision_date: Cell<Option<NaiveDate>>,
@@ -510,6 +518,7 @@ impl<C, R> BrokerSimulator<C, R> {
runtime_intraday_start_time: Cell::new(None),
runtime_intraday_end_time: Cell::new(None),
runtime_execution_clock: Cell::new(None),
runtime_callback_phase: Cell::new(BrokerCallbackPhase::Normal),
runtime_algo_schedule: Cell::new(None),
runtime_unprocessed_algorithm_cash: Cell::new(FixedMoney::ZERO),
runtime_decision_date: Cell::new(None),
@@ -561,6 +570,7 @@ impl<C, R> BrokerSimulator<C, R> {
runtime_intraday_start_time: Cell::new(None),
runtime_intraday_end_time: Cell::new(None),
runtime_execution_clock: Cell::new(None),
runtime_callback_phase: Cell::new(BrokerCallbackPhase::Normal),
runtime_algo_schedule: Cell::new(None),
runtime_unprocessed_algorithm_cash: Cell::new(FixedMoney::ZERO),
runtime_decision_date: Cell::new(None),
@@ -1643,17 +1653,21 @@ where
self.deferred_stock_pools.borrow_mut().remove(&contract.pool_id);
}
}
self.process_open_orders(
date,
portfolio,
data,
&mut session.intraday_turnover,
&mut session.execution_cursors,
&mut session.global_execution_cursor,
&mut session.commission_state,
&mut report,
)?;
self.resume_stock_pool_executions(date, portfolio, data, session, &mut report)?;
if self.runtime_callback_phase.get() != BrokerCallbackPhase::ControlsOnly {
self.process_open_orders(
date,
portfolio,
data,
&mut session.intraday_turnover,
&mut session.execution_cursors,
&mut session.global_execution_cursor,
&mut session.commission_state,
&mut report,
)?;
if self.runtime_callback_phase.get() == BrokerCallbackPhase::Normal {
self.resume_stock_pool_executions(date, portfolio, data, session, &mut report)?;
}
}
if !decision.order_intents.is_empty() {
let mut ordered_intents = decision.order_intents.iter().collect::<Vec<_>>();
if self.effective_rebalance_cash_mode() != RebalanceCashMode::PreOpenCash
@@ -1830,6 +1844,50 @@ where
)
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn execute_controls_without_matching(
&self,
date: NaiveDate,
decision_date: NaiveDate,
portfolio: &mut PortfolioState,
data: &DataSet,
decision: &StrategyDecision,
clock: Option<NaiveTime>,
) -> Result<BrokerExecutionReport, BacktestError> {
if decision.rebalance
|| !decision.target_weights.is_empty()
|| !decision.exit_symbols.is_empty()
|| decision.order_intents.iter().any(|intent| {
!matches!(
intent.unwrapped(),
OrderIntent::CancelOrder { .. }
| OrderIntent::CancelSymbol { .. }
| OrderIntent::CancelAll { .. }
| OrderIntent::ModifyOrder { .. }
)
})
{
return Err(BacktestError::Execution(
"non-matching control phase only accepts cancel or modify requests".into(),
));
}
let _guard = RestoreCell(
&self.runtime_callback_phase,
self.runtime_callback_phase
.replace(BrokerCallbackPhase::ControlsOnly),
);
self.execute_between_with_event_dates(
date,
decision_date,
decision_date,
portfolio,
data,
decision,
clock,
clock,
)
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn execute_coarse_at_clock(
&self,
@@ -1861,6 +1919,35 @@ where
)
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn execute_before_strategy_at_clock(
&self,
date: NaiveDate,
decision_date: NaiveDate,
order_created_date: NaiveDate,
decision_total_equity: Option<f64>,
portfolio: &mut PortfolioState,
data: &DataSet,
decision: &StrategyDecision,
clock: Option<NaiveTime>,
) -> Result<BrokerExecutionReport, BacktestError> {
let _guard = RestoreCell(
&self.runtime_callback_phase,
self.runtime_callback_phase
.replace(BrokerCallbackPhase::BeforeStrategy),
);
self.execute_coarse_at_clock(
date,
decision_date,
order_created_date,
decision_total_equity,
portfolio,
data,
decision,
clock,
)
}
pub fn execute_between_with_event_dates(
&self,
date: NaiveDate,