共享回测只读数据索引

This commit is contained in:
boris
2026-08-24 19:48:14 +08:00
parent 1c04318ecf
commit 7503dc8517
+76 -24
View File
@@ -1123,29 +1123,29 @@ impl BenchmarkPriceSeries {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct DataSet { pub struct DataSet {
instruments: HashMap<String, Instrument>, instruments: Arc<HashMap<String, Instrument>>,
calendar: TradingCalendar, calendar: Arc<TradingCalendar>,
market_by_date: BTreeMap<NaiveDate, Vec<Arc<DailyMarketSnapshot>>>, market_by_date: Arc<BTreeMap<NaiveDate, Vec<Arc<DailyMarketSnapshot>>>>,
market_symbol_ids_by_date: Arc<BTreeMap<NaiveDate, Vec<u32>>>, market_symbol_ids_by_date: Arc<BTreeMap<NaiveDate, Vec<u32>>>,
factor_by_date: BTreeMap<NaiveDate, Vec<Arc<DailyFactorSnapshot>>>, factor_by_date: Arc<BTreeMap<NaiveDate, Vec<Arc<DailyFactorSnapshot>>>>,
factor_symbol_ids_by_date: Arc<BTreeMap<NaiveDate, Vec<u32>>>, factor_symbol_ids_by_date: Arc<BTreeMap<NaiveDate, Vec<u32>>>,
factor_text_by_date: BTreeMap<NaiveDate, Vec<FactorTextValue>>, factor_text_by_date: Arc<BTreeMap<NaiveDate, Vec<FactorTextValue>>>,
factor_text_index: HashMap<(NaiveDate, String, String), FactorTextValue>, factor_text_index: Arc<HashMap<(NaiveDate, String, String), FactorTextValue>>,
candidate_by_date: BTreeMap<NaiveDate, Vec<Arc<CandidateEligibility>>>, candidate_by_date: Arc<BTreeMap<NaiveDate, Vec<Arc<CandidateEligibility>>>>,
candidate_symbol_ids_by_date: Arc<BTreeMap<NaiveDate, Vec<u32>>>, candidate_symbol_ids_by_date: Arc<BTreeMap<NaiveDate, Vec<u32>>>,
corporate_actions_by_date: BTreeMap<NaiveDate, Vec<CorporateAction>>, corporate_actions_by_date: Arc<BTreeMap<NaiveDate, Vec<CorporateAction>>>,
execution_quotes_by_date: HashMap<NaiveDate, HashMap<String, Vec<IntradayExecutionQuote>>>, execution_quotes_by_date: HashMap<NaiveDate, HashMap<String, Vec<IntradayExecutionQuote>>>,
order_book_depth_index: HashMap<(NaiveDate, String), Vec<IntradayOrderBookDepthLevel>>, order_book_depth_index: Arc<HashMap<(NaiveDate, String), Vec<IntradayOrderBookDepthLevel>>>,
benchmark_by_date: BTreeMap<NaiveDate, BenchmarkSnapshot>, benchmark_by_date: Arc<BTreeMap<NaiveDate, BenchmarkSnapshot>>,
market_series_by_symbol: Arc<AHashMap<String, Arc<SymbolPriceSeries>>>, market_series_by_symbol: Arc<AHashMap<String, Arc<SymbolPriceSeries>>>,
adjusted_close_series_by_symbol: Arc<AHashMap<String, Arc<AdjustedCloseSeries>>>, adjusted_close_series_by_symbol: Arc<AHashMap<String, Arc<AdjustedCloseSeries>>>,
market_series_by_symbol_id: Arc<Vec<Option<Arc<SymbolPriceSeries>>>>, market_series_by_symbol_id: Arc<Vec<Option<Arc<SymbolPriceSeries>>>>,
adjusted_close_series_by_symbol_id: Arc<Vec<Option<Arc<AdjustedCloseSeries>>>>, adjusted_close_series_by_symbol_id: Arc<Vec<Option<Arc<AdjustedCloseSeries>>>>,
benchmark_series_cache: BenchmarkPriceSeries, benchmark_series_cache: Arc<BenchmarkPriceSeries>,
symbol_id_by_code: Arc<AHashMap<String, u32>>, symbol_id_by_code: Arc<AHashMap<String, u32>>,
eligible_universe_by_date: Arc<OnceLock<BTreeMap<NaiveDate, Vec<EligibleUniverseSnapshot>>>>, eligible_universe_by_date: Arc<OnceLock<BTreeMap<NaiveDate, Vec<EligibleUniverseSnapshot>>>>,
benchmark_code: String, benchmark_code: String,
futures_params_by_symbol: HashMap<String, Vec<FuturesTradingParameter>>, futures_params_by_symbol: Arc<HashMap<String, Vec<FuturesTradingParameter>>>,
} }
impl DataSet { impl DataSet {
@@ -1394,29 +1394,29 @@ impl DataSet {
let futures_params_by_symbol = build_futures_params_index(futures_params); let futures_params_by_symbol = build_futures_params_index(futures_params);
Ok(Self { Ok(Self {
instruments, instruments: Arc::new(instruments),
calendar, calendar: Arc::new(calendar),
market_by_date, market_by_date: Arc::new(market_by_date),
market_symbol_ids_by_date: Arc::new(market_symbol_ids_by_date), market_symbol_ids_by_date: Arc::new(market_symbol_ids_by_date),
factor_by_date, factor_by_date: Arc::new(factor_by_date),
factor_symbol_ids_by_date: Arc::new(factor_symbol_ids_by_date), factor_symbol_ids_by_date: Arc::new(factor_symbol_ids_by_date),
factor_text_by_date, factor_text_by_date: Arc::new(factor_text_by_date),
factor_text_index, factor_text_index: Arc::new(factor_text_index),
candidate_by_date, candidate_by_date: Arc::new(candidate_by_date),
candidate_symbol_ids_by_date: Arc::new(candidate_symbol_ids_by_date), candidate_symbol_ids_by_date: Arc::new(candidate_symbol_ids_by_date),
corporate_actions_by_date, corporate_actions_by_date: Arc::new(corporate_actions_by_date),
execution_quotes_by_date, execution_quotes_by_date,
order_book_depth_index, order_book_depth_index: Arc::new(order_book_depth_index),
benchmark_by_date, benchmark_by_date: Arc::new(benchmark_by_date),
market_series_by_symbol: Arc::new(market_series_by_symbol), market_series_by_symbol: Arc::new(market_series_by_symbol),
adjusted_close_series_by_symbol: Arc::new(adjusted_close_series_by_symbol), adjusted_close_series_by_symbol: Arc::new(adjusted_close_series_by_symbol),
market_series_by_symbol_id: Arc::new(market_series_by_symbol_id), market_series_by_symbol_id: Arc::new(market_series_by_symbol_id),
adjusted_close_series_by_symbol_id: Arc::new(adjusted_close_series_by_symbol_id), adjusted_close_series_by_symbol_id: Arc::new(adjusted_close_series_by_symbol_id),
benchmark_series_cache, benchmark_series_cache: Arc::new(benchmark_series_cache),
symbol_id_by_code: Arc::new(symbol_id_by_code), symbol_id_by_code: Arc::new(symbol_id_by_code),
eligible_universe_by_date: Arc::new(OnceLock::new()), eligible_universe_by_date: Arc::new(OnceLock::new()),
benchmark_code, benchmark_code,
futures_params_by_symbol, futures_params_by_symbol: Arc::new(futures_params_by_symbol),
}) })
} }
@@ -3709,6 +3709,58 @@ mod tests {
} }
} }
#[test]
fn dataset_clone_shares_immutable_base_and_isolates_execution_quotes() {
let date = NaiveDate::parse_from_str("2025-01-02", "%Y-%m-%d").unwrap();
let data = DataSet::from_components(
vec![Instrument {
symbol: "000001.SZ".to_string(),
name: "平安银行".to_string(),
board: "SZ".to_string(),
round_lot: 100,
listed_at: None,
delisted_at: None,
status: "active".to_string(),
}],
vec![market_row("2025-01-02", 10.0, 1_000_000)],
Vec::new(),
Vec::new(),
vec![benchmark_row("2025-01-02", 12.0)],
)
.unwrap();
let mut run_data = data.clone();
assert!(Arc::ptr_eq(&data.instruments, &run_data.instruments));
assert!(Arc::ptr_eq(&data.market_by_date, &run_data.market_by_date));
assert!(Arc::ptr_eq(&data.factor_by_date, &run_data.factor_by_date));
assert!(Arc::ptr_eq(
&data.candidate_by_date,
&run_data.candidate_by_date
));
assert!(Arc::ptr_eq(
&data.benchmark_by_date,
&run_data.benchmark_by_date
));
run_data.add_execution_quotes(vec![IntradayExecutionQuote {
date,
timestamp: NaiveDateTime::parse_from_str("2025-01-02 10:18:00", "%Y-%m-%d %H:%M:%S")
.unwrap(),
symbol: "000001.SZ".to_string(),
last_price: 10.01,
bid1: 10.0,
ask1: 10.01,
bid1_volume: 10_000,
ask1_volume: 10_000,
volume_delta: 10_000,
amount_delta: 100_100.0,
trading_phase: Some("continuous".to_string()),
}]);
assert_eq!(data.execution_quote_count(), 0);
assert_eq!(run_data.execution_quote_count(), 1);
}
#[test] #[test]
fn baseline_selection_uses_structured_instrument_dates_and_status_only() { fn baseline_selection_uses_structured_instrument_dates_and_status_only() {
let date = NaiveDate::parse_from_str("2025-01-02", "%Y-%m-%d").unwrap(); let date = NaiveDate::parse_from_str("2025-01-02", "%Y-%m-%d").unwrap();