补齐精度回归样例并允许次日开盘使用真实执行报价

This commit is contained in:
boris
2026-09-19 21:22:12 +08:00
parent 5924e43f3d
commit 175b319d47
3 changed files with 25 additions and 2 deletions
+23 -1
View File
@@ -8735,7 +8735,7 @@ where
| MatchingType::MinuteBestCounterparty
| MatchingType::Vwap
| MatchingType::Twap
) || (self.matching_type == MatchingType::CurrentBarClose
) || (matches!(self.matching_type, MatchingType::CurrentBarClose | MatchingType::NextBarOpen)
&& self.intraday_execution_start_time.is_some())
}
@@ -10349,6 +10349,28 @@ mod tests {
assert!(!audit_a[0].passed); assert!(audit_b[0].passed);
}
#[test]
fn next_open_with_observations_uses_opening_volume_not_daily_totals_or_future_quotes() {
let market=limit_test_snapshot();
let date=market.date;
let open=NaiveTime::from_hms_opt(9,30,0).unwrap();
let quote=|time:NaiveTime,volume| IntradayExecutionQuote { observation_kind:Default::default(),date,
symbol:"000001.SZ".into(),timestamp:date.and_time(time),last_price:market.open,
bid1:0.,ask1:0.,bid1_volume:0,ask1_volume:0,volume_delta:volume,amount_delta:market.open*volume as f64,trading_phase:None };
let quotes=vec![quote(open,400),quote(NaiveTime::from_hms_opt(9,31,0).unwrap(),1_000_000)];
let data=DataSet::from_components_with_actions_and_quotes(vec![limit_test_instrument()],vec![market],vec![],
vec![limit_test_candidate(true,true)],vec![limit_test_benchmark()],vec![],quotes).unwrap();
let broker=BrokerSimulator::new(ChinaAShareCostModel::default(),ChinaEquityRuleHooks)
.with_matching_type(MatchingType::NextBarOpen).with_intraday_execution_start_time(open).with_liquidity_limit(false);
broker.runtime_intraday_end_time.set(Some(open));
broker.runtime_execution_clock.set(Some(open));
let mut account=PortfolioState::new(100_000.);
let report=broker.execute(date,&mut account,&data,&StrategyDecision { order_intents:vec![OrderIntent::Shares {
symbol:"000001.SZ".into(),quantity:1000,reason:"opening capacity regression".into()}],..Default::default() }).unwrap();
assert_eq!(report.fill_events.iter().map(|fill|fill.quantity).sum::<u32>(),100);
assert!(report.fill_events.iter().all(|fill|fill.execution_timestamp==Some(date.and_time(open))));
}
#[test]
fn daily_capacity_requires_a_timed_observation_instead_of_falling_back_to_total_volume() {
let mut snapshot = limit_test_snapshot();
@@ -320,6 +320,7 @@ fn deferred_etf_batch_failure_keeps_both_targets_and_prior_generation_progress()
execute_on: Some(date),
target_value: 1000.into(),
target_weight_bps: 5000,
target_weight_ratio: None,
side: crate::stock_pool_execution::OrderSide::Buy,
max_positions: 2,
rule: Default::default(),
+1 -1
View File
@@ -95,7 +95,7 @@ pub(super) fn valuation(
mod ratio_tests {
use super::*;
fn configuration() -> (Vec<String>, StockPoolDecisionConstraints, BTreeMap<String,i32>) {
let symbols = vec!["000001.SZ".into(),"000002.SZ".into(),"000003.SZ".into()];
let symbols: Vec<String> = vec!["000001.SZ".into(),"000002.SZ".into(),"000003.SZ".into()];
let paused = FrozenStockPoolPosition { trade_date: NaiveDate::from_ymd_opt(2026,9,3).unwrap(), reason:"paused".into(), valuation_price:Decimal::from(10) };
let constraints = StockPoolDecisionConstraints { frozen_positions:BTreeMap::from([(symbols[0].clone(),paused)]),
prior_target_weights:BTreeMap::from([(symbols[0].clone(),3334)]), ..Default::default() };