Add rqalpha-style scheduler time rules

This commit is contained in:
boris
2026-04-23 06:34:07 -07:00
parent fae09afb86
commit 5265f82fef
10 changed files with 557 additions and 233 deletions

View File

@@ -6,8 +6,8 @@ use chrono::NaiveDate;
use fidc_core::{
BacktestConfig, BacktestEngine, BenchmarkSnapshot, BrokerSimulator, CandidateEligibility,
ChinaAShareCostModel, ChinaEquityRuleHooks, DailyFactorSnapshot, DailyMarketSnapshot, DataSet,
Instrument, OrderIntent, PriceField, ProcessEventKind, ScheduleRule, ScheduleStage, Strategy,
StrategyContext, StrategyDecision,
Instrument, OrderIntent, PriceField, ProcessEventKind, ScheduleRule, ScheduleStage,
ScheduleTimeRule, Strategy, StrategyContext, StrategyDecision,
};
fn d(year: i32, month: u32, day: u32) -> NaiveDate {
@@ -147,9 +147,14 @@ impl Strategy for ScheduledProbeStrategy {
fn schedule_rules(&self) -> Vec<ScheduleRule> {
vec![
ScheduleRule::daily("daily_auction", ScheduleStage::OpenAuction),
ScheduleRule::weekly_by_weekday("friday_on_day", 5, ScheduleStage::OnDay),
ScheduleRule::monthly("first_trading_day_on_day", 1, ScheduleStage::OnDay),
ScheduleRule::daily("daily_before_trading", ScheduleStage::BeforeTrading)
.with_time_rule(ScheduleTimeRule::before_trading()),
ScheduleRule::daily("daily_market_open", ScheduleStage::OpenAuction)
.with_time_rule(ScheduleTimeRule::market_open(0, 0)),
ScheduleRule::weekly_by_weekday("friday_on_day", 5, ScheduleStage::OnDay)
.with_time_rule(ScheduleTimeRule::physical_time(10, 18)),
ScheduleRule::monthly("first_trading_day_on_day", 1, ScheduleStage::OnDay)
.with_time_rule(ScheduleTimeRule::physical_time(10, 18)),
]
}
@@ -898,24 +903,27 @@ fn engine_runs_scheduled_rules_for_daily_weekly_and_monthly_triggers() {
assert_eq!(
log.borrow().as_slice(),
[
"scheduled:daily_auction:2025-01-30",
"scheduled:daily_before_trading:2025-01-30",
"scheduled:daily_market_open:2025-01-30",
"scheduled:first_trading_day_on_day:2025-01-30",
"scheduled:daily_auction:2025-01-31",
"scheduled:daily_before_trading:2025-01-31",
"scheduled:daily_market_open:2025-01-31",
"scheduled:friday_on_day:2025-01-31",
"scheduled:daily_auction:2025-02-03",
"scheduled:daily_before_trading:2025-02-03",
"scheduled:daily_market_open:2025-02-03",
"scheduled:first_trading_day_on_day:2025-02-03",
]
);
let process_log = process_log.borrow();
assert!(
process_log
.iter()
.any(|item| { item == "PreScheduled:scheduled:daily_auction:open_auction:pre" })
process_log.iter().any(|item| {
item == "PreScheduled:scheduled:daily_before_trading:before_trading:pre"
})
);
assert!(
process_log
.iter()
.any(|item| { item == "PostScheduled:scheduled:daily_auction:open_auction:post" })
.any(|item| { item == "PostScheduled:scheduled:daily_market_open:open_auction:post" })
);
assert!(
process_log
@@ -1154,9 +1162,9 @@ fn engine_dispatches_process_events_to_external_bus_listeners() {
let external_log = external_log.borrow();
assert!(
external_log
.iter()
.any(|item| { item == "PreScheduled:scheduled:daily_auction:open_auction:pre" })
external_log.iter().any(|item| {
item == "PreScheduled:scheduled:daily_before_trading:before_trading:pre"
})
);
assert!(
external_log

View File

@@ -317,7 +317,10 @@ fn broker_executes_target_shares_like_order_to() {
)
.expect("broker execution");
assert_eq!(portfolio.position("000002.SZ").map(|pos| pos.quantity), Some(200));
assert_eq!(
portfolio.position("000002.SZ").map(|pos| pos.quantity),
Some(200)
);
assert_eq!(report.fill_events.len(), 1);
assert_eq!(report.fill_events[0].side, fidc_core::OrderSide::Sell);
assert_eq!(report.fill_events[0].quantity, 100);
@@ -500,7 +503,13 @@ fn broker_executes_target_portfolio_smart_with_custom_prices() {
assert_eq!(report.fill_events[1].symbol, "000002.SZ");
assert_eq!(report.fill_events[1].side, fidc_core::OrderSide::Buy);
assert_eq!(report.fill_events[1].quantity, 100);
assert_eq!(portfolio.position("000001.SZ").map(|pos| pos.quantity).unwrap_or(0), 0);
assert_eq!(
portfolio
.position("000001.SZ")
.map(|pos| pos.quantity)
.unwrap_or(0),
0
);
assert_eq!(
portfolio.position("000002.SZ").map(|pos| pos.quantity),
Some(100)