1use nautilus_common::{actor::DataActorConfig, python::config_error_to_pyvalue_err};
19use nautilus_core::from_pydict;
20use nautilus_model::{
21 data::BarType,
22 enums::{BookType, OrderType, TimeInForce, TrailingOffsetType, TriggerType},
23 identifiers::{ActorId, ClientId, InstrumentId, StrategyId},
24 types::Quantity,
25};
26use nautilus_trading::strategy::StrategyConfig;
27use pyo3::{prelude::*, types::PyDict};
28use rust_decimal::Decimal;
29
30use crate::{DataTesterConfig, ExecTesterConfig};
31
32#[pymethods]
33#[pyo3_stub_gen::derive::gen_stub_pymethods]
34impl DataTesterConfig {
35 #[new]
37 #[allow(
38 clippy::needless_pass_by_value,
39 reason = "PyO3 #[new] requires owned params"
40 )]
41 #[expect(clippy::too_many_arguments)]
42 #[pyo3(signature = (
43 actor_id = None,
44 client_id = None,
45 instrument_ids = None,
46 bar_types = None,
47 subscribe_book_deltas = None,
48 subscribe_book_depth = None,
49 subscribe_book_at_interval = None,
50 subscribe_quotes = None,
51 subscribe_trades = None,
52 subscribe_mark_prices = None,
53 subscribe_index_prices = None,
54 subscribe_funding_rates = None,
55 subscribe_bars = None,
56 subscribe_instrument = None,
57 subscribe_instrument_status = None,
58 subscribe_instrument_close = None,
59 subscribe_option_greeks = None,
60 can_unsubscribe = None,
61 request_instruments = None,
62 request_quotes = None,
63 request_trades = None,
64 request_bars = None,
65 request_book_snapshot = None,
66 request_book_deltas = None,
67 request_funding_rates = None,
68 book_depth = None,
69 book_interval_ms = None,
70 book_levels_to_print = None,
71 manage_book = None,
72 log_data = None,
73 stats_interval_secs = None,
74 log_events = None,
75 log_commands = None,
76 ))]
77 fn py_new(
78 actor_id: Option<ActorId>,
79 client_id: Option<ClientId>,
80 instrument_ids: Option<Vec<InstrumentId>>,
81 bar_types: Option<Vec<BarType>>,
82 subscribe_book_deltas: Option<bool>,
83 subscribe_book_depth: Option<bool>,
84 subscribe_book_at_interval: Option<bool>,
85 subscribe_quotes: Option<bool>,
86 subscribe_trades: Option<bool>,
87 subscribe_mark_prices: Option<bool>,
88 subscribe_index_prices: Option<bool>,
89 subscribe_funding_rates: Option<bool>,
90 subscribe_bars: Option<bool>,
91 subscribe_instrument: Option<bool>,
92 subscribe_instrument_status: Option<bool>,
93 subscribe_instrument_close: Option<bool>,
94 subscribe_option_greeks: Option<bool>,
95 can_unsubscribe: Option<bool>,
96 request_instruments: Option<bool>,
97 request_quotes: Option<bool>,
98 request_trades: Option<bool>,
99 request_bars: Option<bool>,
100 request_book_snapshot: Option<bool>,
101 request_book_deltas: Option<bool>,
102 request_funding_rates: Option<bool>,
103 book_depth: Option<usize>,
104 book_interval_ms: Option<usize>,
105 book_levels_to_print: Option<usize>,
106 manage_book: Option<bool>,
107 log_data: Option<bool>,
108 stats_interval_secs: Option<u64>,
109 log_events: Option<bool>,
110 log_commands: Option<bool>,
111 ) -> PyResult<Self> {
112 let defaults = Self::default();
113 let config = Self {
114 base: DataActorConfig {
115 actor_id,
116 log_events: log_events.unwrap_or(defaults.base.log_events),
117 log_commands: log_commands.unwrap_or(defaults.base.log_commands),
118 },
119 instrument_ids: instrument_ids.unwrap_or(defaults.instrument_ids),
120 client_id,
121 bar_types,
122 subscribe_book_deltas: subscribe_book_deltas.unwrap_or(defaults.subscribe_book_deltas),
123 subscribe_book_depth: subscribe_book_depth.unwrap_or(defaults.subscribe_book_depth),
124 subscribe_book_at_interval: subscribe_book_at_interval
125 .unwrap_or(defaults.subscribe_book_at_interval),
126 subscribe_quotes: subscribe_quotes.unwrap_or(defaults.subscribe_quotes),
127 subscribe_trades: subscribe_trades.unwrap_or(defaults.subscribe_trades),
128 subscribe_mark_prices: subscribe_mark_prices.unwrap_or(defaults.subscribe_mark_prices),
129 subscribe_index_prices: subscribe_index_prices
130 .unwrap_or(defaults.subscribe_index_prices),
131 subscribe_funding_rates: subscribe_funding_rates
132 .unwrap_or(defaults.subscribe_funding_rates),
133 subscribe_bars: subscribe_bars.unwrap_or(defaults.subscribe_bars),
134 subscribe_instrument: subscribe_instrument.unwrap_or(defaults.subscribe_instrument),
135 subscribe_instrument_status: subscribe_instrument_status
136 .unwrap_or(defaults.subscribe_instrument_status),
137 subscribe_instrument_close: subscribe_instrument_close
138 .unwrap_or(defaults.subscribe_instrument_close),
139 subscribe_option_greeks: subscribe_option_greeks
140 .unwrap_or(defaults.subscribe_option_greeks),
141 subscribe_params: defaults.subscribe_params,
142 request_params: defaults.request_params,
143 can_unsubscribe: can_unsubscribe.unwrap_or(defaults.can_unsubscribe),
144 request_instruments: request_instruments.unwrap_or(defaults.request_instruments),
145 request_quotes: request_quotes.unwrap_or(defaults.request_quotes),
146 request_trades: request_trades.unwrap_or(defaults.request_trades),
147 request_bars: request_bars.unwrap_or(defaults.request_bars),
148 request_book_snapshot: request_book_snapshot.unwrap_or(defaults.request_book_snapshot),
149 request_book_deltas: request_book_deltas.unwrap_or(defaults.request_book_deltas),
150 request_funding_rates: request_funding_rates.unwrap_or(defaults.request_funding_rates),
151 book_type: defaults.book_type,
152 book_depth,
153 book_interval_ms: book_interval_ms.unwrap_or(defaults.book_interval_ms),
154 book_levels_to_print: book_levels_to_print.unwrap_or(defaults.book_levels_to_print),
155 manage_book: manage_book.unwrap_or(defaults.manage_book),
156 log_data: log_data.unwrap_or(defaults.log_data),
157 stats_interval_secs: stats_interval_secs.unwrap_or(defaults.stats_interval_secs),
158 };
159 config.validate().map_err(config_error_to_pyvalue_err)?;
160 Ok(config)
161 }
162
163 #[getter]
164 #[pyo3(name = "actor_id")]
165 const fn py_actor_id(&self) -> Option<ActorId> {
166 self.base.actor_id
167 }
168
169 #[getter]
170 #[pyo3(name = "client_id")]
171 const fn py_client_id(&self) -> Option<ClientId> {
172 self.client_id
173 }
174
175 #[getter]
176 #[pyo3(name = "instrument_ids")]
177 fn py_instrument_ids(&self) -> Vec<InstrumentId> {
178 self.instrument_ids.clone()
179 }
180
181 #[getter]
182 #[pyo3(name = "bar_types")]
183 fn py_bar_types(&self) -> Option<Vec<BarType>> {
184 self.bar_types.clone()
185 }
186
187 #[getter]
188 #[pyo3(name = "subscribe_book_deltas")]
189 const fn py_subscribe_book_deltas(&self) -> bool {
190 self.subscribe_book_deltas
191 }
192
193 #[getter]
194 #[pyo3(name = "subscribe_book_depth")]
195 const fn py_subscribe_book_depth(&self) -> bool {
196 self.subscribe_book_depth
197 }
198
199 #[getter]
200 #[pyo3(name = "subscribe_book_at_interval")]
201 const fn py_subscribe_book_at_interval(&self) -> bool {
202 self.subscribe_book_at_interval
203 }
204
205 #[getter]
206 #[pyo3(name = "subscribe_quotes")]
207 const fn py_subscribe_quotes(&self) -> bool {
208 self.subscribe_quotes
209 }
210
211 #[getter]
212 #[pyo3(name = "subscribe_trades")]
213 const fn py_subscribe_trades(&self) -> bool {
214 self.subscribe_trades
215 }
216
217 #[getter]
218 #[pyo3(name = "subscribe_mark_prices")]
219 const fn py_subscribe_mark_prices(&self) -> bool {
220 self.subscribe_mark_prices
221 }
222
223 #[getter]
224 #[pyo3(name = "subscribe_index_prices")]
225 const fn py_subscribe_index_prices(&self) -> bool {
226 self.subscribe_index_prices
227 }
228
229 #[getter]
230 #[pyo3(name = "subscribe_funding_rates")]
231 const fn py_subscribe_funding_rates(&self) -> bool {
232 self.subscribe_funding_rates
233 }
234
235 #[getter]
236 #[pyo3(name = "subscribe_bars")]
237 const fn py_subscribe_bars(&self) -> bool {
238 self.subscribe_bars
239 }
240
241 #[getter]
242 #[pyo3(name = "subscribe_instrument")]
243 const fn py_subscribe_instrument(&self) -> bool {
244 self.subscribe_instrument
245 }
246
247 #[getter]
248 #[pyo3(name = "subscribe_instrument_status")]
249 const fn py_subscribe_instrument_status(&self) -> bool {
250 self.subscribe_instrument_status
251 }
252
253 #[getter]
254 #[pyo3(name = "subscribe_instrument_close")]
255 const fn py_subscribe_instrument_close(&self) -> bool {
256 self.subscribe_instrument_close
257 }
258
259 #[getter]
260 #[pyo3(name = "subscribe_option_greeks")]
261 const fn py_subscribe_option_greeks(&self) -> bool {
262 self.subscribe_option_greeks
263 }
264
265 #[getter]
266 #[pyo3(name = "can_unsubscribe")]
267 const fn py_can_unsubscribe(&self) -> bool {
268 self.can_unsubscribe
269 }
270
271 #[getter]
272 #[pyo3(name = "request_instruments")]
273 const fn py_request_instruments(&self) -> bool {
274 self.request_instruments
275 }
276
277 #[getter]
278 #[pyo3(name = "request_quotes")]
279 const fn py_request_quotes(&self) -> bool {
280 self.request_quotes
281 }
282
283 #[getter]
284 #[pyo3(name = "request_trades")]
285 const fn py_request_trades(&self) -> bool {
286 self.request_trades
287 }
288
289 #[getter]
290 #[pyo3(name = "request_bars")]
291 const fn py_request_bars(&self) -> bool {
292 self.request_bars
293 }
294
295 #[getter]
296 #[pyo3(name = "request_book_snapshot")]
297 const fn py_request_book_snapshot(&self) -> bool {
298 self.request_book_snapshot
299 }
300
301 #[getter]
302 #[pyo3(name = "request_book_deltas")]
303 const fn py_request_book_deltas(&self) -> bool {
304 self.request_book_deltas
305 }
306
307 #[getter]
308 #[pyo3(name = "request_funding_rates")]
309 const fn py_request_funding_rates(&self) -> bool {
310 self.request_funding_rates
311 }
312
313 #[getter]
314 #[pyo3(name = "book_depth")]
315 const fn py_book_depth(&self) -> Option<usize> {
316 self.book_depth
317 }
318
319 #[getter]
320 #[pyo3(name = "book_interval_ms")]
321 const fn py_book_interval_ms(&self) -> usize {
322 self.book_interval_ms
323 }
324
325 #[getter]
326 #[pyo3(name = "book_levels_to_print")]
327 const fn py_book_levels_to_print(&self) -> usize {
328 self.book_levels_to_print
329 }
330
331 #[getter]
332 #[pyo3(name = "manage_book")]
333 const fn py_manage_book(&self) -> bool {
334 self.manage_book
335 }
336
337 #[getter]
338 #[pyo3(name = "log_data")]
339 const fn py_log_data(&self) -> bool {
340 self.log_data
341 }
342
343 #[getter]
344 #[pyo3(name = "stats_interval_secs")]
345 const fn py_stats_interval_secs(&self) -> u64 {
346 self.stats_interval_secs
347 }
348
349 #[getter]
350 #[pyo3(name = "log_events")]
351 const fn py_log_events(&self) -> bool {
352 self.base.log_events
353 }
354
355 #[getter]
356 #[pyo3(name = "log_commands")]
357 const fn py_log_commands(&self) -> bool {
358 self.base.log_commands
359 }
360
361 fn __repr__(&self) -> String {
362 format!("{self:?}")
363 }
364}
365
366#[pymethods]
367#[pyo3_stub_gen::derive::gen_stub_pymethods]
368impl ExecTesterConfig {
369 #[new]
371 #[allow(
372 clippy::needless_pass_by_value,
373 reason = "PyO3 #[new] requires owned params"
374 )]
375 #[expect(clippy::too_many_arguments)]
376 #[pyo3(signature = (
377 strategy_id = None,
378 order_id_tag = None,
379 use_hyphens_in_client_order_ids = None,
380 use_uuid_client_order_ids = None,
381 external_order_claims = None,
382 instrument_id = None,
383 client_id = None,
384 order_qty = None,
385 order_display_qty = None,
386 order_expire_time_delta_mins = None,
387 order_params = None,
388 subscribe_book = None,
389 subscribe_quotes = None,
390 subscribe_trades = None,
391 book_type = None,
392 book_depth = None,
393 book_interval_ms = None,
394 book_levels_to_print = None,
395 open_position_on_start_qty = None,
396 open_position_on_first_quote = None,
397 open_position_time_in_force = None,
398 enable_limit_buys = None,
399 enable_limit_sells = None,
400 enable_stop_buys = None,
401 enable_stop_sells = None,
402 tob_offset_ticks = None,
403 limit_time_in_force = None,
404 stop_order_type = None,
405 stop_offset_ticks = None,
406 stop_limit_offset_ticks = None,
407 stop_trigger_type = None,
408 stop_time_in_force = None,
409 trailing_offset = None,
410 trailing_offset_type = None,
411 enable_brackets = None,
412 batch_submit_limit_pair = None,
413 bracket_entry_order_type = None,
414 bracket_offset_ticks = None,
415 modify_orders_to_maintain_tob_offset = None,
416 modify_stop_orders_to_maintain_offset = None,
417 cancel_replace_orders_to_maintain_tob_offset = None,
418 cancel_replace_stop_orders_to_maintain_offset = None,
419 trigger_limit_order_maintenance_once = None,
420 use_post_only = None,
421 limit_aggressive = None,
422 use_quote_quantity = None,
423 emulation_trigger = None,
424 use_individual_cancels_on_stop = None,
425 cancel_orders_on_stop = None,
426 close_positions_on_stop = None,
427 close_positions_qty_precision = None,
428 close_positions_time_in_force = None,
429 reduce_only_on_stop = None,
430 use_batch_cancel_on_stop = None,
431 dry_run = None,
432 log_data = None,
433 test_reject_post_only = None,
434 test_reject_reduce_only = None,
435 test_modify_rejected = None,
436 can_unsubscribe = None,
437 clamp_to_instrument_price_range = None,
438 log_events = None,
439 log_commands = None,
440 ))]
441 fn py_new(
442 py: Python<'_>,
443 strategy_id: Option<StrategyId>,
444 order_id_tag: Option<String>,
445 use_hyphens_in_client_order_ids: Option<bool>,
446 use_uuid_client_order_ids: Option<bool>,
447 external_order_claims: Option<Vec<InstrumentId>>,
448 instrument_id: Option<InstrumentId>,
449 client_id: Option<ClientId>,
450 order_qty: Option<Quantity>,
451 order_display_qty: Option<Quantity>,
452 order_expire_time_delta_mins: Option<u64>,
453 order_params: Option<Py<PyDict>>,
454 subscribe_book: Option<bool>,
455 subscribe_quotes: Option<bool>,
456 subscribe_trades: Option<bool>,
457 book_type: Option<BookType>,
458 book_depth: Option<usize>,
459 book_interval_ms: Option<usize>,
460 book_levels_to_print: Option<usize>,
461 open_position_on_start_qty: Option<Decimal>,
462 open_position_on_first_quote: Option<bool>,
463 open_position_time_in_force: Option<TimeInForce>,
464 enable_limit_buys: Option<bool>,
465 enable_limit_sells: Option<bool>,
466 enable_stop_buys: Option<bool>,
467 enable_stop_sells: Option<bool>,
468 tob_offset_ticks: Option<u64>,
469 limit_time_in_force: Option<TimeInForce>,
470 stop_order_type: Option<OrderType>,
471 stop_offset_ticks: Option<u64>,
472 stop_limit_offset_ticks: Option<u64>,
473 stop_trigger_type: Option<TriggerType>,
474 stop_time_in_force: Option<TimeInForce>,
475 trailing_offset: Option<Decimal>,
476 trailing_offset_type: Option<TrailingOffsetType>,
477 enable_brackets: Option<bool>,
478 batch_submit_limit_pair: Option<bool>,
479 bracket_entry_order_type: Option<OrderType>,
480 bracket_offset_ticks: Option<u64>,
481 modify_orders_to_maintain_tob_offset: Option<bool>,
482 modify_stop_orders_to_maintain_offset: Option<bool>,
483 cancel_replace_orders_to_maintain_tob_offset: Option<bool>,
484 cancel_replace_stop_orders_to_maintain_offset: Option<bool>,
485 trigger_limit_order_maintenance_once: Option<bool>,
486 use_post_only: Option<bool>,
487 limit_aggressive: Option<bool>,
488 use_quote_quantity: Option<bool>,
489 emulation_trigger: Option<TriggerType>,
490 use_individual_cancels_on_stop: Option<bool>,
491 cancel_orders_on_stop: Option<bool>,
492 close_positions_on_stop: Option<bool>,
493 close_positions_qty_precision: Option<u8>,
494 close_positions_time_in_force: Option<TimeInForce>,
495 reduce_only_on_stop: Option<bool>,
496 use_batch_cancel_on_stop: Option<bool>,
497 dry_run: Option<bool>,
498 log_data: Option<bool>,
499 test_reject_post_only: Option<bool>,
500 test_reject_reduce_only: Option<bool>,
501 test_modify_rejected: Option<bool>,
502 can_unsubscribe: Option<bool>,
503 clamp_to_instrument_price_range: Option<bool>,
504 log_events: Option<bool>,
505 log_commands: Option<bool>,
506 ) -> PyResult<Self> {
507 let defaults = Self::default();
508 let order_params = match order_params {
509 Some(dict) => from_pydict(py, &dict)?,
510 None => None,
511 };
512 let config = Self {
513 base: StrategyConfig {
514 strategy_id,
515 order_id_tag,
516 use_hyphens_in_client_order_ids: use_hyphens_in_client_order_ids
517 .unwrap_or(defaults.base.use_hyphens_in_client_order_ids),
518 use_uuid_client_order_ids: use_uuid_client_order_ids
519 .unwrap_or(defaults.base.use_uuid_client_order_ids),
520 external_order_claims,
521 log_events: log_events.unwrap_or(defaults.base.log_events),
522 log_commands: log_commands.unwrap_or(defaults.base.log_commands),
523 ..Default::default()
524 },
525 instrument_id: instrument_id.unwrap_or(defaults.instrument_id),
526 order_qty: order_qty.unwrap_or(defaults.order_qty),
527 order_display_qty,
528 order_expire_time_delta_mins,
529 order_params,
530 client_id,
531 subscribe_book: subscribe_book.unwrap_or(defaults.subscribe_book),
532 subscribe_quotes: subscribe_quotes.unwrap_or(defaults.subscribe_quotes),
533 subscribe_trades: subscribe_trades.unwrap_or(defaults.subscribe_trades),
534 book_type: book_type.unwrap_or(defaults.book_type),
535 book_depth,
536 book_interval_ms: book_interval_ms.unwrap_or(defaults.book_interval_ms),
537 book_levels_to_print: book_levels_to_print.unwrap_or(defaults.book_levels_to_print),
538 open_position_on_start_qty,
539 open_position_on_first_quote: open_position_on_first_quote
540 .unwrap_or(defaults.open_position_on_first_quote),
541 open_position_time_in_force: open_position_time_in_force
542 .unwrap_or(defaults.open_position_time_in_force),
543 enable_limit_buys: enable_limit_buys.unwrap_or(defaults.enable_limit_buys),
544 enable_limit_sells: enable_limit_sells.unwrap_or(defaults.enable_limit_sells),
545 enable_stop_buys: enable_stop_buys.unwrap_or(defaults.enable_stop_buys),
546 enable_stop_sells: enable_stop_sells.unwrap_or(defaults.enable_stop_sells),
547 tob_offset_ticks: tob_offset_ticks.unwrap_or(defaults.tob_offset_ticks),
548 limit_time_in_force,
549 stop_order_type: stop_order_type.unwrap_or(defaults.stop_order_type),
550 stop_offset_ticks: stop_offset_ticks.unwrap_or(defaults.stop_offset_ticks),
551 stop_limit_offset_ticks,
552 stop_trigger_type: stop_trigger_type.unwrap_or(defaults.stop_trigger_type),
553 stop_time_in_force,
554 trailing_offset,
555 trailing_offset_type: trailing_offset_type.unwrap_or(defaults.trailing_offset_type),
556 enable_brackets: enable_brackets.unwrap_or(defaults.enable_brackets),
557 batch_submit_limit_pair: batch_submit_limit_pair
558 .unwrap_or(defaults.batch_submit_limit_pair),
559 bracket_entry_order_type: bracket_entry_order_type
560 .unwrap_or(defaults.bracket_entry_order_type),
561 bracket_offset_ticks: bracket_offset_ticks.unwrap_or(defaults.bracket_offset_ticks),
562 modify_orders_to_maintain_tob_offset: modify_orders_to_maintain_tob_offset
563 .unwrap_or(defaults.modify_orders_to_maintain_tob_offset),
564 modify_stop_orders_to_maintain_offset: modify_stop_orders_to_maintain_offset
565 .unwrap_or(defaults.modify_stop_orders_to_maintain_offset),
566 cancel_replace_orders_to_maintain_tob_offset:
567 cancel_replace_orders_to_maintain_tob_offset
568 .unwrap_or(defaults.cancel_replace_orders_to_maintain_tob_offset),
569 cancel_replace_stop_orders_to_maintain_offset:
570 cancel_replace_stop_orders_to_maintain_offset
571 .unwrap_or(defaults.cancel_replace_stop_orders_to_maintain_offset),
572 trigger_limit_order_maintenance_once: trigger_limit_order_maintenance_once
573 .unwrap_or(defaults.trigger_limit_order_maintenance_once),
574 use_post_only: use_post_only.unwrap_or(defaults.use_post_only),
575 limit_aggressive: limit_aggressive.unwrap_or(defaults.limit_aggressive),
576 use_quote_quantity: use_quote_quantity.unwrap_or(defaults.use_quote_quantity),
577 emulation_trigger,
578 use_individual_cancels_on_stop: use_individual_cancels_on_stop
579 .unwrap_or(defaults.use_individual_cancels_on_stop),
580 cancel_orders_on_stop: cancel_orders_on_stop.unwrap_or(defaults.cancel_orders_on_stop),
581 close_positions_on_stop: close_positions_on_stop
582 .unwrap_or(defaults.close_positions_on_stop),
583 close_positions_qty_precision,
584 close_positions_time_in_force,
585 reduce_only_on_stop: reduce_only_on_stop.unwrap_or(defaults.reduce_only_on_stop),
586 use_batch_cancel_on_stop: use_batch_cancel_on_stop
587 .unwrap_or(defaults.use_batch_cancel_on_stop),
588 dry_run: dry_run.unwrap_or(defaults.dry_run),
589 log_data: log_data.unwrap_or(defaults.log_data),
590 test_reject_post_only: test_reject_post_only.unwrap_or(defaults.test_reject_post_only),
591 test_reject_reduce_only: test_reject_reduce_only
592 .unwrap_or(defaults.test_reject_reduce_only),
593 test_modify_rejected: test_modify_rejected.unwrap_or(defaults.test_modify_rejected),
594 can_unsubscribe: can_unsubscribe.unwrap_or(defaults.can_unsubscribe),
595 clamp_to_instrument_price_range: clamp_to_instrument_price_range
596 .unwrap_or(defaults.clamp_to_instrument_price_range),
597 };
598 config.validate().map_err(config_error_to_pyvalue_err)?;
599 Ok(config)
600 }
601
602 #[getter]
603 #[pyo3(name = "strategy_id")]
604 const fn py_strategy_id(&self) -> Option<StrategyId> {
605 self.base.strategy_id
606 }
607
608 #[getter]
609 #[pyo3(name = "order_id_tag")]
610 fn py_order_id_tag(&self) -> Option<&str> {
611 self.base.order_id_tag.as_deref()
612 }
613
614 #[getter]
615 #[pyo3(name = "use_hyphens_in_client_order_ids")]
616 const fn py_use_hyphens_in_client_order_ids(&self) -> bool {
617 self.base.use_hyphens_in_client_order_ids
618 }
619
620 #[getter]
621 #[pyo3(name = "use_uuid_client_order_ids")]
622 const fn py_use_uuid_client_order_ids(&self) -> bool {
623 self.base.use_uuid_client_order_ids
624 }
625
626 #[getter]
627 #[pyo3(name = "external_order_claims")]
628 fn py_external_order_claims(&self) -> Option<Vec<InstrumentId>> {
629 self.base.external_order_claims.clone()
630 }
631
632 #[getter]
633 #[pyo3(name = "instrument_id")]
634 const fn py_instrument_id(&self) -> InstrumentId {
635 self.instrument_id
636 }
637
638 #[getter]
639 #[pyo3(name = "client_id")]
640 const fn py_client_id(&self) -> Option<ClientId> {
641 self.client_id
642 }
643
644 #[getter]
645 #[pyo3(name = "order_qty")]
646 const fn py_order_qty(&self) -> Quantity {
647 self.order_qty
648 }
649
650 #[getter]
651 #[pyo3(name = "order_display_qty")]
652 const fn py_order_display_qty(&self) -> Option<Quantity> {
653 self.order_display_qty
654 }
655
656 #[getter]
657 #[pyo3(name = "order_expire_time_delta_mins")]
658 const fn py_order_expire_time_delta_mins(&self) -> Option<u64> {
659 self.order_expire_time_delta_mins
660 }
661
662 #[getter]
663 #[pyo3(name = "order_params")]
664 fn py_order_params(&self, py: Python<'_>) -> PyResult<Option<Py<PyDict>>> {
665 self.order_params
666 .as_ref()
667 .map(|params| params.to_pydict(py))
668 .transpose()
669 }
670
671 #[getter]
672 #[pyo3(name = "subscribe_book")]
673 const fn py_subscribe_book(&self) -> bool {
674 self.subscribe_book
675 }
676
677 #[getter]
678 #[pyo3(name = "subscribe_quotes")]
679 const fn py_subscribe_quotes(&self) -> bool {
680 self.subscribe_quotes
681 }
682
683 #[getter]
684 #[pyo3(name = "subscribe_trades")]
685 const fn py_subscribe_trades(&self) -> bool {
686 self.subscribe_trades
687 }
688
689 #[getter]
690 #[pyo3(name = "book_type")]
691 const fn py_book_type(&self) -> BookType {
692 self.book_type
693 }
694
695 #[getter]
696 #[pyo3(name = "book_depth")]
697 const fn py_book_depth(&self) -> Option<usize> {
698 self.book_depth
699 }
700
701 #[getter]
702 #[pyo3(name = "book_interval_ms")]
703 const fn py_book_interval_ms(&self) -> usize {
704 self.book_interval_ms
705 }
706
707 #[getter]
708 #[pyo3(name = "book_levels_to_print")]
709 const fn py_book_levels_to_print(&self) -> usize {
710 self.book_levels_to_print
711 }
712
713 #[getter]
714 #[pyo3(name = "open_position_on_start_qty")]
715 const fn py_open_position_on_start_qty(&self) -> Option<Decimal> {
716 self.open_position_on_start_qty
717 }
718
719 #[getter]
720 #[pyo3(name = "open_position_on_first_quote")]
721 const fn py_open_position_on_first_quote(&self) -> bool {
722 self.open_position_on_first_quote
723 }
724
725 #[getter]
726 #[pyo3(name = "open_position_time_in_force")]
727 const fn py_open_position_time_in_force(&self) -> TimeInForce {
728 self.open_position_time_in_force
729 }
730
731 #[getter]
732 #[pyo3(name = "enable_limit_buys")]
733 const fn py_enable_limit_buys(&self) -> bool {
734 self.enable_limit_buys
735 }
736
737 #[getter]
738 #[pyo3(name = "enable_limit_sells")]
739 const fn py_enable_limit_sells(&self) -> bool {
740 self.enable_limit_sells
741 }
742
743 #[getter]
744 #[pyo3(name = "enable_stop_buys")]
745 const fn py_enable_stop_buys(&self) -> bool {
746 self.enable_stop_buys
747 }
748
749 #[getter]
750 #[pyo3(name = "enable_stop_sells")]
751 const fn py_enable_stop_sells(&self) -> bool {
752 self.enable_stop_sells
753 }
754
755 #[getter]
756 #[pyo3(name = "tob_offset_ticks")]
757 const fn py_tob_offset_ticks(&self) -> u64 {
758 self.tob_offset_ticks
759 }
760
761 #[getter]
762 #[pyo3(name = "limit_time_in_force")]
763 const fn py_limit_time_in_force(&self) -> Option<TimeInForce> {
764 self.limit_time_in_force
765 }
766
767 #[getter]
768 #[pyo3(name = "stop_order_type")]
769 const fn py_stop_order_type(&self) -> OrderType {
770 self.stop_order_type
771 }
772
773 #[getter]
774 #[pyo3(name = "stop_offset_ticks")]
775 const fn py_stop_offset_ticks(&self) -> u64 {
776 self.stop_offset_ticks
777 }
778
779 #[getter]
780 #[pyo3(name = "stop_limit_offset_ticks")]
781 const fn py_stop_limit_offset_ticks(&self) -> Option<u64> {
782 self.stop_limit_offset_ticks
783 }
784
785 #[getter]
786 #[pyo3(name = "stop_trigger_type")]
787 const fn py_stop_trigger_type(&self) -> TriggerType {
788 self.stop_trigger_type
789 }
790
791 #[getter]
792 #[pyo3(name = "stop_time_in_force")]
793 const fn py_stop_time_in_force(&self) -> Option<TimeInForce> {
794 self.stop_time_in_force
795 }
796
797 #[getter]
798 #[pyo3(name = "trailing_offset")]
799 const fn py_trailing_offset(&self) -> Option<Decimal> {
800 self.trailing_offset
801 }
802
803 #[getter]
804 #[pyo3(name = "trailing_offset_type")]
805 const fn py_trailing_offset_type(&self) -> TrailingOffsetType {
806 self.trailing_offset_type
807 }
808
809 #[getter]
810 #[pyo3(name = "enable_brackets")]
811 const fn py_enable_brackets(&self) -> bool {
812 self.enable_brackets
813 }
814
815 #[getter]
816 #[pyo3(name = "batch_submit_limit_pair")]
817 const fn py_batch_submit_limit_pair(&self) -> bool {
818 self.batch_submit_limit_pair
819 }
820
821 #[getter]
822 #[pyo3(name = "bracket_entry_order_type")]
823 const fn py_bracket_entry_order_type(&self) -> OrderType {
824 self.bracket_entry_order_type
825 }
826
827 #[getter]
828 #[pyo3(name = "bracket_offset_ticks")]
829 const fn py_bracket_offset_ticks(&self) -> u64 {
830 self.bracket_offset_ticks
831 }
832
833 #[getter]
834 #[pyo3(name = "modify_orders_to_maintain_tob_offset")]
835 const fn py_modify_orders_to_maintain_tob_offset(&self) -> bool {
836 self.modify_orders_to_maintain_tob_offset
837 }
838
839 #[getter]
840 #[pyo3(name = "modify_stop_orders_to_maintain_offset")]
841 const fn py_modify_stop_orders_to_maintain_offset(&self) -> bool {
842 self.modify_stop_orders_to_maintain_offset
843 }
844
845 #[getter]
846 #[pyo3(name = "cancel_replace_orders_to_maintain_tob_offset")]
847 const fn py_cancel_replace_orders_to_maintain_tob_offset(&self) -> bool {
848 self.cancel_replace_orders_to_maintain_tob_offset
849 }
850
851 #[getter]
852 #[pyo3(name = "cancel_replace_stop_orders_to_maintain_offset")]
853 const fn py_cancel_replace_stop_orders_to_maintain_offset(&self) -> bool {
854 self.cancel_replace_stop_orders_to_maintain_offset
855 }
856
857 #[getter]
858 #[pyo3(name = "trigger_limit_order_maintenance_once")]
859 const fn py_trigger_limit_order_maintenance_once(&self) -> bool {
860 self.trigger_limit_order_maintenance_once
861 }
862
863 #[getter]
864 #[pyo3(name = "use_post_only")]
865 const fn py_use_post_only(&self) -> bool {
866 self.use_post_only
867 }
868
869 #[getter]
870 #[pyo3(name = "limit_aggressive")]
871 const fn py_limit_aggressive(&self) -> bool {
872 self.limit_aggressive
873 }
874
875 #[getter]
876 #[pyo3(name = "use_quote_quantity")]
877 const fn py_use_quote_quantity(&self) -> bool {
878 self.use_quote_quantity
879 }
880
881 #[getter]
882 #[pyo3(name = "emulation_trigger")]
883 const fn py_emulation_trigger(&self) -> Option<TriggerType> {
884 self.emulation_trigger
885 }
886
887 #[getter]
888 #[pyo3(name = "use_individual_cancels_on_stop")]
889 const fn py_use_individual_cancels_on_stop(&self) -> bool {
890 self.use_individual_cancels_on_stop
891 }
892
893 #[getter]
894 #[pyo3(name = "cancel_orders_on_stop")]
895 const fn py_cancel_orders_on_stop(&self) -> bool {
896 self.cancel_orders_on_stop
897 }
898
899 #[getter]
900 #[pyo3(name = "close_positions_on_stop")]
901 const fn py_close_positions_on_stop(&self) -> bool {
902 self.close_positions_on_stop
903 }
904
905 #[getter]
906 #[pyo3(name = "close_positions_qty_precision")]
907 const fn py_close_positions_qty_precision(&self) -> Option<u8> {
908 self.close_positions_qty_precision
909 }
910
911 #[getter]
912 #[pyo3(name = "close_positions_time_in_force")]
913 const fn py_close_positions_time_in_force(&self) -> Option<TimeInForce> {
914 self.close_positions_time_in_force
915 }
916
917 #[getter]
918 #[pyo3(name = "reduce_only_on_stop")]
919 const fn py_reduce_only_on_stop(&self) -> bool {
920 self.reduce_only_on_stop
921 }
922
923 #[getter]
924 #[pyo3(name = "use_batch_cancel_on_stop")]
925 const fn py_use_batch_cancel_on_stop(&self) -> bool {
926 self.use_batch_cancel_on_stop
927 }
928
929 #[getter]
930 #[pyo3(name = "dry_run")]
931 const fn py_dry_run(&self) -> bool {
932 self.dry_run
933 }
934
935 #[getter]
936 #[pyo3(name = "log_data")]
937 const fn py_log_data(&self) -> bool {
938 self.log_data
939 }
940
941 #[getter]
942 #[pyo3(name = "test_reject_post_only")]
943 const fn py_test_reject_post_only(&self) -> bool {
944 self.test_reject_post_only
945 }
946
947 #[getter]
948 #[pyo3(name = "test_reject_reduce_only")]
949 const fn py_test_reject_reduce_only(&self) -> bool {
950 self.test_reject_reduce_only
951 }
952
953 #[getter]
954 #[pyo3(name = "test_modify_rejected")]
955 const fn py_test_modify_rejected(&self) -> bool {
956 self.test_modify_rejected
957 }
958
959 #[getter]
960 #[pyo3(name = "can_unsubscribe")]
961 const fn py_can_unsubscribe(&self) -> bool {
962 self.can_unsubscribe
963 }
964
965 #[getter]
966 #[pyo3(name = "clamp_to_instrument_price_range")]
967 const fn py_clamp_to_instrument_price_range(&self) -> bool {
968 self.clamp_to_instrument_price_range
969 }
970
971 #[getter]
972 #[pyo3(name = "log_events")]
973 const fn py_log_events(&self) -> bool {
974 self.base.log_events
975 }
976
977 #[getter]
978 #[pyo3(name = "log_commands")]
979 const fn py_log_commands(&self) -> bool {
980 self.base.log_commands
981 }
982
983 fn __repr__(&self) -> String {
984 format!("{self:?}")
985 }
986}