1use std::time::Duration;
17
18use ahash::AHashMap;
19use nautilus_common::{
20 cache::CacheConfig, enums::Environment, logging::logger::LoggerConfig,
21 msgbus::database::MessageBusConfig,
22};
23use nautilus_core::{UUID4, UnixNanos};
24use nautilus_data::engine::config::DataEngineConfig;
25use nautilus_execution::engine::config::ExecutionEngineConfig;
26use nautilus_model::{
27 data::BarSpecification,
28 enums::{AccountType, BookType, OmsType},
29 identifiers::{ClientId, InstrumentId, TraderId},
30 types::Currency,
31};
32use nautilus_portfolio::config::PortfolioConfig;
33use nautilus_risk::engine::config::RiskEngineConfig;
34use nautilus_system::config::{NautilusKernelConfig, StreamingConfig};
35use ustr::Ustr;
36
37#[derive(Debug, Clone)]
39pub struct BacktestEngineConfig {
40 pub environment: Environment,
42 pub trader_id: TraderId,
44 pub load_state: bool,
46 pub save_state: bool,
48 pub logging: LoggerConfig,
50 pub instance_id: Option<UUID4>,
52 pub timeout_connection: Duration,
54 pub timeout_reconciliation: Duration,
56 pub timeout_portfolio: Duration,
58 pub timeout_disconnection: Duration,
60 pub delay_post_stop: Duration,
62 pub timeout_shutdown: Duration,
64 pub cache: Option<CacheConfig>,
66 pub msgbus: Option<MessageBusConfig>,
68 pub data_engine: Option<DataEngineConfig>,
70 pub risk_engine: Option<RiskEngineConfig>,
72 pub exec_engine: Option<ExecutionEngineConfig>,
74 pub portfolio: Option<PortfolioConfig>,
76 pub streaming: Option<StreamingConfig>,
78 pub bypass_logging: bool,
80 pub run_analysis: bool,
82}
83
84impl BacktestEngineConfig {
85 #[must_use]
86 #[allow(clippy::too_many_arguments)]
87 pub fn new(
88 environment: Environment,
89 trader_id: TraderId,
90 load_state: Option<bool>,
91 save_state: Option<bool>,
92 bypass_logging: Option<bool>,
93 run_analysis: Option<bool>,
94 timeout_connection: Option<u64>,
95 timeout_reconciliation: Option<u64>,
96 timeout_portfolio: Option<u64>,
97 timeout_disconnection: Option<u64>,
98 delay_post_stop: Option<u64>,
99 timeout_shutdown: Option<u64>,
100 logging: Option<LoggerConfig>,
101 instance_id: Option<UUID4>,
102 cache: Option<CacheConfig>,
103 msgbus: Option<MessageBusConfig>,
104 data_engine: Option<DataEngineConfig>,
105 risk_engine: Option<RiskEngineConfig>,
106 exec_engine: Option<ExecutionEngineConfig>,
107 portfolio: Option<PortfolioConfig>,
108 streaming: Option<StreamingConfig>,
109 ) -> Self {
110 Self {
111 environment,
112 trader_id,
113 load_state: load_state.unwrap_or(false),
114 save_state: save_state.unwrap_or(false),
115 logging: logging.unwrap_or_default(),
116 instance_id,
117 timeout_connection: Duration::from_secs(timeout_connection.unwrap_or(60)),
118 timeout_reconciliation: Duration::from_secs(timeout_reconciliation.unwrap_or(30)),
119 timeout_portfolio: Duration::from_secs(timeout_portfolio.unwrap_or(10)),
120 timeout_disconnection: Duration::from_secs(timeout_disconnection.unwrap_or(10)),
121 delay_post_stop: Duration::from_secs(delay_post_stop.unwrap_or(10)),
122 timeout_shutdown: Duration::from_secs(timeout_shutdown.unwrap_or(5)),
123 cache,
124 msgbus,
125 data_engine,
126 risk_engine,
127 exec_engine,
128 portfolio,
129 streaming,
130 bypass_logging: bypass_logging.unwrap_or(false),
131 run_analysis: run_analysis.unwrap_or(true),
132 }
133 }
134}
135
136impl NautilusKernelConfig for BacktestEngineConfig {
137 fn environment(&self) -> Environment {
138 self.environment
139 }
140
141 fn trader_id(&self) -> TraderId {
142 self.trader_id
143 }
144
145 fn load_state(&self) -> bool {
146 self.load_state
147 }
148
149 fn save_state(&self) -> bool {
150 self.save_state
151 }
152
153 fn logging(&self) -> LoggerConfig {
154 self.logging.clone()
155 }
156
157 fn instance_id(&self) -> Option<UUID4> {
158 self.instance_id
159 }
160
161 fn timeout_connection(&self) -> Duration {
162 self.timeout_connection
163 }
164
165 fn timeout_reconciliation(&self) -> Duration {
166 self.timeout_reconciliation
167 }
168
169 fn timeout_portfolio(&self) -> Duration {
170 self.timeout_portfolio
171 }
172
173 fn timeout_disconnection(&self) -> Duration {
174 self.timeout_disconnection
175 }
176
177 fn delay_post_stop(&self) -> Duration {
178 self.delay_post_stop
179 }
180
181 fn timeout_shutdown(&self) -> Duration {
182 self.timeout_shutdown
183 }
184
185 fn cache(&self) -> Option<CacheConfig> {
186 self.cache.clone()
187 }
188
189 fn msgbus(&self) -> Option<MessageBusConfig> {
190 self.msgbus.clone()
191 }
192
193 fn data_engine(&self) -> Option<DataEngineConfig> {
194 self.data_engine.clone()
195 }
196
197 fn risk_engine(&self) -> Option<RiskEngineConfig> {
198 self.risk_engine.clone()
199 }
200
201 fn exec_engine(&self) -> Option<ExecutionEngineConfig> {
202 self.exec_engine.clone()
203 }
204
205 fn portfolio(&self) -> Option<PortfolioConfig> {
206 self.portfolio.clone()
207 }
208
209 fn streaming(&self) -> Option<StreamingConfig> {
210 self.streaming.clone()
211 }
212}
213
214impl Default for BacktestEngineConfig {
215 fn default() -> Self {
216 Self {
217 environment: Environment::Backtest,
218 trader_id: TraderId::default(),
219 load_state: false,
220 save_state: false,
221 logging: LoggerConfig::default(),
222 instance_id: None,
223 timeout_connection: Duration::from_secs(60),
224 timeout_reconciliation: Duration::from_secs(30),
225 timeout_portfolio: Duration::from_secs(10),
226 timeout_disconnection: Duration::from_secs(10),
227 delay_post_stop: Duration::from_secs(10),
228 timeout_shutdown: Duration::from_secs(5),
229 cache: None,
230 msgbus: None,
231 data_engine: None,
232 risk_engine: None,
233 exec_engine: None,
234 portfolio: None,
235 streaming: None,
236 bypass_logging: false,
237 run_analysis: true,
238 }
239 }
240}
241
242#[derive(Debug, Clone)]
244#[allow(dead_code)]
245pub struct BacktestVenueConfig {
246 name: Ustr,
248 oms_type: OmsType,
250 account_type: AccountType,
252 book_type: BookType,
254 starting_balances: Vec<String>,
256 routing: bool,
258 frozen_account: bool,
260 reject_stop_orders: bool,
262 support_gtd_orders: bool,
264 support_contingent_orders: bool,
267 use_position_ids: bool,
269 use_random_ids: bool,
271 use_reduce_only: bool,
273 bar_execution: bool,
275 bar_adaptive_high_low_ordering: bool,
282 trade_execution: bool,
284 base_currency: Option<Currency>,
286 default_leverage: Option<f64>,
288 leverages: Option<AHashMap<Currency, f64>>,
290 price_protection_points: u32,
293}
294
295impl BacktestVenueConfig {
296 #[allow(clippy::too_many_arguments)]
297 #[must_use]
298 pub fn new(
299 name: Ustr,
300 oms_type: OmsType,
301 account_type: AccountType,
302 book_type: BookType,
303 routing: Option<bool>,
304 frozen_account: Option<bool>,
305 reject_stop_orders: Option<bool>,
306 support_gtd_orders: Option<bool>,
307 support_contingent_orders: Option<bool>,
308 use_position_ids: Option<bool>,
309 use_random_ids: Option<bool>,
310 use_reduce_only: Option<bool>,
311 bar_execution: Option<bool>,
312 bar_adaptive_high_low_ordering: Option<bool>,
313 trade_execution: Option<bool>,
314 starting_balances: Vec<String>,
315 base_currency: Option<Currency>,
316 default_leverage: Option<f64>,
317 leverages: Option<AHashMap<Currency, f64>>,
318 price_protection_points: Option<u32>,
319 ) -> Self {
320 Self {
321 name,
322 oms_type,
323 account_type,
324 book_type,
325 routing: routing.unwrap_or(false),
326 frozen_account: frozen_account.unwrap_or(false),
327 reject_stop_orders: reject_stop_orders.unwrap_or(true),
328 support_gtd_orders: support_gtd_orders.unwrap_or(true),
329 support_contingent_orders: support_contingent_orders.unwrap_or(true),
330 use_position_ids: use_position_ids.unwrap_or(true),
331 use_random_ids: use_random_ids.unwrap_or(false),
332 use_reduce_only: use_reduce_only.unwrap_or(true),
333 bar_execution: bar_execution.unwrap_or(true),
334 bar_adaptive_high_low_ordering: bar_adaptive_high_low_ordering.unwrap_or(false),
335 trade_execution: trade_execution.unwrap_or(true),
336 starting_balances,
337 base_currency,
338 default_leverage,
339 leverages,
340 price_protection_points: price_protection_points.unwrap_or(0),
341 }
342 }
343}
344
345#[derive(Debug, Clone)]
347#[allow(dead_code)]
348pub struct BacktestDataConfig {
349 catalog_path: String,
351 catalog_fs_protocol: Option<String>,
353 instrument_id: Option<InstrumentId>,
355 start_time: Option<UnixNanos>,
357 end_time: Option<UnixNanos>,
359 filter_expr: Option<String>,
361 client_id: Option<ClientId>,
363 metadata: Option<AHashMap<String, String>>,
365 bar_spec: Option<BarSpecification>,
367}
368
369impl BacktestDataConfig {
370 #[allow(clippy::too_many_arguments)]
371 #[must_use]
372 pub const fn new(
373 catalog_path: String,
374 catalog_fs_protocol: Option<String>,
375 instrument_id: Option<InstrumentId>,
376 start_time: Option<UnixNanos>,
377 end_time: Option<UnixNanos>,
378 filter_expr: Option<String>,
379 client_id: Option<ClientId>,
380 metadata: Option<AHashMap<String, String>>,
381 bar_spec: Option<BarSpecification>,
382 ) -> Self {
383 Self {
384 catalog_path,
385 catalog_fs_protocol,
386 instrument_id,
387 start_time,
388 end_time,
389 filter_expr,
390 client_id,
391 metadata,
392 bar_spec,
393 }
394 }
395}
396
397#[derive(Debug, Clone)]
400#[allow(dead_code)]
401pub struct BacktestRunConfig {
402 venues: Vec<BacktestVenueConfig>,
404 data: Vec<BacktestDataConfig>,
406 engine: BacktestEngineConfig,
408 chunk_size: Option<usize>,
411 dispose_on_completion: bool,
415 start: Option<UnixNanos>,
418 end: Option<UnixNanos>,
421}
422
423impl BacktestRunConfig {
424 #[must_use]
425 pub fn new(
426 venues: Vec<BacktestVenueConfig>,
427 data: Vec<BacktestDataConfig>,
428 engine: BacktestEngineConfig,
429 chunk_size: Option<usize>,
430 dispose_on_completion: Option<bool>,
431 start: Option<UnixNanos>,
432 end: Option<UnixNanos>,
433 ) -> Self {
434 Self {
435 venues,
436 data,
437 engine,
438 chunk_size,
439 dispose_on_completion: dispose_on_completion.unwrap_or(true),
440 start,
441 end,
442 }
443 }
444}