Expose process event context to strategy runtime
This commit is contained in:
@@ -232,31 +232,42 @@ where
|
||||
.map(|decision_idx| (decision_idx, execution_dates[decision_idx]));
|
||||
let (decision_index, decision_date) =
|
||||
decision_slot.unwrap_or((execution_idx, execution_date));
|
||||
let mut process_events = Vec::new();
|
||||
let pre_open_orders = self.broker.open_order_views();
|
||||
let daily_context = StrategyContext {
|
||||
let schedule_rules = self.strategy.schedule_rules();
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&pre_open_orders,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::PreBeforeTrading,
|
||||
"before_trading:pre",
|
||||
)?;
|
||||
self.strategy.before_trading(&StrategyContext {
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
data: &self.data,
|
||||
portfolio: &portfolio,
|
||||
open_orders: &pre_open_orders,
|
||||
};
|
||||
let schedule_rules = self.strategy.schedule_rules();
|
||||
let mut process_events = Vec::new();
|
||||
process_events: &process_events,
|
||||
active_process_event: None,
|
||||
})?;
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&daily_context,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::PreBeforeTrading,
|
||||
"before_trading:pre",
|
||||
)?;
|
||||
self.strategy.before_trading(&daily_context)?;
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&daily_context,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&pre_open_orders,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::BeforeTrading,
|
||||
@@ -265,7 +276,12 @@ where
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&daily_context,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&pre_open_orders,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::PostBeforeTrading,
|
||||
@@ -274,7 +290,12 @@ where
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&daily_context,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&pre_open_orders,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::PreOpenAuction,
|
||||
@@ -286,15 +307,33 @@ where
|
||||
execution_date,
|
||||
ScheduleStage::OpenAuction,
|
||||
&schedule_rules,
|
||||
&daily_context,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&pre_open_orders,
|
||||
&mut process_events,
|
||||
&mut self.process_event_bus,
|
||||
)?;
|
||||
auction_decision.merge_from(self.strategy.open_auction(&daily_context)?);
|
||||
auction_decision.merge_from(self.strategy.open_auction(&StrategyContext {
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
data: &self.data,
|
||||
portfolio: &portfolio,
|
||||
open_orders: &pre_open_orders,
|
||||
process_events: &process_events,
|
||||
active_process_event: None,
|
||||
})?);
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&daily_context,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&pre_open_orders,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::OpenAuction,
|
||||
@@ -307,25 +346,27 @@ where
|
||||
&auction_decision,
|
||||
)?;
|
||||
let post_auction_open_orders = self.broker.open_order_views();
|
||||
let post_auction_context = StrategyContext {
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
data: &self.data,
|
||||
portfolio: &portfolio,
|
||||
open_orders: &post_auction_open_orders,
|
||||
};
|
||||
publish_process_events(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&post_auction_context,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&post_auction_open_orders,
|
||||
&mut process_events,
|
||||
&mut report.process_events,
|
||||
)?;
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&post_auction_context,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&post_auction_open_orders,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::PostOpenAuction,
|
||||
@@ -335,7 +376,12 @@ where
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&post_auction_context,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&post_auction_open_orders,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::PreOnDay,
|
||||
@@ -351,6 +397,8 @@ where
|
||||
data: &self.data,
|
||||
portfolio: &portfolio,
|
||||
open_orders: &on_day_open_orders,
|
||||
process_events: &process_events,
|
||||
active_process_event: None,
|
||||
})
|
||||
})
|
||||
.transpose()?
|
||||
@@ -361,29 +409,23 @@ where
|
||||
execution_date,
|
||||
ScheduleStage::OnDay,
|
||||
&schedule_rules,
|
||||
&StrategyContext {
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
data: &self.data,
|
||||
portfolio: &portfolio,
|
||||
open_orders: &on_day_open_orders,
|
||||
},
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&on_day_open_orders,
|
||||
&mut process_events,
|
||||
&mut self.process_event_bus,
|
||||
)?);
|
||||
let on_day_context = StrategyContext {
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
data: &self.data,
|
||||
portfolio: &portfolio,
|
||||
open_orders: &on_day_open_orders,
|
||||
};
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&on_day_context,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&on_day_open_orders,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::OnDay,
|
||||
@@ -394,18 +436,15 @@ where
|
||||
self.broker
|
||||
.execute(execution_date, &mut portfolio, &self.data, &decision)?;
|
||||
let post_intraday_open_orders = self.broker.open_order_views();
|
||||
let post_intraday_context = StrategyContext {
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
data: &self.data,
|
||||
portfolio: &portfolio,
|
||||
open_orders: &post_intraday_open_orders,
|
||||
};
|
||||
publish_process_events(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&post_intraday_context,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&post_intraday_open_orders,
|
||||
&mut process_events,
|
||||
&mut intraday_report.process_events,
|
||||
)?;
|
||||
@@ -419,7 +458,12 @@ where
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&post_intraday_context,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&post_intraday_open_orders,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::PostOnDay,
|
||||
@@ -429,28 +473,39 @@ where
|
||||
portfolio.update_prices(execution_date, &self.data, PriceField::Close)?;
|
||||
|
||||
let post_trade_open_orders = self.broker.open_order_views();
|
||||
let post_trade_context = StrategyContext {
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&post_trade_open_orders,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::PreAfterTrading,
|
||||
"after_trading:pre",
|
||||
)?;
|
||||
self.strategy.after_trading(&StrategyContext {
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
data: &self.data,
|
||||
portfolio: &portfolio,
|
||||
open_orders: &post_trade_open_orders,
|
||||
};
|
||||
process_events: &process_events,
|
||||
active_process_event: None,
|
||||
})?;
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&post_trade_context,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::PreAfterTrading,
|
||||
"after_trading:pre",
|
||||
)?;
|
||||
self.strategy.after_trading(&post_trade_context)?;
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&post_trade_context,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&post_trade_open_orders,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::AfterTrading,
|
||||
@@ -460,7 +515,12 @@ where
|
||||
publish_process_events(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&post_trade_context,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&post_trade_open_orders,
|
||||
&mut process_events,
|
||||
&mut close_report.process_events,
|
||||
)?;
|
||||
@@ -470,18 +530,15 @@ where
|
||||
report.account_events.extend(close_report.account_events);
|
||||
report.diagnostics.extend(close_report.diagnostics);
|
||||
let post_close_open_orders = self.broker.open_order_views();
|
||||
let post_close_context = StrategyContext {
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
data: &self.data,
|
||||
portfolio: &portfolio,
|
||||
open_orders: &post_close_open_orders,
|
||||
};
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&post_close_context,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&post_close_open_orders,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::PostAfterTrading,
|
||||
@@ -490,17 +547,36 @@ where
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&post_close_context,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&post_close_open_orders,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::PreSettlement,
|
||||
"settlement:pre",
|
||||
)?;
|
||||
self.strategy.on_settlement(&post_close_context)?;
|
||||
self.strategy.on_settlement(&StrategyContext {
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
data: &self.data,
|
||||
portfolio: &portfolio,
|
||||
open_orders: &post_close_open_orders,
|
||||
process_events: &process_events,
|
||||
active_process_event: None,
|
||||
})?;
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&post_close_context,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&post_close_open_orders,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::Settlement,
|
||||
@@ -509,7 +585,12 @@ where
|
||||
publish_phase_event(
|
||||
&mut self.strategy,
|
||||
&mut self.process_event_bus,
|
||||
&post_close_context,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
&self.data,
|
||||
&portfolio,
|
||||
&post_close_open_orders,
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::PostSettlement,
|
||||
@@ -1005,7 +1086,11 @@ fn collect_scheduled_decisions<S: Strategy>(
|
||||
execution_date: NaiveDate,
|
||||
stage: ScheduleStage,
|
||||
rules: &[ScheduleRule],
|
||||
ctx: &StrategyContext<'_>,
|
||||
decision_date: NaiveDate,
|
||||
decision_index: usize,
|
||||
data: &crate::data::DataSet,
|
||||
portfolio: &PortfolioState,
|
||||
open_orders: &[crate::strategy::OpenOrderView],
|
||||
process_events: &mut Vec<ProcessEvent>,
|
||||
process_event_bus: &mut ProcessEventBus,
|
||||
) -> Result<crate::strategy::StrategyDecision, BacktestError> {
|
||||
@@ -1014,17 +1099,39 @@ fn collect_scheduled_decisions<S: Strategy>(
|
||||
publish_phase_event(
|
||||
strategy,
|
||||
process_event_bus,
|
||||
ctx,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
data,
|
||||
portfolio,
|
||||
open_orders,
|
||||
process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::PreScheduled,
|
||||
format!("scheduled:{}:{}:pre", rule.name, stage_label(stage)),
|
||||
)?;
|
||||
combined.merge_from(strategy.on_scheduled(ctx, rule)?);
|
||||
combined.merge_from(strategy.on_scheduled(
|
||||
&StrategyContext {
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
data,
|
||||
portfolio,
|
||||
open_orders,
|
||||
process_events: process_events.as_slice(),
|
||||
active_process_event: None,
|
||||
},
|
||||
rule,
|
||||
)?);
|
||||
publish_phase_event(
|
||||
strategy,
|
||||
process_event_bus,
|
||||
ctx,
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
data,
|
||||
portfolio,
|
||||
open_orders,
|
||||
process_events,
|
||||
execution_date,
|
||||
ProcessEventKind::PostScheduled,
|
||||
@@ -1037,7 +1144,12 @@ fn collect_scheduled_decisions<S: Strategy>(
|
||||
fn publish_phase_event<S: Strategy>(
|
||||
strategy: &mut S,
|
||||
process_event_bus: &mut ProcessEventBus,
|
||||
ctx: &StrategyContext<'_>,
|
||||
execution_date: NaiveDate,
|
||||
decision_date: NaiveDate,
|
||||
decision_index: usize,
|
||||
data: &crate::data::DataSet,
|
||||
portfolio: &PortfolioState,
|
||||
open_orders: &[crate::strategy::OpenOrderView],
|
||||
events: &mut Vec<ProcessEvent>,
|
||||
date: NaiveDate,
|
||||
kind: ProcessEventKind,
|
||||
@@ -1052,7 +1164,18 @@ fn publish_phase_event<S: Strategy>(
|
||||
detail: detail.into(),
|
||||
};
|
||||
process_event_bus.publish(&event);
|
||||
strategy.on_process_event(ctx, &event)?;
|
||||
let process_events = events.as_slice();
|
||||
let event_ctx = StrategyContext {
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
data,
|
||||
portfolio,
|
||||
open_orders,
|
||||
process_events,
|
||||
active_process_event: Some(&event),
|
||||
};
|
||||
strategy.on_process_event(&event_ctx, &event)?;
|
||||
events.push(event);
|
||||
Ok(())
|
||||
}
|
||||
@@ -1060,13 +1183,29 @@ fn publish_phase_event<S: Strategy>(
|
||||
fn publish_process_events<S: Strategy>(
|
||||
strategy: &mut S,
|
||||
process_event_bus: &mut ProcessEventBus,
|
||||
ctx: &StrategyContext<'_>,
|
||||
execution_date: NaiveDate,
|
||||
decision_date: NaiveDate,
|
||||
decision_index: usize,
|
||||
data: &crate::data::DataSet,
|
||||
portfolio: &PortfolioState,
|
||||
open_orders: &[crate::strategy::OpenOrderView],
|
||||
target: &mut Vec<ProcessEvent>,
|
||||
incoming: &mut Vec<ProcessEvent>,
|
||||
) -> Result<(), BacktestError> {
|
||||
for event in incoming.drain(..) {
|
||||
process_event_bus.publish(&event);
|
||||
strategy.on_process_event(ctx, &event)?;
|
||||
let process_events = target.as_slice();
|
||||
let event_ctx = StrategyContext {
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
data,
|
||||
portfolio,
|
||||
open_orders,
|
||||
process_events,
|
||||
active_process_event: Some(&event),
|
||||
};
|
||||
strategy.on_process_event(&event_ctx, &event)?;
|
||||
target.push(event);
|
||||
}
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user