Add rqalpha-style scheduler primitives
This commit is contained in:
@@ -9,6 +9,7 @@ use crate::events::{AccountEvent, FillEvent, OrderEvent, OrderSide, OrderStatus,
|
||||
use crate::metrics::{BacktestMetrics, compute_backtest_metrics};
|
||||
use crate::portfolio::{CashReceivable, HoldingSummary, PortfolioState};
|
||||
use crate::rules::EquityRuleHooks;
|
||||
use crate::scheduler::{ScheduleRule, ScheduleStage, Scheduler};
|
||||
use crate::strategy::{Strategy, StrategyContext};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
@@ -124,6 +125,8 @@ where
|
||||
F: FnMut(&BacktestDayProgress),
|
||||
{
|
||||
let mut portfolio = PortfolioState::new(self.config.initial_cash);
|
||||
let scheduler_calendar = self.data.calendar().clone();
|
||||
let scheduler = Scheduler::new(&scheduler_calendar);
|
||||
let execution_dates = self
|
||||
.data
|
||||
.calendar()
|
||||
@@ -202,8 +205,17 @@ where
|
||||
data: &self.data,
|
||||
portfolio: &portfolio,
|
||||
};
|
||||
let schedule_rules = self.strategy.schedule_rules();
|
||||
self.strategy.before_trading(&daily_context)?;
|
||||
let auction_decision = self.strategy.open_auction(&daily_context)?;
|
||||
let mut auction_decision = collect_scheduled_decisions(
|
||||
&mut self.strategy,
|
||||
&scheduler,
|
||||
execution_date,
|
||||
ScheduleStage::OpenAuction,
|
||||
&schedule_rules,
|
||||
&daily_context,
|
||||
)?;
|
||||
auction_decision.merge_from(self.strategy.open_auction(&daily_context)?);
|
||||
let mut report = self.broker.execute(
|
||||
execution_date,
|
||||
&mut portfolio,
|
||||
@@ -211,7 +223,7 @@ where
|
||||
&auction_decision,
|
||||
)?;
|
||||
|
||||
let decision = decision_slot
|
||||
let mut decision = decision_slot
|
||||
.map(|(decision_idx, decision_date)| {
|
||||
self.strategy.on_day(&StrategyContext {
|
||||
execution_date,
|
||||
@@ -223,6 +235,20 @@ where
|
||||
})
|
||||
.transpose()?
|
||||
.unwrap_or_default();
|
||||
decision.merge_from(collect_scheduled_decisions(
|
||||
&mut self.strategy,
|
||||
&scheduler,
|
||||
execution_date,
|
||||
ScheduleStage::OnDay,
|
||||
&schedule_rules,
|
||||
&StrategyContext {
|
||||
execution_date,
|
||||
decision_date,
|
||||
decision_index,
|
||||
data: &self.data,
|
||||
portfolio: &portfolio,
|
||||
},
|
||||
)?);
|
||||
|
||||
let intraday_report =
|
||||
self.broker
|
||||
@@ -635,6 +661,21 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_scheduled_decisions<S: Strategy>(
|
||||
strategy: &mut S,
|
||||
scheduler: &Scheduler<'_>,
|
||||
execution_date: NaiveDate,
|
||||
stage: ScheduleStage,
|
||||
rules: &[ScheduleRule],
|
||||
ctx: &StrategyContext<'_>,
|
||||
) -> Result<crate::strategy::StrategyDecision, BacktestError> {
|
||||
let mut combined = crate::strategy::StrategyDecision::default();
|
||||
for rule in scheduler.triggered_rules(execution_date, stage, rules) {
|
||||
combined.merge_from(strategy.on_scheduled(ctx, rule)?);
|
||||
}
|
||||
Ok(combined)
|
||||
}
|
||||
|
||||
mod date_format {
|
||||
use chrono::NaiveDate;
|
||||
use serde::Serializer;
|
||||
|
||||
Reference in New Issue
Block a user