跳过无业务分钟回调

This commit is contained in:
boris
2026-08-25 04:02:33 +08:00
parent 85c9d03b99
commit 81d70f18b3
6 changed files with 154 additions and 21 deletions
+82
View File
@@ -637,6 +637,7 @@ struct MinuteProbeStrategy {
seen_ticks: Rc<RefCell<Vec<String>>>,
scheduled_count: Rc<RefCell<usize>>,
subscribe_symbols: BTreeSet<String>,
minute_callbacks: bool,
ordered: bool,
}
@@ -812,6 +813,10 @@ impl Strategy for MinuteProbeStrategy {
"minute-probe"
}
fn requires_minute_callbacks(&self) -> bool {
self.minute_callbacks
}
fn schedule_rules(&self) -> Vec<ScheduleRule> {
vec![
ScheduleRule::daily("minute_barrier", ScheduleStage::Minute)
@@ -2066,6 +2071,7 @@ fn engine_runs_minute_hooks_and_executes_minute_orders() {
seen_ticks: seen_ticks.clone(),
scheduled_count: scheduled_count.clone(),
subscribe_symbols: BTreeSet::from(["000001.SZ".to_string(), "000002.SZ".to_string()]),
minute_callbacks: true,
ordered: false,
};
let broker = BrokerSimulator::new_with_execution_price(
@@ -2143,6 +2149,82 @@ fn engine_runs_minute_hooks_and_executes_minute_orders() {
);
}
#[test]
fn engine_skips_empty_platform_style_minute_callbacks_between_schedule_times() {
let date = d(2025, 1, 2);
let mut data = single_day_anchor_data(date);
data.add_execution_quotes(vec![
IntradayExecutionQuote {
date,
symbol: "000001.SZ".to_string(),
timestamp: dt(2025, 1, 2, 10, 18, 0),
last_price: 10.2,
bid1: 10.1,
ask1: 10.2,
bid1_volume: 1_000,
ask1_volume: 1_000,
volume_delta: 1_000,
amount_delta: 10_200.0,
trading_phase: Some("continuous".to_string()),
},
IntradayExecutionQuote {
date,
symbol: "000001.SZ".to_string(),
timestamp: dt(2025, 1, 2, 10, 19, 0),
last_price: 10.3,
bid1: 10.2,
ask1: 10.3,
bid1_volume: 1_000,
ask1_volume: 1_000,
volume_delta: 1_000,
amount_delta: 10_300.0,
trading_phase: Some("continuous".to_string()),
},
]);
let seen_ticks = Rc::new(RefCell::new(Vec::new()));
let scheduled_count = Rc::new(RefCell::new(0usize));
let strategy = MinuteProbeStrategy {
seen_ticks: seen_ticks.clone(),
scheduled_count: scheduled_count.clone(),
subscribe_symbols: BTreeSet::from(["000001.SZ".to_string()]),
minute_callbacks: false,
ordered: false,
};
let broker = BrokerSimulator::new_with_execution_price(
ChinaAShareCostModel::default(),
ChinaEquityRuleHooks::default(),
PriceField::Last,
);
let mut engine = BacktestEngine::new(
data,
strategy,
broker,
BacktestConfig {
initial_cash: 10_000.0,
benchmark_code: "000300.SH".to_string(),
start_date: Some(date),
end_date: Some(date),
decision_lag_trading_days: 0,
execution_price_field: PriceField::Last,
},
)
.with_execution_quote_loader(|_| Ok(Vec::new()));
let result = engine.run().expect("scheduled-only minute run");
assert!(seen_ticks.borrow().is_empty());
assert_eq!(*scheduled_count.borrow(), 1);
assert!(result.fills.is_empty());
assert_eq!(
result
.process_events
.iter()
.filter(|event| event.kind == ProcessEventKind::PreMinute)
.count(),
1
);
}
#[test]
fn strategy_context_exposes_engine_native_data_helpers() {
let date1 = d(2025, 1, 2);