修复退市生效日结算

This commit is contained in:
boris
2026-07-04 14:12:10 +08:00
parent 3e907d8e43
commit 14810708f0
3 changed files with 60 additions and 1 deletions
+1 -1
View File
@@ -3319,7 +3319,7 @@ where
let Some(instrument) = self.data.instrument(&symbol) else { let Some(instrument) = self.data.instrument(&symbol) else {
continue; continue;
}; };
let should_settle = instrument.is_delisted_before(date) let should_settle = instrument.is_delisted_on_or_before(date)
|| (instrument.status.eq_ignore_ascii_case("delisted") || (instrument.status.eq_ignore_ascii_case("delisted")
&& instrument.delisted_at.is_none() && instrument.delisted_at.is_none()
&& self.data.market(date, &symbol).is_none()); && self.data.market(date, &symbol).is_none());
+5
View File
@@ -40,6 +40,11 @@ impl Instrument {
.is_some_and(|delisted_at| delisted_at < date) .is_some_and(|delisted_at| delisted_at < date)
} }
pub fn is_delisted_on_or_before(&self, date: NaiveDate) -> bool {
self.delisted_at
.is_some_and(|delisted_at| delisted_at <= date)
}
pub fn is_active_on(&self, date: NaiveDate) -> bool { pub fn is_active_on(&self, date: NaiveDate) -> bool {
self.listed_at.is_none_or(|listed_at| listed_at <= date) self.listed_at.is_none_or(|listed_at| listed_at <= date)
&& !self.is_delisted_before(date) && !self.is_delisted_before(date)
+54
View File
@@ -114,6 +114,29 @@ fn engine_settles_delisted_position_before_missing_market_snapshot_breaks_run()
lower_limit: 4.5, lower_limit: 4.5,
price_tick: 0.01, price_tick: 0.01,
}, },
DailyMarketSnapshot {
date: delist_date,
symbol: "000002.SZ".to_string(),
timestamp: Some("2025-01-03 10:18:00".to_string()),
day_open: 5.05,
open: 5.05,
high: 5.15,
low: 5.0,
close: 5.05,
last_price: 5.05,
bid1: 5.04,
ask1: 5.06,
prev_close: 5.0,
volume: 110_000,
minute_volume: 110_000,
bid1_volume: 110_000,
ask1_volume: 110_000,
trading_phase: Some("continuous".to_string()),
paused: false,
upper_limit: 5.5,
lower_limit: 4.5,
price_tick: 0.01,
},
DailyMarketSnapshot { DailyMarketSnapshot {
date: date2, date: date2,
symbol: "000002.SZ".to_string(), symbol: "000002.SZ".to_string(),
@@ -159,6 +182,16 @@ fn engine_settles_delisted_position_before_missing_market_snapshot_breaks_run()
effective_turnover_ratio: Some(1.0), effective_turnover_ratio: Some(1.0),
extra_factors: BTreeMap::new(), extra_factors: BTreeMap::new(),
}, },
DailyFactorSnapshot {
date: delist_date,
symbol: "000002.SZ".to_string(),
market_cap_bn: 30.5,
free_float_cap_bn: 28.5,
pe_ttm: 10.0,
turnover_ratio: Some(1.0),
effective_turnover_ratio: Some(1.0),
extra_factors: BTreeMap::new(),
},
DailyFactorSnapshot { DailyFactorSnapshot {
date: date2, date: date2,
symbol: "000002.SZ".to_string(), symbol: "000002.SZ".to_string(),
@@ -197,6 +230,19 @@ fn engine_settles_delisted_position_before_missing_market_snapshot_breaks_run()
is_one_yuan: false, is_one_yuan: false,
risk_level_code: None, risk_level_code: None,
}, },
CandidateEligibility {
date: delist_date,
symbol: "000002.SZ".to_string(),
is_st: false,
is_star_st: false,
is_new_listing: false,
is_paused: false,
allow_buy: true,
allow_sell: true,
is_kcb: false,
is_one_yuan: false,
risk_level_code: None,
},
CandidateEligibility { CandidateEligibility {
date: date2, date: date2,
symbol: "000002.SZ".to_string(), symbol: "000002.SZ".to_string(),
@@ -220,6 +266,14 @@ fn engine_settles_delisted_position_before_missing_market_snapshot_breaks_run()
prev_close: 99.0, prev_close: 99.0,
volume: 1_000_000, volume: 1_000_000,
}, },
BenchmarkSnapshot {
date: delist_date,
benchmark: "000300.SH".to_string(),
open: 100.5,
close: 100.5,
prev_close: 100.0,
volume: 1_050_000,
},
BenchmarkSnapshot { BenchmarkSnapshot {
date: date2, date: date2,
benchmark: "000300.SH".to_string(), benchmark: "000300.SH".to_string(),