修正退市持仓虚假现金兑付

This commit is contained in:
boris
2026-07-15 20:48:17 +08:00
parent d63ac73903
commit e7d1c875fd
3 changed files with 50 additions and 98 deletions
+20 -11
View File
@@ -42,7 +42,7 @@ impl Strategy for BuyThenHoldStrategy {
}
#[test]
fn engine_settles_delisted_position_before_missing_market_snapshot_breaks_run() {
fn engine_keeps_unresolved_delisted_position_without_fabricating_a_fill() {
let date1 = d(2025, 1, 2);
let delist_date = d(2025, 1, 3);
let date2 = d(2025, 1, 6);
@@ -306,24 +306,33 @@ fn engine_settles_delisted_position_before_missing_market_snapshot_breaks_run()
);
let result = engine.run().expect("backtest succeeds");
assert_eq!(result.fills.len(), 2);
assert_eq!(result.fills.len(), 1);
assert!(
result
.fills
.iter()
.any(|fill| fill.reason.contains("delisted_cash_settlement")
&& fill.symbol == "000001.SZ")
);
assert!(
result
.holdings_summary
.iter()
.all(|holding| holding.symbol != "000001.SZ")
.all(|fill| !fill.reason.contains("delisted_cash_settlement"))
);
let unresolved = result
.holdings_summary
.iter()
.find(|holding| holding.symbol == "000001.SZ")
.expect("unresolved delisted holding remains auditable");
assert_eq!(unresolved.quantity, 900);
assert_eq!(unresolved.last_price, 0.0);
assert_eq!(unresolved.market_value, 0.0);
assert!(result.equity_curve.iter().any(|point| {
point
.notes
.contains("unresolved_delisted_position symbol=000001.SZ")
&& point.notes.contains("settlement_action=missing")
&& point.notes.contains("valuation_policy=zero")
&& point.notes.contains("no_order=true")
}));
}
#[test]
fn engine_applies_successor_conversion_before_delisted_cash_settlement() {
fn engine_applies_successor_conversion_before_unresolved_delisting_audit() {
let date1 = d(2025, 1, 2);
let date2 = d(2025, 1, 3);
let data = DataSet::from_components_with_actions(