nautilus_testkit/
common.rs1use std::{
17 fs::File,
18 path::{Path, PathBuf},
19 sync::OnceLock,
20};
21
22use nautilus_core::paths::get_test_data_path;
23use nautilus_model::{
24 data::OrderBookDelta,
25 instruments::{InstrumentAny, stubs::equity_aapl_itch},
26};
27use nautilus_serialization::arrow::DecodeFromRecordBatch;
28use parquet::arrow::arrow_reader::ParquetRecordBatchReaderBuilder;
29
30use crate::files::ensure_file_exists_or_download_http;
31
32#[must_use]
38pub fn get_test_data_file_path(path: &str) -> String {
39 get_test_data_path()
40 .join(path)
41 .to_str()
42 .unwrap()
43 .to_string()
44}
45
46#[must_use]
52#[allow(unused_mut)]
53pub fn get_nautilus_test_data_file_path(filename: &str) -> String {
54 let mut path = get_test_data_path().join("nautilus");
55
56 #[cfg(feature = "high-precision")]
57 {
58 path = path.join("128-bit");
59 }
60 #[cfg(not(feature = "high-precision"))]
61 {
62 path = path.join("64-bit");
63 }
64
65 path.join(filename).to_str().unwrap().to_string()
66}
67
68#[must_use]
70pub fn get_test_data_large_checksums_filepath() -> PathBuf {
71 get_test_data_path().join("large").join("checksums.json")
72}
73
74#[must_use]
80pub fn ensure_test_data_exists(filename: &str, url: &str) -> PathBuf {
81 let filepath = get_test_data_path().join("large").join(filename);
82 let checksums_filepath = get_test_data_large_checksums_filepath();
83 ensure_file_exists_or_download_http(&filepath, url, Some(&checksums_filepath), None).unwrap();
84 filepath
85}
86
87#[must_use]
93pub fn ensure_itch_aapl_deltas_parquet() -> PathBuf {
94 ensure_test_data_exists(
95 "itch_AAPL.XNAS_2019-01-30_deltas.parquet",
96 "https://test-data.nautechsystems.io/large/itch_AAPL.XNAS_2019-01-30_deltas.parquet",
97 )
98}
99
100#[must_use]
106pub fn ensure_tardis_deribit_deltas_parquet() -> PathBuf {
107 ensure_test_data_exists(
108 "tardis_BTC-PERPETUAL.DERIBIT_2020-04-01_deltas.parquet",
109 "https://test-data.nautechsystems.io/large/tardis_BTC-PERPETUAL.DERIBIT_2020-04-01_deltas.parquet",
110 )
111}
112
113#[must_use]
115pub fn get_tardis_deribit_book_l2_path() -> PathBuf {
116 get_test_data_path()
117 .join("tardis")
118 .join("deribit_incremental_book_L2_BTC-PERPETUAL.csv")
119}
120
121#[must_use]
123pub fn get_tardis_binance_snapshot5_path() -> PathBuf {
124 get_test_data_path()
125 .join("tardis")
126 .join("binance-futures_book_snapshot_5_BTCUSDT.csv")
127}
128
129#[must_use]
131pub fn get_tardis_binance_snapshot25_path() -> PathBuf {
132 get_test_data_path()
133 .join("tardis")
134 .join("binance-futures_book_snapshot_25_BTCUSDT.csv")
135}
136
137#[must_use]
139pub fn get_tardis_huobi_quotes_path() -> PathBuf {
140 get_test_data_path()
141 .join("tardis")
142 .join("huobi-dm-swap_quotes_BTC-USD.csv")
143}
144
145#[must_use]
147pub fn get_tardis_bitmex_trades_path() -> PathBuf {
148 get_test_data_path()
149 .join("tardis")
150 .join("bitmex_trades_XBTUSD.csv")
151}
152
153#[must_use]
156pub fn itch_aapl_equity() -> InstrumentAny {
157 InstrumentAny::Equity(equity_aapl_itch())
158}
159
160#[must_use]
164pub fn load_itch_aapl_deltas(limit: Option<usize>) -> Vec<OrderBookDelta> {
165 static PATH: OnceLock<PathBuf> = OnceLock::new();
166 let filepath = PATH.get_or_init(ensure_itch_aapl_deltas_parquet);
167 load_deltas_from_parquet(filepath, limit)
168}
169
170#[must_use]
174pub fn load_tardis_deribit_deltas(limit: Option<usize>) -> Vec<OrderBookDelta> {
175 static PATH: OnceLock<PathBuf> = OnceLock::new();
176 let filepath = PATH.get_or_init(ensure_tardis_deribit_deltas_parquet);
177 load_deltas_from_parquet(filepath, limit)
178}
179
180fn load_deltas_from_parquet(filepath: &Path, limit: Option<usize>) -> Vec<OrderBookDelta> {
181 let file = File::open(filepath).unwrap();
182 let mut builder = ParquetRecordBatchReaderBuilder::try_new(file).unwrap();
183 let metadata = builder.schema().metadata().clone();
184
185 if let Some(limit) = limit {
186 builder = builder.with_limit(limit);
187 }
188 let reader = builder.build().unwrap();
189
190 let mut deltas = Vec::new();
191 for batch_result in reader {
192 let batch = batch_result.unwrap();
193 let batch_deltas = OrderBookDelta::decode_batch(&metadata, batch).unwrap();
194 deltas.extend(batch_deltas);
195 }
196 deltas
197}