1use std::{cell::RefCell, rc::Rc};
19
20use bytes::Bytes;
21use nautilus_core::python::to_pyvalue_err;
22#[cfg(feature = "defi")]
23use nautilus_model::defi::{Pool, PoolProfiler};
24use nautilus_model::{
25 data::{
26 Bar, BarType, FundingRateUpdate, InstrumentStatus, QuoteTick, TradeTick,
27 prices::{IndexPriceUpdate, MarkPriceUpdate},
28 },
29 enums::{AggregationSource, OmsType, OrderSide, PositionSide, PriceType},
30 identifiers::{
31 AccountId, ClientId, ClientOrderId, ComponentId, ExecAlgorithmId, InstrumentId,
32 OrderListId, PositionId, StrategyId, Venue, VenueOrderId,
33 },
34 instruments::SyntheticInstrument,
35 orderbook::{OrderBook, own::OwnOrderBook},
36 orders::OrderList,
37 position::Position,
38 python::{
39 account::account_any_to_pyobject,
40 instruments::{instrument_any_to_pyobject, pyobject_to_instrument_any},
41 orders::{order_any_to_pyobject, pyobject_to_order_any},
42 },
43 types::{Currency, Money, Price, Quantity},
44};
45use pyo3::prelude::*;
46
47use crate::{
48 cache::{Cache, CacheConfig},
49 enums::SerializationEncoding,
50};
51
52#[allow(non_camel_case_types)]
57#[pyo3::pyclass(
58 module = "nautilus_trader.core.nautilus_pyo3.common",
59 name = "Cache",
60 unsendable,
61 from_py_object
62)]
63#[pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.common")]
64#[derive(Debug, Clone)]
65pub struct PyCache(Rc<RefCell<Cache>>);
66
67impl PyCache {
68 #[must_use]
70 pub fn from_rc(rc: Rc<RefCell<Cache>>) -> Self {
71 Self(rc)
72 }
73
74 #[must_use]
76 pub fn cache_rc(&self) -> Rc<RefCell<Cache>> {
77 self.0.clone()
78 }
79}
80
81#[pymethods]
82#[pyo3_stub_gen::derive::gen_stub_pymethods]
83impl PyCache {
84 #[new]
85 #[pyo3(signature = (config=None))]
86 fn py_new(config: Option<CacheConfig>) -> Self {
87 Self(Rc::new(RefCell::new(Cache::new(config, None))))
88 }
89
90 #[pyo3(name = "reset")]
91 fn py_reset(&mut self) {
92 self.0.borrow_mut().reset();
93 }
94
95 #[pyo3(name = "dispose")]
96 fn py_dispose(&mut self) {
97 self.0.borrow_mut().dispose();
98 }
99
100 #[pyo3(name = "get")]
101 fn py_get(&self, key: &str) -> PyResult<Option<Vec<u8>>> {
102 match self.0.borrow().get(key).map_err(to_pyvalue_err)? {
103 Some(bytes) => Ok(Some(bytes.to_vec())),
104 None => Ok(None),
105 }
106 }
107
108 #[pyo3(name = "add")]
109 fn py_add_general(&mut self, key: &str, value: Vec<u8>) -> PyResult<()> {
110 self.0
111 .borrow_mut()
112 .add(key, Bytes::from(value))
113 .map_err(to_pyvalue_err)
114 }
115
116 #[pyo3(name = "quote", signature = (instrument_id, index=0))]
117 fn py_quote(&self, instrument_id: InstrumentId, index: usize) -> Option<QuoteTick> {
118 self.0
119 .borrow()
120 .quote_at_index(&instrument_id, index)
121 .copied()
122 }
123
124 #[pyo3(name = "trade", signature = (instrument_id, index=0))]
125 fn py_trade(&self, instrument_id: InstrumentId, index: usize) -> Option<TradeTick> {
126 self.0
127 .borrow()
128 .trade_at_index(&instrument_id, index)
129 .copied()
130 }
131
132 #[pyo3(name = "bar", signature = (bar_type, index=0))]
133 fn py_bar(&self, bar_type: BarType, index: usize) -> Option<Bar> {
134 self.0.borrow().bar_at_index(&bar_type, index).copied()
135 }
136
137 #[pyo3(name = "quotes")]
138 fn py_quotes(&self, instrument_id: InstrumentId) -> Option<Vec<QuoteTick>> {
139 self.0.borrow().quotes(&instrument_id)
140 }
141
142 #[pyo3(name = "trades")]
143 fn py_trades(&self, instrument_id: InstrumentId) -> Option<Vec<TradeTick>> {
144 self.0.borrow().trades(&instrument_id)
145 }
146
147 #[pyo3(name = "bars")]
148 fn py_bars(&self, bar_type: BarType) -> Option<Vec<Bar>> {
149 self.0.borrow().bars(&bar_type)
150 }
151
152 #[pyo3(name = "bar_types", signature = (aggregation_source, instrument_id=None, price_type=None))]
153 fn py_bar_types(
154 &self,
155 aggregation_source: AggregationSource,
156 instrument_id: Option<InstrumentId>,
157 price_type: Option<PriceType>,
158 ) -> Vec<BarType> {
159 self.0
160 .borrow()
161 .bar_types(
162 instrument_id.as_ref(),
163 price_type.as_ref(),
164 aggregation_source,
165 )
166 .into_iter()
167 .copied()
168 .collect()
169 }
170
171 #[pyo3(name = "mark_price")]
172 fn py_mark_price(&self, instrument_id: InstrumentId) -> Option<MarkPriceUpdate> {
173 self.0.borrow().mark_price(&instrument_id).copied()
174 }
175
176 #[pyo3(name = "mark_prices")]
177 fn py_mark_prices(&self, instrument_id: InstrumentId) -> Option<Vec<MarkPriceUpdate>> {
178 self.0.borrow().mark_prices(&instrument_id)
179 }
180
181 #[pyo3(name = "index_price")]
182 fn py_index_price(&self, instrument_id: InstrumentId) -> Option<IndexPriceUpdate> {
183 self.0.borrow().index_price(&instrument_id).copied()
184 }
185
186 #[pyo3(name = "index_prices")]
187 fn py_index_prices(&self, instrument_id: InstrumentId) -> Option<Vec<IndexPriceUpdate>> {
188 self.0.borrow().index_prices(&instrument_id)
189 }
190
191 #[pyo3(name = "funding_rate")]
192 fn py_funding_rate(&self, instrument_id: InstrumentId) -> Option<FundingRateUpdate> {
193 self.0.borrow().funding_rate(&instrument_id).copied()
194 }
195
196 #[pyo3(name = "instrument_status")]
197 fn py_instrument_status(&self, instrument_id: InstrumentId) -> Option<InstrumentStatus> {
198 self.0.borrow().instrument_status(&instrument_id).copied()
199 }
200
201 #[pyo3(name = "instrument_statuses")]
202 fn py_instrument_statuses(&self, instrument_id: InstrumentId) -> Option<Vec<InstrumentStatus>> {
203 self.0.borrow().instrument_statuses(&instrument_id)
204 }
205
206 #[pyo3(name = "price")]
207 fn py_price(&self, instrument_id: InstrumentId, price_type: PriceType) -> Option<Price> {
208 self.0.borrow().price(&instrument_id, price_type)
209 }
210
211 #[pyo3(name = "order_book")]
212 fn py_order_book(&self, instrument_id: InstrumentId) -> Option<OrderBook> {
213 self.0.borrow().order_book(&instrument_id).cloned()
214 }
215
216 #[pyo3(name = "has_order_book")]
217 fn py_has_order_book(&self, instrument_id: InstrumentId) -> bool {
218 self.0.borrow().has_order_book(&instrument_id)
219 }
220
221 #[pyo3(name = "book_update_count")]
222 fn py_book_update_count(&self, instrument_id: InstrumentId) -> usize {
223 self.0.borrow().book_update_count(&instrument_id)
224 }
225
226 #[pyo3(name = "has_quote_ticks")]
227 fn py_has_quote_ticks(&self, instrument_id: InstrumentId) -> bool {
228 self.0.borrow().has_quote_ticks(&instrument_id)
229 }
230
231 #[pyo3(name = "has_trade_ticks")]
232 fn py_has_trade_ticks(&self, instrument_id: InstrumentId) -> bool {
233 self.0.borrow().has_trade_ticks(&instrument_id)
234 }
235
236 #[pyo3(name = "has_bars")]
237 fn py_has_bars(&self, bar_type: BarType) -> bool {
238 self.0.borrow().has_bars(&bar_type)
239 }
240
241 #[pyo3(name = "quote_count")]
242 fn py_quote_count(&self, instrument_id: InstrumentId) -> usize {
243 self.0.borrow().quote_count(&instrument_id)
244 }
245
246 #[pyo3(name = "trade_count")]
247 fn py_trade_count(&self, instrument_id: InstrumentId) -> usize {
248 self.0.borrow().trade_count(&instrument_id)
249 }
250
251 #[pyo3(name = "bar_count")]
252 fn py_bar_count(&self, bar_type: BarType) -> usize {
253 self.0.borrow().bar_count(&bar_type)
254 }
255
256 #[pyo3(name = "get_xrate")]
257 fn py_get_xrate(
258 &self,
259 venue: Venue,
260 from_currency: Currency,
261 to_currency: Currency,
262 price_type: PriceType,
263 ) -> Option<f64> {
264 self.0
265 .borrow()
266 .get_xrate(venue, from_currency, to_currency, price_type)
267 }
268
269 #[pyo3(name = "get_mark_xrate")]
270 fn py_get_mark_xrate(&self, from_currency: Currency, to_currency: Currency) -> Option<f64> {
271 self.0.borrow().get_mark_xrate(from_currency, to_currency)
272 }
273
274 #[pyo3(name = "own_order_book")]
275 fn py_own_order_book(&self, instrument_id: InstrumentId) -> Option<OwnOrderBook> {
276 self.0.borrow().own_order_book(&instrument_id).cloned()
277 }
278
279 #[pyo3(name = "instrument")]
280 fn py_instrument(
281 &self,
282 py: Python,
283 instrument_id: InstrumentId,
284 ) -> PyResult<Option<Py<PyAny>>> {
285 let cache = self.0.borrow();
286 match cache.instrument(&instrument_id) {
287 Some(instrument) => Ok(Some(instrument_any_to_pyobject(py, instrument.clone())?)),
288 None => Ok(None),
289 }
290 }
291
292 #[pyo3(name = "instrument_ids", signature = (venue=None))]
293 fn py_instrument_ids(&self, venue: Option<Venue>) -> Vec<InstrumentId> {
294 self.0
295 .borrow()
296 .instrument_ids(venue.as_ref())
297 .into_iter()
298 .copied()
299 .collect()
300 }
301
302 #[pyo3(name = "instruments", signature = (venue=None))]
303 fn py_instruments(&self, py: Python, venue: Option<Venue>) -> PyResult<Vec<Py<PyAny>>> {
304 let cache = self.0.borrow();
305 let mut py_instruments = Vec::new();
306
307 match venue {
308 Some(venue) => {
309 for instrument in cache.instruments(&venue, None) {
310 py_instruments.push(instrument_any_to_pyobject(py, (*instrument).clone())?);
311 }
312 }
313 None => {
314 for instrument_id in cache.instrument_ids(None) {
315 if let Some(instrument) = cache.instrument(instrument_id) {
316 py_instruments.push(instrument_any_to_pyobject(py, instrument.clone())?);
317 }
318 }
319 }
320 }
321 Ok(py_instruments)
322 }
323
324 #[pyo3(name = "synthetic")]
325 fn py_synthetic(&self, instrument_id: InstrumentId) -> Option<SyntheticInstrument> {
326 self.0.borrow().synthetic(&instrument_id).cloned()
327 }
328
329 #[pyo3(name = "synthetic_ids")]
330 fn py_synthetic_ids(&self) -> Vec<InstrumentId> {
331 self.0
332 .borrow()
333 .synthetic_ids()
334 .into_iter()
335 .copied()
336 .collect()
337 }
338
339 #[pyo3(name = "account")]
340 fn py_account(&self, py: Python, account_id: AccountId) -> PyResult<Option<Py<PyAny>>> {
341 let cache = self.0.borrow();
342 match cache.account(&account_id) {
343 Some(account) => Ok(Some(account_any_to_pyobject(py, account.clone())?)),
344 None => Ok(None),
345 }
346 }
347
348 #[pyo3(name = "account_for_venue")]
349 fn py_account_for_venue(&self, py: Python, venue: Venue) -> PyResult<Option<Py<PyAny>>> {
350 let cache = self.0.borrow();
351 match cache.account_for_venue(&venue) {
352 Some(account) => Ok(Some(account_any_to_pyobject(py, account.clone())?)),
353 None => Ok(None),
354 }
355 }
356
357 #[pyo3(name = "account_id")]
358 fn py_account_id(&self, venue: Venue) -> Option<AccountId> {
359 self.0.borrow().account_id(&venue).copied()
360 }
361
362 #[pyo3(name = "client_order_ids", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
363 fn py_client_order_ids(
364 &self,
365 venue: Option<Venue>,
366 instrument_id: Option<InstrumentId>,
367 strategy_id: Option<StrategyId>,
368 account_id: Option<AccountId>,
369 ) -> Vec<ClientOrderId> {
370 self.0
371 .borrow()
372 .client_order_ids(
373 venue.as_ref(),
374 instrument_id.as_ref(),
375 strategy_id.as_ref(),
376 account_id.as_ref(),
377 )
378 .into_iter()
379 .collect()
380 }
381
382 #[pyo3(name = "client_order_ids_open", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
383 fn py_client_order_ids_open(
384 &self,
385 venue: Option<Venue>,
386 instrument_id: Option<InstrumentId>,
387 strategy_id: Option<StrategyId>,
388 account_id: Option<AccountId>,
389 ) -> Vec<ClientOrderId> {
390 self.0
391 .borrow()
392 .client_order_ids_open(
393 venue.as_ref(),
394 instrument_id.as_ref(),
395 strategy_id.as_ref(),
396 account_id.as_ref(),
397 )
398 .into_iter()
399 .collect()
400 }
401
402 #[pyo3(name = "client_order_ids_closed", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
403 fn py_client_order_ids_closed(
404 &self,
405 venue: Option<Venue>,
406 instrument_id: Option<InstrumentId>,
407 strategy_id: Option<StrategyId>,
408 account_id: Option<AccountId>,
409 ) -> Vec<ClientOrderId> {
410 self.0
411 .borrow()
412 .client_order_ids_closed(
413 venue.as_ref(),
414 instrument_id.as_ref(),
415 strategy_id.as_ref(),
416 account_id.as_ref(),
417 )
418 .into_iter()
419 .collect()
420 }
421
422 #[pyo3(name = "client_order_ids_emulated", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
423 fn py_client_order_ids_emulated(
424 &self,
425 venue: Option<Venue>,
426 instrument_id: Option<InstrumentId>,
427 strategy_id: Option<StrategyId>,
428 account_id: Option<AccountId>,
429 ) -> Vec<ClientOrderId> {
430 self.0
431 .borrow()
432 .client_order_ids_emulated(
433 venue.as_ref(),
434 instrument_id.as_ref(),
435 strategy_id.as_ref(),
436 account_id.as_ref(),
437 )
438 .into_iter()
439 .collect()
440 }
441
442 #[pyo3(name = "client_order_ids_inflight", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
443 fn py_client_order_ids_inflight(
444 &self,
445 venue: Option<Venue>,
446 instrument_id: Option<InstrumentId>,
447 strategy_id: Option<StrategyId>,
448 account_id: Option<AccountId>,
449 ) -> Vec<ClientOrderId> {
450 self.0
451 .borrow()
452 .client_order_ids_inflight(
453 venue.as_ref(),
454 instrument_id.as_ref(),
455 strategy_id.as_ref(),
456 account_id.as_ref(),
457 )
458 .into_iter()
459 .collect()
460 }
461
462 #[pyo3(name = "position_ids", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
463 fn py_position_ids(
464 &self,
465 venue: Option<Venue>,
466 instrument_id: Option<InstrumentId>,
467 strategy_id: Option<StrategyId>,
468 account_id: Option<AccountId>,
469 ) -> Vec<PositionId> {
470 self.0
471 .borrow()
472 .position_ids(
473 venue.as_ref(),
474 instrument_id.as_ref(),
475 strategy_id.as_ref(),
476 account_id.as_ref(),
477 )
478 .into_iter()
479 .collect()
480 }
481
482 #[pyo3(name = "position_open_ids", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
483 fn py_position_open_ids(
484 &self,
485 venue: Option<Venue>,
486 instrument_id: Option<InstrumentId>,
487 strategy_id: Option<StrategyId>,
488 account_id: Option<AccountId>,
489 ) -> Vec<PositionId> {
490 self.0
491 .borrow()
492 .position_open_ids(
493 venue.as_ref(),
494 instrument_id.as_ref(),
495 strategy_id.as_ref(),
496 account_id.as_ref(),
497 )
498 .into_iter()
499 .collect()
500 }
501
502 #[pyo3(name = "position_closed_ids", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
503 fn py_position_closed_ids(
504 &self,
505 venue: Option<Venue>,
506 instrument_id: Option<InstrumentId>,
507 strategy_id: Option<StrategyId>,
508 account_id: Option<AccountId>,
509 ) -> Vec<PositionId> {
510 self.0
511 .borrow()
512 .position_closed_ids(
513 venue.as_ref(),
514 instrument_id.as_ref(),
515 strategy_id.as_ref(),
516 account_id.as_ref(),
517 )
518 .into_iter()
519 .collect()
520 }
521
522 #[pyo3(name = "actor_ids")]
523 fn py_actor_ids(&self) -> Vec<ComponentId> {
524 self.0.borrow().actor_ids().into_iter().collect()
525 }
526
527 #[pyo3(name = "strategy_ids")]
528 fn py_strategy_ids(&self) -> Vec<StrategyId> {
529 self.0.borrow().strategy_ids().into_iter().collect()
530 }
531
532 #[pyo3(name = "exec_algorithm_ids")]
533 fn py_exec_algorithm_ids(&self) -> Vec<ExecAlgorithmId> {
534 self.0.borrow().exec_algorithm_ids().into_iter().collect()
535 }
536
537 #[pyo3(name = "order")]
538 fn py_order(&self, py: Python, client_order_id: ClientOrderId) -> PyResult<Option<Py<PyAny>>> {
539 let cache = self.0.borrow();
540 match cache.order(&client_order_id) {
541 Some(order) => Ok(Some(order_any_to_pyobject(py, order.clone())?)),
542 None => Ok(None),
543 }
544 }
545
546 #[pyo3(name = "client_order_id")]
547 fn py_client_order_id(&self, venue_order_id: VenueOrderId) -> Option<ClientOrderId> {
548 self.0.borrow().client_order_id(&venue_order_id).copied()
549 }
550
551 #[pyo3(name = "venue_order_id")]
552 fn py_venue_order_id(&self, client_order_id: ClientOrderId) -> Option<VenueOrderId> {
553 self.0.borrow().venue_order_id(&client_order_id).copied()
554 }
555
556 #[pyo3(name = "client_id")]
557 fn py_client_id(&self, client_order_id: ClientOrderId) -> Option<ClientId> {
558 self.0.borrow().client_id(&client_order_id).copied()
559 }
560
561 #[pyo3(name = "orders", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
562 fn py_orders(
563 &self,
564 py: Python,
565 venue: Option<Venue>,
566 instrument_id: Option<InstrumentId>,
567 strategy_id: Option<StrategyId>,
568 account_id: Option<AccountId>,
569 side: Option<OrderSide>,
570 ) -> PyResult<Vec<Py<PyAny>>> {
571 let cache = self.0.borrow();
572 cache
573 .orders(
574 venue.as_ref(),
575 instrument_id.as_ref(),
576 strategy_id.as_ref(),
577 account_id.as_ref(),
578 side,
579 )
580 .into_iter()
581 .map(|o| order_any_to_pyobject(py, o.clone()))
582 .collect()
583 }
584
585 #[pyo3(name = "orders_open", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
586 fn py_orders_open(
587 &self,
588 py: Python,
589 venue: Option<Venue>,
590 instrument_id: Option<InstrumentId>,
591 strategy_id: Option<StrategyId>,
592 account_id: Option<AccountId>,
593 side: Option<OrderSide>,
594 ) -> PyResult<Vec<Py<PyAny>>> {
595 let cache = self.0.borrow();
596 cache
597 .orders_open(
598 venue.as_ref(),
599 instrument_id.as_ref(),
600 strategy_id.as_ref(),
601 account_id.as_ref(),
602 side,
603 )
604 .into_iter()
605 .map(|o| order_any_to_pyobject(py, o.clone()))
606 .collect()
607 }
608
609 #[pyo3(name = "orders_closed", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
610 fn py_orders_closed(
611 &self,
612 py: Python,
613 venue: Option<Venue>,
614 instrument_id: Option<InstrumentId>,
615 strategy_id: Option<StrategyId>,
616 account_id: Option<AccountId>,
617 side: Option<OrderSide>,
618 ) -> PyResult<Vec<Py<PyAny>>> {
619 let cache = self.0.borrow();
620 cache
621 .orders_closed(
622 venue.as_ref(),
623 instrument_id.as_ref(),
624 strategy_id.as_ref(),
625 account_id.as_ref(),
626 side,
627 )
628 .into_iter()
629 .map(|o| order_any_to_pyobject(py, o.clone()))
630 .collect()
631 }
632
633 #[pyo3(name = "orders_emulated", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
634 fn py_orders_emulated(
635 &self,
636 py: Python,
637 venue: Option<Venue>,
638 instrument_id: Option<InstrumentId>,
639 strategy_id: Option<StrategyId>,
640 account_id: Option<AccountId>,
641 side: Option<OrderSide>,
642 ) -> PyResult<Vec<Py<PyAny>>> {
643 let cache = self.0.borrow();
644 cache
645 .orders_emulated(
646 venue.as_ref(),
647 instrument_id.as_ref(),
648 strategy_id.as_ref(),
649 account_id.as_ref(),
650 side,
651 )
652 .into_iter()
653 .map(|o| order_any_to_pyobject(py, o.clone()))
654 .collect()
655 }
656
657 #[pyo3(name = "orders_inflight", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
658 fn py_orders_inflight(
659 &self,
660 py: Python,
661 venue: Option<Venue>,
662 instrument_id: Option<InstrumentId>,
663 strategy_id: Option<StrategyId>,
664 account_id: Option<AccountId>,
665 side: Option<OrderSide>,
666 ) -> PyResult<Vec<Py<PyAny>>> {
667 let cache = self.0.borrow();
668 cache
669 .orders_inflight(
670 venue.as_ref(),
671 instrument_id.as_ref(),
672 strategy_id.as_ref(),
673 account_id.as_ref(),
674 side,
675 )
676 .into_iter()
677 .map(|o| order_any_to_pyobject(py, o.clone()))
678 .collect()
679 }
680
681 #[pyo3(name = "orders_for_position")]
682 fn py_orders_for_position(
683 &self,
684 py: Python,
685 position_id: PositionId,
686 ) -> PyResult<Vec<Py<PyAny>>> {
687 let cache = self.0.borrow();
688 cache
689 .orders_for_position(&position_id)
690 .into_iter()
691 .map(|o| order_any_to_pyobject(py, o.clone()))
692 .collect()
693 }
694
695 #[pyo3(name = "order_exists")]
696 fn py_order_exists(&self, client_order_id: ClientOrderId) -> bool {
697 self.0.borrow().order_exists(&client_order_id)
698 }
699
700 #[pyo3(name = "is_order_open")]
701 fn py_is_order_open(&self, client_order_id: ClientOrderId) -> bool {
702 self.0.borrow().is_order_open(&client_order_id)
703 }
704
705 #[pyo3(name = "is_order_closed")]
706 fn py_is_order_closed(&self, client_order_id: ClientOrderId) -> bool {
707 self.0.borrow().is_order_closed(&client_order_id)
708 }
709
710 #[pyo3(name = "is_order_emulated")]
711 fn py_is_order_emulated(&self, client_order_id: ClientOrderId) -> bool {
712 self.0.borrow().is_order_emulated(&client_order_id)
713 }
714
715 #[pyo3(name = "is_order_inflight")]
716 fn py_is_order_inflight(&self, client_order_id: ClientOrderId) -> bool {
717 self.0.borrow().is_order_inflight(&client_order_id)
718 }
719
720 #[pyo3(name = "is_order_pending_cancel_local")]
721 fn py_is_order_pending_cancel_local(&self, client_order_id: ClientOrderId) -> bool {
722 self.0
723 .borrow()
724 .is_order_pending_cancel_local(&client_order_id)
725 }
726
727 #[pyo3(name = "orders_open_count", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
728 fn py_orders_open_count(
729 &self,
730 venue: Option<Venue>,
731 instrument_id: Option<InstrumentId>,
732 strategy_id: Option<StrategyId>,
733 account_id: Option<AccountId>,
734 side: Option<OrderSide>,
735 ) -> usize {
736 self.0.borrow().orders_open_count(
737 venue.as_ref(),
738 instrument_id.as_ref(),
739 strategy_id.as_ref(),
740 account_id.as_ref(),
741 side,
742 )
743 }
744
745 #[pyo3(name = "orders_closed_count", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
746 fn py_orders_closed_count(
747 &self,
748 venue: Option<Venue>,
749 instrument_id: Option<InstrumentId>,
750 strategy_id: Option<StrategyId>,
751 account_id: Option<AccountId>,
752 side: Option<OrderSide>,
753 ) -> usize {
754 self.0.borrow().orders_closed_count(
755 venue.as_ref(),
756 instrument_id.as_ref(),
757 strategy_id.as_ref(),
758 account_id.as_ref(),
759 side,
760 )
761 }
762
763 #[pyo3(name = "orders_emulated_count", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
764 fn py_orders_emulated_count(
765 &self,
766 venue: Option<Venue>,
767 instrument_id: Option<InstrumentId>,
768 strategy_id: Option<StrategyId>,
769 account_id: Option<AccountId>,
770 side: Option<OrderSide>,
771 ) -> usize {
772 self.0.borrow().orders_emulated_count(
773 venue.as_ref(),
774 instrument_id.as_ref(),
775 strategy_id.as_ref(),
776 account_id.as_ref(),
777 side,
778 )
779 }
780
781 #[pyo3(name = "orders_inflight_count", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
782 fn py_orders_inflight_count(
783 &self,
784 venue: Option<Venue>,
785 instrument_id: Option<InstrumentId>,
786 strategy_id: Option<StrategyId>,
787 account_id: Option<AccountId>,
788 side: Option<OrderSide>,
789 ) -> usize {
790 self.0.borrow().orders_inflight_count(
791 venue.as_ref(),
792 instrument_id.as_ref(),
793 strategy_id.as_ref(),
794 account_id.as_ref(),
795 side,
796 )
797 }
798
799 #[pyo3(name = "orders_total_count", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
800 fn py_orders_total_count(
801 &self,
802 venue: Option<Venue>,
803 instrument_id: Option<InstrumentId>,
804 strategy_id: Option<StrategyId>,
805 account_id: Option<AccountId>,
806 side: Option<OrderSide>,
807 ) -> usize {
808 self.0.borrow().orders_total_count(
809 venue.as_ref(),
810 instrument_id.as_ref(),
811 strategy_id.as_ref(),
812 account_id.as_ref(),
813 side,
814 )
815 }
816
817 #[pyo3(name = "order_list")]
818 fn py_order_list(&self, py: Python, order_list_id: OrderListId) -> PyResult<Option<Py<PyAny>>> {
819 let cache = self.0.borrow();
820 match cache.order_list(&order_list_id) {
821 Some(order_list) => Ok(Some(order_list.clone().into_pyobject(py)?.into())),
822 None => Ok(None),
823 }
824 }
825
826 #[pyo3(name = "order_lists", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
827 fn py_order_lists(
828 &self,
829 py: Python,
830 venue: Option<Venue>,
831 instrument_id: Option<InstrumentId>,
832 strategy_id: Option<StrategyId>,
833 account_id: Option<AccountId>,
834 ) -> PyResult<Vec<Py<PyAny>>> {
835 let cache = self.0.borrow();
836 cache
837 .order_lists(
838 venue.as_ref(),
839 instrument_id.as_ref(),
840 strategy_id.as_ref(),
841 account_id.as_ref(),
842 )
843 .into_iter()
844 .map(|ol| Ok(ol.clone().into_pyobject(py)?.into()))
845 .collect()
846 }
847
848 #[pyo3(name = "order_list_exists")]
849 fn py_order_list_exists(&self, order_list_id: OrderListId) -> bool {
850 self.0.borrow().order_list_exists(&order_list_id)
851 }
852
853 #[pyo3(name = "orders_for_exec_algorithm", signature = (exec_algorithm_id, venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
854 #[expect(clippy::too_many_arguments)]
855 fn py_orders_for_exec_algorithm(
856 &self,
857 py: Python,
858 exec_algorithm_id: ExecAlgorithmId,
859 venue: Option<Venue>,
860 instrument_id: Option<InstrumentId>,
861 strategy_id: Option<StrategyId>,
862 account_id: Option<AccountId>,
863 side: Option<OrderSide>,
864 ) -> PyResult<Vec<Py<PyAny>>> {
865 let cache = self.0.borrow();
866 cache
867 .orders_for_exec_algorithm(
868 &exec_algorithm_id,
869 venue.as_ref(),
870 instrument_id.as_ref(),
871 strategy_id.as_ref(),
872 account_id.as_ref(),
873 side,
874 )
875 .into_iter()
876 .map(|o| order_any_to_pyobject(py, o.clone()))
877 .collect()
878 }
879
880 #[pyo3(name = "orders_for_exec_spawn")]
881 fn py_orders_for_exec_spawn(
882 &self,
883 py: Python,
884 exec_spawn_id: ClientOrderId,
885 ) -> PyResult<Vec<Py<PyAny>>> {
886 let cache = self.0.borrow();
887 cache
888 .orders_for_exec_spawn(&exec_spawn_id)
889 .into_iter()
890 .map(|o| order_any_to_pyobject(py, o.clone()))
891 .collect()
892 }
893
894 #[pyo3(name = "exec_spawn_total_quantity")]
895 fn py_exec_spawn_total_quantity(
896 &self,
897 exec_spawn_id: ClientOrderId,
898 active_only: bool,
899 ) -> Option<Quantity> {
900 self.0
901 .borrow()
902 .exec_spawn_total_quantity(&exec_spawn_id, active_only)
903 }
904
905 #[pyo3(name = "exec_spawn_total_filled_qty")]
906 fn py_exec_spawn_total_filled_qty(
907 &self,
908 exec_spawn_id: ClientOrderId,
909 active_only: bool,
910 ) -> Option<Quantity> {
911 self.0
912 .borrow()
913 .exec_spawn_total_filled_qty(&exec_spawn_id, active_only)
914 }
915
916 #[pyo3(name = "exec_spawn_total_leaves_qty")]
917 fn py_exec_spawn_total_leaves_qty(
918 &self,
919 exec_spawn_id: ClientOrderId,
920 active_only: bool,
921 ) -> Option<Quantity> {
922 self.0
923 .borrow()
924 .exec_spawn_total_leaves_qty(&exec_spawn_id, active_only)
925 }
926
927 #[pyo3(name = "position")]
928 fn py_position(&self, py: Python, position_id: PositionId) -> PyResult<Option<Py<PyAny>>> {
929 let cache = self.0.borrow();
930 match cache.position(&position_id) {
931 Some(position) => Ok(Some(position.clone().into_pyobject(py)?.into())),
932 None => Ok(None),
933 }
934 }
935
936 #[pyo3(name = "position_for_order")]
937 fn py_position_for_order(
938 &self,
939 py: Python,
940 client_order_id: ClientOrderId,
941 ) -> PyResult<Option<Py<PyAny>>> {
942 let cache = self.0.borrow();
943 match cache.position_for_order(&client_order_id) {
944 Some(position) => Ok(Some(position.clone().into_pyobject(py)?.into())),
945 None => Ok(None),
946 }
947 }
948
949 #[pyo3(name = "position_id")]
950 fn py_position_id(&self, client_order_id: ClientOrderId) -> Option<PositionId> {
951 self.0.borrow().position_id(&client_order_id).copied()
952 }
953
954 #[pyo3(name = "positions", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
955 fn py_positions(
956 &self,
957 py: Python,
958 venue: Option<Venue>,
959 instrument_id: Option<InstrumentId>,
960 strategy_id: Option<StrategyId>,
961 account_id: Option<AccountId>,
962 side: Option<PositionSide>,
963 ) -> PyResult<Vec<Py<PyAny>>> {
964 let cache = self.0.borrow();
965 cache
966 .positions(
967 venue.as_ref(),
968 instrument_id.as_ref(),
969 strategy_id.as_ref(),
970 account_id.as_ref(),
971 side,
972 )
973 .into_iter()
974 .map(|p| Ok(p.clone().into_pyobject(py)?.into()))
975 .collect()
976 }
977
978 #[pyo3(name = "positions_open", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
979 fn py_positions_open(
980 &self,
981 py: Python,
982 venue: Option<Venue>,
983 instrument_id: Option<InstrumentId>,
984 strategy_id: Option<StrategyId>,
985 account_id: Option<AccountId>,
986 side: Option<PositionSide>,
987 ) -> PyResult<Vec<Py<PyAny>>> {
988 let cache = self.0.borrow();
989 cache
990 .positions_open(
991 venue.as_ref(),
992 instrument_id.as_ref(),
993 strategy_id.as_ref(),
994 account_id.as_ref(),
995 side,
996 )
997 .into_iter()
998 .map(|p| Ok(p.clone().into_pyobject(py)?.into()))
999 .collect()
1000 }
1001
1002 #[pyo3(name = "positions_closed", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
1003 fn py_positions_closed(
1004 &self,
1005 py: Python,
1006 venue: Option<Venue>,
1007 instrument_id: Option<InstrumentId>,
1008 strategy_id: Option<StrategyId>,
1009 account_id: Option<AccountId>,
1010 side: Option<PositionSide>,
1011 ) -> PyResult<Vec<Py<PyAny>>> {
1012 let cache = self.0.borrow();
1013 cache
1014 .positions_closed(
1015 venue.as_ref(),
1016 instrument_id.as_ref(),
1017 strategy_id.as_ref(),
1018 account_id.as_ref(),
1019 side,
1020 )
1021 .into_iter()
1022 .map(|p| Ok(p.clone().into_pyobject(py)?.into()))
1023 .collect()
1024 }
1025
1026 #[pyo3(name = "position_exists")]
1027 fn py_position_exists(&self, position_id: PositionId) -> bool {
1028 self.0.borrow().position_exists(&position_id)
1029 }
1030
1031 #[pyo3(name = "is_position_open")]
1032 fn py_is_position_open(&self, position_id: PositionId) -> bool {
1033 self.0.borrow().is_position_open(&position_id)
1034 }
1035
1036 #[pyo3(name = "is_position_closed")]
1037 fn py_is_position_closed(&self, position_id: PositionId) -> bool {
1038 self.0.borrow().is_position_closed(&position_id)
1039 }
1040
1041 #[pyo3(name = "positions_open_count", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
1042 fn py_positions_open_count(
1043 &self,
1044 venue: Option<Venue>,
1045 instrument_id: Option<InstrumentId>,
1046 strategy_id: Option<StrategyId>,
1047 account_id: Option<AccountId>,
1048 side: Option<PositionSide>,
1049 ) -> usize {
1050 self.0.borrow().positions_open_count(
1051 venue.as_ref(),
1052 instrument_id.as_ref(),
1053 strategy_id.as_ref(),
1054 account_id.as_ref(),
1055 side,
1056 )
1057 }
1058
1059 #[pyo3(name = "positions_closed_count", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
1060 fn py_positions_closed_count(
1061 &self,
1062 venue: Option<Venue>,
1063 instrument_id: Option<InstrumentId>,
1064 strategy_id: Option<StrategyId>,
1065 account_id: Option<AccountId>,
1066 side: Option<PositionSide>,
1067 ) -> usize {
1068 self.0.borrow().positions_closed_count(
1069 venue.as_ref(),
1070 instrument_id.as_ref(),
1071 strategy_id.as_ref(),
1072 account_id.as_ref(),
1073 side,
1074 )
1075 }
1076
1077 #[pyo3(name = "positions_total_count", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
1078 fn py_positions_total_count(
1079 &self,
1080 venue: Option<Venue>,
1081 instrument_id: Option<InstrumentId>,
1082 strategy_id: Option<StrategyId>,
1083 account_id: Option<AccountId>,
1084 side: Option<PositionSide>,
1085 ) -> usize {
1086 self.0.borrow().positions_total_count(
1087 venue.as_ref(),
1088 instrument_id.as_ref(),
1089 strategy_id.as_ref(),
1090 account_id.as_ref(),
1091 side,
1092 )
1093 }
1094
1095 #[pyo3(name = "strategy_id_for_order")]
1096 fn py_strategy_id_for_order(&self, client_order_id: ClientOrderId) -> Option<StrategyId> {
1097 self.0
1098 .borrow()
1099 .strategy_id_for_order(&client_order_id)
1100 .copied()
1101 }
1102
1103 #[pyo3(name = "strategy_id_for_position")]
1104 fn py_strategy_id_for_position(&self, position_id: PositionId) -> Option<StrategyId> {
1105 self.0
1106 .borrow()
1107 .strategy_id_for_position(&position_id)
1108 .copied()
1109 }
1110
1111 #[pyo3(name = "position_snapshot_bytes")]
1112 fn py_position_snapshot_bytes(&self, position_id: PositionId) -> Option<Vec<Vec<u8>>> {
1113 self.0.borrow().position_snapshot_bytes(&position_id)
1114 }
1115
1116 #[pyo3(name = "snapshot_position")]
1117 #[expect(clippy::needless_pass_by_value)]
1118 fn py_snapshot_position(&self, py: Python, position: Py<PyAny>) -> PyResult<()> {
1119 let position_obj = position.extract::<Position>(py)?;
1120 self.0
1121 .borrow_mut()
1122 .snapshot_position(&position_obj)
1123 .map(|_| ())
1124 .map_err(to_pyvalue_err)
1125 }
1126
1127 #[pyo3(name = "position_snapshots", signature = (position_id=None, account_id=None))]
1128 fn py_position_snapshots(
1129 &self,
1130 py: Python,
1131 position_id: Option<PositionId>,
1132 account_id: Option<AccountId>,
1133 ) -> PyResult<Vec<Py<PyAny>>> {
1134 let cache = self.0.borrow();
1135 cache
1136 .position_snapshots(position_id.as_ref(), account_id.as_ref())
1137 .into_iter()
1138 .map(|p| Ok(p.into_pyobject(py)?.into()))
1139 .collect()
1140 }
1141}
1142
1143#[cfg(feature = "defi")]
1144#[pymethods]
1145#[pyo3_stub_gen::derive::gen_stub_pymethods]
1146impl PyCache {
1147 #[pyo3(name = "pool")]
1148 fn py_pool(&self, instrument_id: InstrumentId) -> Option<Pool> {
1149 self.0
1150 .try_borrow()
1151 .ok()
1152 .and_then(|cache| cache.pool(&instrument_id).cloned())
1153 }
1154
1155 #[pyo3(name = "pool_profiler")]
1156 fn py_pool_profiler(&self, instrument_id: InstrumentId) -> Option<PoolProfiler> {
1157 self.0
1158 .try_borrow()
1159 .ok()
1160 .and_then(|cache| cache.pool_profiler(&instrument_id).cloned())
1161 }
1162}
1163
1164#[pymethods]
1165#[pyo3_stub_gen::derive::gen_stub_pymethods]
1166impl CacheConfig {
1167 #[new]
1169 #[expect(clippy::too_many_arguments)]
1170 #[pyo3(signature = (
1171 encoding=None,
1172 timestamps_as_iso8601=None,
1173 buffer_interval_ms=None,
1174 bulk_read_batch_size=None,
1175 use_trader_prefix=None,
1176 use_instance_id=None,
1177 flush_on_start=None,
1178 drop_instruments_on_reset=None,
1179 tick_capacity=None,
1180 bar_capacity=None,
1181 save_market_data=None,
1182 persist_account_events=None,
1183 ))]
1184 fn py_new(
1185 encoding: Option<SerializationEncoding>,
1186 timestamps_as_iso8601: Option<bool>,
1187 buffer_interval_ms: Option<usize>,
1188 bulk_read_batch_size: Option<usize>,
1189 use_trader_prefix: Option<bool>,
1190 use_instance_id: Option<bool>,
1191 flush_on_start: Option<bool>,
1192 drop_instruments_on_reset: Option<bool>,
1193 tick_capacity: Option<usize>,
1194 bar_capacity: Option<usize>,
1195 save_market_data: Option<bool>,
1196 persist_account_events: Option<bool>,
1197 ) -> Self {
1198 Self::new(
1199 None, encoding.unwrap_or(SerializationEncoding::MsgPack),
1201 timestamps_as_iso8601.unwrap_or(false),
1202 buffer_interval_ms,
1203 bulk_read_batch_size,
1204 use_trader_prefix.unwrap_or(true),
1205 use_instance_id.unwrap_or(false),
1206 flush_on_start.unwrap_or(false),
1207 drop_instruments_on_reset.unwrap_or(true),
1208 tick_capacity.unwrap_or(10_000),
1209 bar_capacity.unwrap_or(10_000),
1210 persist_account_events.unwrap_or(true),
1211 save_market_data.unwrap_or(false),
1212 )
1213 }
1214
1215 fn __str__(&self) -> String {
1216 format!("{self:?}")
1217 }
1218
1219 fn __repr__(&self) -> String {
1220 format!("{self:?}")
1221 }
1222
1223 #[getter]
1224 fn encoding(&self) -> SerializationEncoding {
1225 self.encoding
1226 }
1227
1228 #[getter]
1229 fn timestamps_as_iso8601(&self) -> bool {
1230 self.timestamps_as_iso8601
1231 }
1232
1233 #[getter]
1234 fn buffer_interval_ms(&self) -> Option<usize> {
1235 self.buffer_interval_ms
1236 }
1237
1238 #[getter]
1239 fn bulk_read_batch_size(&self) -> Option<usize> {
1240 self.bulk_read_batch_size
1241 }
1242
1243 #[getter]
1244 fn use_trader_prefix(&self) -> bool {
1245 self.use_trader_prefix
1246 }
1247
1248 #[getter]
1249 fn use_instance_id(&self) -> bool {
1250 self.use_instance_id
1251 }
1252
1253 #[getter]
1254 fn flush_on_start(&self) -> bool {
1255 self.flush_on_start
1256 }
1257
1258 #[getter]
1259 fn drop_instruments_on_reset(&self) -> bool {
1260 self.drop_instruments_on_reset
1261 }
1262
1263 #[getter]
1264 fn tick_capacity(&self) -> usize {
1265 self.tick_capacity
1266 }
1267
1268 #[getter]
1269 fn bar_capacity(&self) -> usize {
1270 self.bar_capacity
1271 }
1272
1273 #[getter]
1274 fn persist_account_events(&self) -> bool {
1275 self.persist_account_events
1276 }
1277
1278 #[getter]
1279 fn save_market_data(&self) -> bool {
1280 self.save_market_data
1281 }
1282}
1283
1284#[pymethods]
1285impl Cache {
1286 #[new]
1288 fn py_new(config: Option<CacheConfig>) -> Self {
1289 Self::new(config, None)
1290 }
1291
1292 fn __repr__(&self) -> String {
1293 format!("{self:?}")
1294 }
1295
1296 #[pyo3(name = "reset")]
1302 fn py_reset(&mut self) {
1303 self.reset();
1304 }
1305
1306 #[pyo3(name = "dispose")]
1310 fn py_dispose(&mut self) {
1311 self.dispose();
1312 }
1313
1314 #[pyo3(name = "add_currency")]
1320 fn py_add_currency(&mut self, currency: Currency) -> PyResult<()> {
1321 self.add_currency(currency).map_err(to_pyvalue_err)
1322 }
1323
1324 #[pyo3(name = "add_instrument")]
1330 fn py_add_instrument(&mut self, py: Python, instrument: Py<PyAny>) -> PyResult<()> {
1331 let instrument_any = pyobject_to_instrument_any(py, instrument)?;
1332 self.add_instrument(instrument_any).map_err(to_pyvalue_err)
1333 }
1334
1335 #[pyo3(name = "instrument")]
1337 fn py_instrument(
1338 &self,
1339 py: Python,
1340 instrument_id: InstrumentId,
1341 ) -> PyResult<Option<Py<PyAny>>> {
1342 match self.instrument(&instrument_id) {
1343 Some(instrument) => Ok(Some(instrument_any_to_pyobject(py, instrument.clone())?)),
1344 None => Ok(None),
1345 }
1346 }
1347
1348 #[pyo3(name = "instrument_ids")]
1350 fn py_instrument_ids(&self, venue: Option<Venue>) -> Vec<InstrumentId> {
1351 self.instrument_ids(venue.as_ref())
1352 .into_iter()
1353 .copied()
1354 .collect()
1355 }
1356
1357 #[pyo3(name = "instruments")]
1359 fn py_instruments(&self, py: Python, venue: Option<Venue>) -> PyResult<Vec<Py<PyAny>>> {
1360 let mut py_instruments = Vec::new();
1361
1362 if let Some(venue) = venue {
1363 let instruments = self.instruments(&venue, None);
1364 for instrument in instruments {
1365 py_instruments.push(instrument_any_to_pyobject(py, (*instrument).clone())?);
1366 }
1367 } else {
1368 let instrument_ids = self.instrument_ids(None);
1369 for instrument_id in instrument_ids {
1370 if let Some(instrument) = self.instrument(instrument_id) {
1371 py_instruments.push(instrument_any_to_pyobject(py, instrument.clone())?);
1372 }
1373 }
1374 }
1375
1376 Ok(py_instruments)
1377 }
1378
1379 #[pyo3(name = "add_order")]
1387 fn py_add_order(
1388 &mut self,
1389 py: Python,
1390 order: Py<PyAny>,
1391 position_id: Option<PositionId>,
1392 client_id: Option<ClientId>,
1393 replace_existing: Option<bool>,
1394 ) -> PyResult<()> {
1395 let order_any = pyobject_to_order_any(py, order)?;
1396 self.add_order(
1397 order_any,
1398 position_id,
1399 client_id,
1400 replace_existing.unwrap_or(false),
1401 )
1402 .map_err(to_pyvalue_err)
1403 }
1404
1405 #[pyo3(name = "order")]
1412 fn py_order(&self, py: Python, client_order_id: ClientOrderId) -> PyResult<Option<Py<PyAny>>> {
1413 match self.order(&client_order_id) {
1414 Some(order) => Ok(Some(order_any_to_pyobject(py, order.clone())?)),
1415 None => Ok(None),
1416 }
1417 }
1418
1419 #[pyo3(name = "order_exists")]
1421 fn py_order_exists(&self, client_order_id: ClientOrderId) -> bool {
1422 self.order_exists(&client_order_id)
1423 }
1424
1425 #[pyo3(name = "is_order_open")]
1427 fn py_is_order_open(&self, client_order_id: ClientOrderId) -> bool {
1428 self.is_order_open(&client_order_id)
1429 }
1430
1431 #[pyo3(name = "is_order_closed")]
1433 fn py_is_order_closed(&self, client_order_id: ClientOrderId) -> bool {
1434 self.is_order_closed(&client_order_id)
1435 }
1436
1437 #[pyo3(name = "is_order_active_local")]
1442 fn py_is_order_active_local(&self, client_order_id: ClientOrderId) -> bool {
1443 self.is_order_active_local(&client_order_id)
1444 }
1445
1446 #[pyo3(name = "orders_active_local")]
1451 fn py_orders_active_local(
1452 &self,
1453 py: Python,
1454 venue: Option<Venue>,
1455 instrument_id: Option<InstrumentId>,
1456 strategy_id: Option<StrategyId>,
1457 account_id: Option<AccountId>,
1458 side: Option<OrderSide>,
1459 ) -> PyResult<Vec<Py<PyAny>>> {
1460 self.orders_active_local(
1461 venue.as_ref(),
1462 instrument_id.as_ref(),
1463 strategy_id.as_ref(),
1464 account_id.as_ref(),
1465 side,
1466 )
1467 .into_iter()
1468 .map(|order| order_any_to_pyobject(py, order.clone()))
1469 .collect()
1470 }
1471
1472 #[pyo3(name = "orders_active_local_count")]
1477 fn py_orders_active_local_count(
1478 &self,
1479 venue: Option<Venue>,
1480 instrument_id: Option<InstrumentId>,
1481 strategy_id: Option<StrategyId>,
1482 account_id: Option<AccountId>,
1483 side: Option<OrderSide>,
1484 ) -> usize {
1485 self.orders_active_local_count(
1486 venue.as_ref(),
1487 instrument_id.as_ref(),
1488 strategy_id.as_ref(),
1489 account_id.as_ref(),
1490 side,
1491 )
1492 }
1493
1494 #[pyo3(name = "orders_open_count")]
1496 fn py_orders_open_count(
1497 &self,
1498 venue: Option<Venue>,
1499 instrument_id: Option<InstrumentId>,
1500 strategy_id: Option<StrategyId>,
1501 account_id: Option<AccountId>,
1502 side: Option<OrderSide>,
1503 ) -> usize {
1504 self.orders_open_count(
1505 venue.as_ref(),
1506 instrument_id.as_ref(),
1507 strategy_id.as_ref(),
1508 account_id.as_ref(),
1509 side,
1510 )
1511 }
1512
1513 #[pyo3(name = "orders_closed_count")]
1515 fn py_orders_closed_count(
1516 &self,
1517 venue: Option<Venue>,
1518 instrument_id: Option<InstrumentId>,
1519 strategy_id: Option<StrategyId>,
1520 account_id: Option<AccountId>,
1521 side: Option<OrderSide>,
1522 ) -> usize {
1523 self.orders_closed_count(
1524 venue.as_ref(),
1525 instrument_id.as_ref(),
1526 strategy_id.as_ref(),
1527 account_id.as_ref(),
1528 side,
1529 )
1530 }
1531
1532 #[pyo3(name = "orders_total_count")]
1534 fn py_orders_total_count(
1535 &self,
1536 venue: Option<Venue>,
1537 instrument_id: Option<InstrumentId>,
1538 strategy_id: Option<StrategyId>,
1539 account_id: Option<AccountId>,
1540 side: Option<OrderSide>,
1541 ) -> usize {
1542 self.orders_total_count(
1543 venue.as_ref(),
1544 instrument_id.as_ref(),
1545 strategy_id.as_ref(),
1546 account_id.as_ref(),
1547 side,
1548 )
1549 }
1550
1551 #[pyo3(name = "add_position")]
1553 #[expect(clippy::needless_pass_by_value)]
1554 fn py_add_position(
1555 &mut self,
1556 py: Python,
1557 position: Py<PyAny>,
1558 oms_type: OmsType,
1559 ) -> PyResult<()> {
1560 let position_obj = position.extract::<Position>(py)?;
1561 self.add_position(&position_obj, oms_type)
1562 .map_err(to_pyvalue_err)
1563 }
1564
1565 #[pyo3(name = "snapshot_position")]
1572 #[expect(clippy::needless_pass_by_value)]
1573 fn py_snapshot_position(&mut self, py: Python, position: Py<PyAny>) -> PyResult<()> {
1574 let position_obj = position.extract::<Position>(py)?;
1575 self.snapshot_position(&position_obj)
1576 .map(|_| ())
1577 .map_err(to_pyvalue_err)
1578 }
1579
1580 #[pyo3(name = "position")]
1582 fn py_position(&self, py: Python, position_id: PositionId) -> PyResult<Option<Py<PyAny>>> {
1583 match self.position(&position_id) {
1584 Some(position) => Ok(Some(position.clone().into_pyobject(py)?.into())),
1585 None => Ok(None),
1586 }
1587 }
1588
1589 #[pyo3(name = "position_exists")]
1591 fn py_position_exists(&self, position_id: PositionId) -> bool {
1592 self.position_exists(&position_id)
1593 }
1594
1595 #[pyo3(name = "is_position_open")]
1597 fn py_is_position_open(&self, position_id: PositionId) -> bool {
1598 self.is_position_open(&position_id)
1599 }
1600
1601 #[pyo3(name = "is_position_closed")]
1603 fn py_is_position_closed(&self, position_id: PositionId) -> bool {
1604 self.is_position_closed(&position_id)
1605 }
1606
1607 #[pyo3(name = "positions_open_count")]
1609 fn py_positions_open_count(
1610 &self,
1611 venue: Option<Venue>,
1612 instrument_id: Option<InstrumentId>,
1613 strategy_id: Option<StrategyId>,
1614 account_id: Option<AccountId>,
1615 side: Option<PositionSide>,
1616 ) -> usize {
1617 self.positions_open_count(
1618 venue.as_ref(),
1619 instrument_id.as_ref(),
1620 strategy_id.as_ref(),
1621 account_id.as_ref(),
1622 side,
1623 )
1624 }
1625
1626 #[pyo3(name = "positions_closed_count")]
1628 fn py_positions_closed_count(
1629 &self,
1630 venue: Option<Venue>,
1631 instrument_id: Option<InstrumentId>,
1632 strategy_id: Option<StrategyId>,
1633 account_id: Option<AccountId>,
1634 side: Option<PositionSide>,
1635 ) -> usize {
1636 self.positions_closed_count(
1637 venue.as_ref(),
1638 instrument_id.as_ref(),
1639 strategy_id.as_ref(),
1640 account_id.as_ref(),
1641 side,
1642 )
1643 }
1644
1645 #[pyo3(name = "positions_total_count")]
1647 fn py_positions_total_count(
1648 &self,
1649 venue: Option<Venue>,
1650 instrument_id: Option<InstrumentId>,
1651 strategy_id: Option<StrategyId>,
1652 account_id: Option<AccountId>,
1653 side: Option<PositionSide>,
1654 ) -> usize {
1655 self.positions_total_count(
1656 venue.as_ref(),
1657 instrument_id.as_ref(),
1658 strategy_id.as_ref(),
1659 account_id.as_ref(),
1660 side,
1661 )
1662 }
1663
1664 #[pyo3(name = "add_quote")]
1670 fn py_add_quote(&mut self, quote: QuoteTick) -> PyResult<()> {
1671 self.add_quote(quote).map_err(to_pyvalue_err)
1672 }
1673
1674 #[pyo3(name = "add_trade")]
1680 fn py_add_trade(&mut self, trade: TradeTick) -> PyResult<()> {
1681 self.add_trade(trade).map_err(to_pyvalue_err)
1682 }
1683
1684 #[pyo3(name = "add_bar")]
1690 fn py_add_bar(&mut self, bar: Bar) -> PyResult<()> {
1691 self.add_bar(bar).map_err(to_pyvalue_err)
1692 }
1693
1694 #[pyo3(name = "quote")]
1696 fn py_quote(&self, instrument_id: InstrumentId) -> Option<QuoteTick> {
1697 self.quote(&instrument_id).copied()
1698 }
1699
1700 #[pyo3(name = "trade")]
1702 fn py_trade(&self, instrument_id: InstrumentId) -> Option<TradeTick> {
1703 self.trade(&instrument_id).copied()
1704 }
1705
1706 #[pyo3(name = "bar")]
1708 fn py_bar(&self, bar_type: BarType) -> Option<Bar> {
1709 self.bar(&bar_type).copied()
1710 }
1711
1712 #[pyo3(name = "quotes")]
1714 fn py_quotes(&self, instrument_id: InstrumentId) -> Option<Vec<QuoteTick>> {
1715 self.quotes(&instrument_id)
1716 }
1717
1718 #[pyo3(name = "trades")]
1720 fn py_trades(&self, instrument_id: InstrumentId) -> Option<Vec<TradeTick>> {
1721 self.trades(&instrument_id)
1722 }
1723
1724 #[pyo3(name = "bars")]
1726 fn py_bars(&self, bar_type: BarType) -> Option<Vec<Bar>> {
1727 self.bars(&bar_type)
1728 }
1729
1730 #[pyo3(name = "has_quote_ticks")]
1732 fn py_has_quote_ticks(&self, instrument_id: InstrumentId) -> bool {
1733 self.has_quote_ticks(&instrument_id)
1734 }
1735
1736 #[pyo3(name = "has_trade_ticks")]
1738 fn py_has_trade_ticks(&self, instrument_id: InstrumentId) -> bool {
1739 self.has_trade_ticks(&instrument_id)
1740 }
1741
1742 #[pyo3(name = "has_bars")]
1744 fn py_has_bars(&self, bar_type: BarType) -> bool {
1745 self.has_bars(&bar_type)
1746 }
1747
1748 #[pyo3(name = "quote_count")]
1750 fn py_quote_count(&self, instrument_id: InstrumentId) -> usize {
1751 self.quote_count(&instrument_id)
1752 }
1753
1754 #[pyo3(name = "trade_count")]
1756 fn py_trade_count(&self, instrument_id: InstrumentId) -> usize {
1757 self.trade_count(&instrument_id)
1758 }
1759
1760 #[pyo3(name = "bar_count")]
1762 fn py_bar_count(&self, bar_type: BarType) -> usize {
1763 self.bar_count(&bar_type)
1764 }
1765
1766 #[pyo3(name = "mark_price")]
1768 fn py_mark_price(&self, instrument_id: InstrumentId) -> Option<MarkPriceUpdate> {
1769 self.mark_price(&instrument_id).copied()
1770 }
1771
1772 #[pyo3(name = "mark_prices")]
1774 fn py_mark_prices(&self, instrument_id: InstrumentId) -> Option<Vec<MarkPriceUpdate>> {
1775 self.mark_prices(&instrument_id)
1776 }
1777
1778 #[pyo3(name = "index_price")]
1780 fn py_index_price(&self, instrument_id: InstrumentId) -> Option<IndexPriceUpdate> {
1781 self.index_price(&instrument_id).copied()
1782 }
1783
1784 #[pyo3(name = "index_prices")]
1786 fn py_index_prices(&self, instrument_id: InstrumentId) -> Option<Vec<IndexPriceUpdate>> {
1787 self.index_prices(&instrument_id)
1788 }
1789
1790 #[pyo3(name = "funding_rate")]
1792 fn py_funding_rate(&self, instrument_id: InstrumentId) -> Option<FundingRateUpdate> {
1793 self.funding_rate(&instrument_id).copied()
1794 }
1795
1796 #[pyo3(name = "instrument_status")]
1798 fn py_instrument_status(&self, instrument_id: InstrumentId) -> Option<InstrumentStatus> {
1799 self.instrument_status(&instrument_id).copied()
1800 }
1801
1802 #[pyo3(name = "instrument_statuses")]
1804 fn py_instrument_statuses(&self, instrument_id: InstrumentId) -> Option<Vec<InstrumentStatus>> {
1805 self.instrument_statuses(&instrument_id)
1806 }
1807
1808 #[pyo3(name = "order_book")]
1810 fn py_order_book(&self, instrument_id: InstrumentId) -> Option<OrderBook> {
1811 self.order_book(&instrument_id).cloned()
1812 }
1813
1814 #[pyo3(name = "has_order_book")]
1816 fn py_has_order_book(&self, instrument_id: InstrumentId) -> bool {
1817 self.has_order_book(&instrument_id)
1818 }
1819
1820 #[pyo3(name = "book_update_count")]
1822 fn py_book_update_count(&self, instrument_id: InstrumentId) -> usize {
1823 self.book_update_count(&instrument_id)
1824 }
1825
1826 #[pyo3(name = "synthetic")]
1828 fn py_synthetic(&self, instrument_id: InstrumentId) -> Option<SyntheticInstrument> {
1829 self.synthetic(&instrument_id).cloned()
1830 }
1831
1832 #[pyo3(name = "synthetic_ids")]
1834 fn py_synthetic_ids(&self) -> Vec<InstrumentId> {
1835 self.synthetic_ids().into_iter().copied().collect()
1836 }
1837
1838 #[pyo3(name = "client_order_ids")]
1840 fn py_client_order_ids(
1841 &self,
1842 venue: Option<Venue>,
1843 instrument_id: Option<InstrumentId>,
1844 strategy_id: Option<StrategyId>,
1845 account_id: Option<AccountId>,
1846 ) -> Vec<ClientOrderId> {
1847 self.client_order_ids(
1848 venue.as_ref(),
1849 instrument_id.as_ref(),
1850 strategy_id.as_ref(),
1851 account_id.as_ref(),
1852 )
1853 .into_iter()
1854 .collect()
1855 }
1856
1857 #[pyo3(name = "client_order_ids_open")]
1859 fn py_client_order_ids_open(
1860 &self,
1861 venue: Option<Venue>,
1862 instrument_id: Option<InstrumentId>,
1863 strategy_id: Option<StrategyId>,
1864 account_id: Option<AccountId>,
1865 ) -> Vec<ClientOrderId> {
1866 self.client_order_ids_open(
1867 venue.as_ref(),
1868 instrument_id.as_ref(),
1869 strategy_id.as_ref(),
1870 account_id.as_ref(),
1871 )
1872 .into_iter()
1873 .collect()
1874 }
1875
1876 #[pyo3(name = "client_order_ids_closed")]
1878 fn py_client_order_ids_closed(
1879 &self,
1880 venue: Option<Venue>,
1881 instrument_id: Option<InstrumentId>,
1882 strategy_id: Option<StrategyId>,
1883 account_id: Option<AccountId>,
1884 ) -> Vec<ClientOrderId> {
1885 self.client_order_ids_closed(
1886 venue.as_ref(),
1887 instrument_id.as_ref(),
1888 strategy_id.as_ref(),
1889 account_id.as_ref(),
1890 )
1891 .into_iter()
1892 .collect()
1893 }
1894
1895 #[pyo3(name = "client_order_ids_emulated")]
1897 fn py_client_order_ids_emulated(
1898 &self,
1899 venue: Option<Venue>,
1900 instrument_id: Option<InstrumentId>,
1901 strategy_id: Option<StrategyId>,
1902 account_id: Option<AccountId>,
1903 ) -> Vec<ClientOrderId> {
1904 self.client_order_ids_emulated(
1905 venue.as_ref(),
1906 instrument_id.as_ref(),
1907 strategy_id.as_ref(),
1908 account_id.as_ref(),
1909 )
1910 .into_iter()
1911 .collect()
1912 }
1913
1914 #[pyo3(name = "client_order_ids_inflight")]
1916 fn py_client_order_ids_inflight(
1917 &self,
1918 venue: Option<Venue>,
1919 instrument_id: Option<InstrumentId>,
1920 strategy_id: Option<StrategyId>,
1921 account_id: Option<AccountId>,
1922 ) -> Vec<ClientOrderId> {
1923 self.client_order_ids_inflight(
1924 venue.as_ref(),
1925 instrument_id.as_ref(),
1926 strategy_id.as_ref(),
1927 account_id.as_ref(),
1928 )
1929 .into_iter()
1930 .collect()
1931 }
1932
1933 #[pyo3(name = "position_ids")]
1935 fn py_position_ids(
1936 &self,
1937 venue: Option<Venue>,
1938 instrument_id: Option<InstrumentId>,
1939 strategy_id: Option<StrategyId>,
1940 account_id: Option<AccountId>,
1941 ) -> Vec<PositionId> {
1942 self.position_ids(
1943 venue.as_ref(),
1944 instrument_id.as_ref(),
1945 strategy_id.as_ref(),
1946 account_id.as_ref(),
1947 )
1948 .into_iter()
1949 .collect()
1950 }
1951
1952 #[pyo3(name = "position_open_ids")]
1954 fn py_position_open_ids(
1955 &self,
1956 venue: Option<Venue>,
1957 instrument_id: Option<InstrumentId>,
1958 strategy_id: Option<StrategyId>,
1959 account_id: Option<AccountId>,
1960 ) -> Vec<PositionId> {
1961 self.position_open_ids(
1962 venue.as_ref(),
1963 instrument_id.as_ref(),
1964 strategy_id.as_ref(),
1965 account_id.as_ref(),
1966 )
1967 .into_iter()
1968 .collect()
1969 }
1970
1971 #[pyo3(name = "position_closed_ids")]
1973 fn py_position_closed_ids(
1974 &self,
1975 venue: Option<Venue>,
1976 instrument_id: Option<InstrumentId>,
1977 strategy_id: Option<StrategyId>,
1978 account_id: Option<AccountId>,
1979 ) -> Vec<PositionId> {
1980 self.position_closed_ids(
1981 venue.as_ref(),
1982 instrument_id.as_ref(),
1983 strategy_id.as_ref(),
1984 account_id.as_ref(),
1985 )
1986 .into_iter()
1987 .collect()
1988 }
1989
1990 #[pyo3(name = "actor_ids")]
1992 fn py_actor_ids(&self) -> Vec<ComponentId> {
1993 self.actor_ids().into_iter().collect()
1994 }
1995
1996 #[pyo3(name = "strategy_ids")]
1998 fn py_strategy_ids(&self) -> Vec<StrategyId> {
1999 self.strategy_ids().into_iter().collect()
2000 }
2001
2002 #[pyo3(name = "exec_algorithm_ids")]
2004 fn py_exec_algorithm_ids(&self) -> Vec<ExecAlgorithmId> {
2005 self.exec_algorithm_ids().into_iter().collect()
2006 }
2007
2008 #[pyo3(name = "client_order_id")]
2010 fn py_client_order_id(&self, venue_order_id: VenueOrderId) -> Option<ClientOrderId> {
2011 self.client_order_id(&venue_order_id).copied()
2012 }
2013
2014 #[pyo3(name = "venue_order_id")]
2016 fn py_venue_order_id(&self, client_order_id: ClientOrderId) -> Option<VenueOrderId> {
2017 self.venue_order_id(&client_order_id).copied()
2018 }
2019
2020 #[pyo3(name = "client_id")]
2022 fn py_client_id(&self, client_order_id: ClientOrderId) -> Option<ClientId> {
2023 self.client_id(&client_order_id).copied()
2024 }
2025
2026 #[pyo3(name = "orders")]
2032 fn py_orders(
2033 &self,
2034 py: Python,
2035 venue: Option<Venue>,
2036 instrument_id: Option<InstrumentId>,
2037 strategy_id: Option<StrategyId>,
2038 account_id: Option<AccountId>,
2039 side: Option<OrderSide>,
2040 ) -> PyResult<Vec<Py<PyAny>>> {
2041 self.orders(
2042 venue.as_ref(),
2043 instrument_id.as_ref(),
2044 strategy_id.as_ref(),
2045 account_id.as_ref(),
2046 side,
2047 )
2048 .into_iter()
2049 .map(|o| order_any_to_pyobject(py, o.clone()))
2050 .collect()
2051 }
2052
2053 #[pyo3(name = "orders_open")]
2055 fn py_orders_open(
2056 &self,
2057 py: Python,
2058 venue: Option<Venue>,
2059 instrument_id: Option<InstrumentId>,
2060 strategy_id: Option<StrategyId>,
2061 account_id: Option<AccountId>,
2062 side: Option<OrderSide>,
2063 ) -> PyResult<Vec<Py<PyAny>>> {
2064 self.orders_open(
2065 venue.as_ref(),
2066 instrument_id.as_ref(),
2067 strategy_id.as_ref(),
2068 account_id.as_ref(),
2069 side,
2070 )
2071 .into_iter()
2072 .map(|o| order_any_to_pyobject(py, o.clone()))
2073 .collect()
2074 }
2075
2076 #[pyo3(name = "orders_closed")]
2078 fn py_orders_closed(
2079 &self,
2080 py: Python,
2081 venue: Option<Venue>,
2082 instrument_id: Option<InstrumentId>,
2083 strategy_id: Option<StrategyId>,
2084 account_id: Option<AccountId>,
2085 side: Option<OrderSide>,
2086 ) -> PyResult<Vec<Py<PyAny>>> {
2087 self.orders_closed(
2088 venue.as_ref(),
2089 instrument_id.as_ref(),
2090 strategy_id.as_ref(),
2091 account_id.as_ref(),
2092 side,
2093 )
2094 .into_iter()
2095 .map(|o| order_any_to_pyobject(py, o.clone()))
2096 .collect()
2097 }
2098
2099 #[pyo3(name = "orders_emulated")]
2101 fn py_orders_emulated(
2102 &self,
2103 py: Python,
2104 venue: Option<Venue>,
2105 instrument_id: Option<InstrumentId>,
2106 strategy_id: Option<StrategyId>,
2107 account_id: Option<AccountId>,
2108 side: Option<OrderSide>,
2109 ) -> PyResult<Vec<Py<PyAny>>> {
2110 self.orders_emulated(
2111 venue.as_ref(),
2112 instrument_id.as_ref(),
2113 strategy_id.as_ref(),
2114 account_id.as_ref(),
2115 side,
2116 )
2117 .into_iter()
2118 .map(|o| order_any_to_pyobject(py, o.clone()))
2119 .collect()
2120 }
2121
2122 #[pyo3(name = "orders_inflight")]
2124 fn py_orders_inflight(
2125 &self,
2126 py: Python,
2127 venue: Option<Venue>,
2128 instrument_id: Option<InstrumentId>,
2129 strategy_id: Option<StrategyId>,
2130 account_id: Option<AccountId>,
2131 side: Option<OrderSide>,
2132 ) -> PyResult<Vec<Py<PyAny>>> {
2133 self.orders_inflight(
2134 venue.as_ref(),
2135 instrument_id.as_ref(),
2136 strategy_id.as_ref(),
2137 account_id.as_ref(),
2138 side,
2139 )
2140 .into_iter()
2141 .map(|o| order_any_to_pyobject(py, o.clone()))
2142 .collect()
2143 }
2144
2145 #[pyo3(name = "orders_for_position")]
2147 fn py_orders_for_position(
2148 &self,
2149 py: Python,
2150 position_id: PositionId,
2151 ) -> PyResult<Vec<Py<PyAny>>> {
2152 self.orders_for_position(&position_id)
2153 .into_iter()
2154 .map(|o| order_any_to_pyobject(py, o.clone()))
2155 .collect()
2156 }
2157
2158 #[pyo3(name = "is_order_emulated")]
2160 fn py_is_order_emulated(&self, client_order_id: ClientOrderId) -> bool {
2161 self.is_order_emulated(&client_order_id)
2162 }
2163
2164 #[pyo3(name = "is_order_inflight")]
2166 fn py_is_order_inflight(&self, client_order_id: ClientOrderId) -> bool {
2167 self.is_order_inflight(&client_order_id)
2168 }
2169
2170 #[pyo3(name = "is_order_pending_cancel_local")]
2172 fn py_is_order_pending_cancel_local(&self, client_order_id: ClientOrderId) -> bool {
2173 self.is_order_pending_cancel_local(&client_order_id)
2174 }
2175
2176 #[pyo3(name = "orders_emulated_count")]
2178 fn py_orders_emulated_count(
2179 &self,
2180 venue: Option<Venue>,
2181 instrument_id: Option<InstrumentId>,
2182 strategy_id: Option<StrategyId>,
2183 account_id: Option<AccountId>,
2184 side: Option<OrderSide>,
2185 ) -> usize {
2186 self.orders_emulated_count(
2187 venue.as_ref(),
2188 instrument_id.as_ref(),
2189 strategy_id.as_ref(),
2190 account_id.as_ref(),
2191 side,
2192 )
2193 }
2194
2195 #[pyo3(name = "orders_inflight_count")]
2197 fn py_orders_inflight_count(
2198 &self,
2199 venue: Option<Venue>,
2200 instrument_id: Option<InstrumentId>,
2201 strategy_id: Option<StrategyId>,
2202 account_id: Option<AccountId>,
2203 side: Option<OrderSide>,
2204 ) -> usize {
2205 self.orders_inflight_count(
2206 venue.as_ref(),
2207 instrument_id.as_ref(),
2208 strategy_id.as_ref(),
2209 account_id.as_ref(),
2210 side,
2211 )
2212 }
2213
2214 #[pyo3(name = "order_list")]
2216 fn py_order_list(&self, order_list_id: OrderListId) -> Option<OrderList> {
2217 self.order_list(&order_list_id).cloned()
2218 }
2219
2220 #[pyo3(name = "order_lists")]
2222 fn py_order_lists(
2223 &self,
2224 venue: Option<Venue>,
2225 instrument_id: Option<InstrumentId>,
2226 strategy_id: Option<StrategyId>,
2227 account_id: Option<AccountId>,
2228 ) -> Vec<OrderList> {
2229 self.order_lists(
2230 venue.as_ref(),
2231 instrument_id.as_ref(),
2232 strategy_id.as_ref(),
2233 account_id.as_ref(),
2234 )
2235 .into_iter()
2236 .cloned()
2237 .collect()
2238 }
2239
2240 #[pyo3(name = "order_list_exists")]
2242 fn py_order_list_exists(&self, order_list_id: OrderListId) -> bool {
2243 self.order_list_exists(&order_list_id)
2244 }
2245
2246 #[pyo3(name = "orders_for_exec_algorithm")]
2249 #[expect(clippy::too_many_arguments)]
2250 fn py_orders_for_exec_algorithm(
2251 &self,
2252 py: Python,
2253 exec_algorithm_id: ExecAlgorithmId,
2254 venue: Option<Venue>,
2255 instrument_id: Option<InstrumentId>,
2256 strategy_id: Option<StrategyId>,
2257 account_id: Option<AccountId>,
2258 side: Option<OrderSide>,
2259 ) -> PyResult<Vec<Py<PyAny>>> {
2260 self.orders_for_exec_algorithm(
2261 &exec_algorithm_id,
2262 venue.as_ref(),
2263 instrument_id.as_ref(),
2264 strategy_id.as_ref(),
2265 account_id.as_ref(),
2266 side,
2267 )
2268 .into_iter()
2269 .map(|o| order_any_to_pyobject(py, o.clone()))
2270 .collect()
2271 }
2272
2273 #[pyo3(name = "orders_for_exec_spawn")]
2275 fn py_orders_for_exec_spawn(
2276 &self,
2277 py: Python,
2278 exec_spawn_id: ClientOrderId,
2279 ) -> PyResult<Vec<Py<PyAny>>> {
2280 self.orders_for_exec_spawn(&exec_spawn_id)
2281 .into_iter()
2282 .map(|o| order_any_to_pyobject(py, o.clone()))
2283 .collect()
2284 }
2285
2286 #[pyo3(name = "exec_spawn_total_quantity")]
2288 fn py_exec_spawn_total_quantity(
2289 &self,
2290 exec_spawn_id: ClientOrderId,
2291 active_only: bool,
2292 ) -> Option<Quantity> {
2293 self.exec_spawn_total_quantity(&exec_spawn_id, active_only)
2294 }
2295
2296 #[pyo3(name = "exec_spawn_total_filled_qty")]
2298 fn py_exec_spawn_total_filled_qty(
2299 &self,
2300 exec_spawn_id: ClientOrderId,
2301 active_only: bool,
2302 ) -> Option<Quantity> {
2303 self.exec_spawn_total_filled_qty(&exec_spawn_id, active_only)
2304 }
2305
2306 #[pyo3(name = "exec_spawn_total_leaves_qty")]
2308 fn py_exec_spawn_total_leaves_qty(
2309 &self,
2310 exec_spawn_id: ClientOrderId,
2311 active_only: bool,
2312 ) -> Option<Quantity> {
2313 self.exec_spawn_total_leaves_qty(&exec_spawn_id, active_only)
2314 }
2315
2316 #[pyo3(name = "position_for_order")]
2318 fn py_position_for_order(
2319 &self,
2320 py: Python,
2321 client_order_id: ClientOrderId,
2322 ) -> PyResult<Option<Py<PyAny>>> {
2323 match self.position_for_order(&client_order_id) {
2324 Some(position) => Ok(Some(position.clone().into_pyobject(py)?.into())),
2325 None => Ok(None),
2326 }
2327 }
2328
2329 #[pyo3(name = "position_id")]
2331 fn py_position_id(&self, client_order_id: ClientOrderId) -> Option<PositionId> {
2332 self.position_id(&client_order_id).copied()
2333 }
2334
2335 #[pyo3(name = "positions")]
2341 fn py_positions(
2342 &self,
2343 py: Python,
2344 venue: Option<Venue>,
2345 instrument_id: Option<InstrumentId>,
2346 strategy_id: Option<StrategyId>,
2347 account_id: Option<AccountId>,
2348 side: Option<PositionSide>,
2349 ) -> PyResult<Vec<Py<PyAny>>> {
2350 self.positions(
2351 venue.as_ref(),
2352 instrument_id.as_ref(),
2353 strategy_id.as_ref(),
2354 account_id.as_ref(),
2355 side,
2356 )
2357 .into_iter()
2358 .map(|p| Ok(p.clone().into_pyobject(py)?.into()))
2359 .collect()
2360 }
2361
2362 #[pyo3(name = "positions_open")]
2364 fn py_positions_open(
2365 &self,
2366 py: Python,
2367 venue: Option<Venue>,
2368 instrument_id: Option<InstrumentId>,
2369 strategy_id: Option<StrategyId>,
2370 account_id: Option<AccountId>,
2371 side: Option<PositionSide>,
2372 ) -> PyResult<Vec<Py<PyAny>>> {
2373 self.positions_open(
2374 venue.as_ref(),
2375 instrument_id.as_ref(),
2376 strategy_id.as_ref(),
2377 account_id.as_ref(),
2378 side,
2379 )
2380 .into_iter()
2381 .map(|p| Ok(p.clone().into_pyobject(py)?.into()))
2382 .collect()
2383 }
2384
2385 #[pyo3(name = "positions_closed")]
2387 fn py_positions_closed(
2388 &self,
2389 py: Python,
2390 venue: Option<Venue>,
2391 instrument_id: Option<InstrumentId>,
2392 strategy_id: Option<StrategyId>,
2393 account_id: Option<AccountId>,
2394 side: Option<PositionSide>,
2395 ) -> PyResult<Vec<Py<PyAny>>> {
2396 self.positions_closed(
2397 venue.as_ref(),
2398 instrument_id.as_ref(),
2399 strategy_id.as_ref(),
2400 account_id.as_ref(),
2401 side,
2402 )
2403 .into_iter()
2404 .map(|p| Ok(p.clone().into_pyobject(py)?.into()))
2405 .collect()
2406 }
2407
2408 #[pyo3(name = "strategy_id_for_order")]
2410 fn py_strategy_id_for_order(&self, client_order_id: ClientOrderId) -> Option<StrategyId> {
2411 self.strategy_id_for_order(&client_order_id).copied()
2412 }
2413
2414 #[pyo3(name = "strategy_id_for_position")]
2416 fn py_strategy_id_for_position(&self, position_id: PositionId) -> Option<StrategyId> {
2417 self.strategy_id_for_position(&position_id).copied()
2418 }
2419
2420 #[pyo3(name = "position_snapshot_bytes")]
2425 fn py_position_snapshot_bytes(&self, position_id: PositionId) -> Option<Vec<Vec<u8>>> {
2426 self.position_snapshot_bytes(&position_id)
2427 }
2428
2429 #[pyo3(name = "position_snapshots", signature = (position_id=None, account_id=None))]
2435 fn py_position_snapshots(
2436 &self,
2437 py: Python,
2438 position_id: Option<PositionId>,
2439 account_id: Option<AccountId>,
2440 ) -> PyResult<Vec<Py<PyAny>>> {
2441 self.position_snapshots(position_id.as_ref(), account_id.as_ref())
2442 .into_iter()
2443 .map(|p| Ok(p.into_pyobject(py)?.into()))
2444 .collect()
2445 }
2446
2447 #[pyo3(name = "account")]
2449 fn py_account(&self, py: Python, account_id: AccountId) -> PyResult<Option<Py<PyAny>>> {
2450 match self.account(&account_id) {
2451 Some(account) => Ok(Some(account_any_to_pyobject(py, account.clone())?)),
2452 None => Ok(None),
2453 }
2454 }
2455
2456 #[pyo3(name = "account_for_venue")]
2458 fn py_account_for_venue(&self, py: Python, venue: Venue) -> PyResult<Option<Py<PyAny>>> {
2459 match self.account_for_venue(&venue) {
2460 Some(account) => Ok(Some(account_any_to_pyobject(py, account.clone())?)),
2461 None => Ok(None),
2462 }
2463 }
2464
2465 #[pyo3(name = "account_id")]
2467 fn py_account_id(&self, venue: Venue) -> Option<AccountId> {
2468 self.account_id(&venue).copied()
2469 }
2470
2471 #[pyo3(name = "get")]
2477 fn py_get(&self, key: &str) -> PyResult<Option<Vec<u8>>> {
2478 match self.get(key).map_err(to_pyvalue_err)? {
2479 Some(bytes) => Ok(Some(bytes.to_vec())),
2480 None => Ok(None),
2481 }
2482 }
2483
2484 #[pyo3(name = "add")]
2486 fn py_add_general(&mut self, key: &str, value: Vec<u8>) -> PyResult<()> {
2487 self.add(key, Bytes::from(value)).map_err(to_pyvalue_err)
2488 }
2489
2490 #[pyo3(name = "price")]
2492 fn py_price(&self, instrument_id: InstrumentId, price_type: PriceType) -> Option<Price> {
2493 self.price(&instrument_id, price_type)
2494 }
2495
2496 #[pyo3(name = "get_xrate")]
2498 fn py_get_xrate(
2499 &self,
2500 venue: Venue,
2501 from_currency: Currency,
2502 to_currency: Currency,
2503 price_type: PriceType,
2504 ) -> Option<f64> {
2505 self.get_xrate(venue, from_currency, to_currency, price_type)
2506 }
2507
2508 #[pyo3(name = "get_mark_xrate")]
2510 fn py_get_mark_xrate(&self, from_currency: Currency, to_currency: Currency) -> Option<f64> {
2511 self.get_mark_xrate(from_currency, to_currency)
2512 }
2513
2514 #[pyo3(name = "set_mark_xrate")]
2516 fn py_set_mark_xrate(&mut self, from_currency: Currency, to_currency: Currency, xrate: f64) {
2517 self.set_mark_xrate(from_currency, to_currency, xrate);
2518 }
2519
2520 #[pyo3(name = "clear_mark_xrate")]
2522 fn py_clear_mark_xrate(&mut self, from_currency: Currency, to_currency: Currency) {
2523 self.clear_mark_xrate(from_currency, to_currency);
2524 }
2525
2526 #[pyo3(name = "clear_mark_xrates")]
2528 fn py_clear_mark_xrates(&mut self) {
2529 self.clear_mark_xrates();
2530 }
2531
2532 #[pyo3(name = "calculate_unrealized_pnl")]
2534 #[expect(clippy::needless_pass_by_value)]
2535 fn py_calculate_unrealized_pnl(
2536 &self,
2537 py: Python,
2538 position: Py<PyAny>,
2539 ) -> PyResult<Option<Money>> {
2540 let position = position.extract::<Position>(py)?;
2541 Ok(self.calculate_unrealized_pnl(&position))
2542 }
2543
2544 #[pyo3(name = "own_order_book")]
2546 fn py_own_order_book(&self, instrument_id: InstrumentId) -> Option<OwnOrderBook> {
2547 self.own_order_book(&instrument_id).cloned()
2548 }
2549
2550 #[pyo3(name = "update_own_order_book")]
2558 fn py_update_own_order_book(&mut self, py: Python, order: Py<PyAny>) -> PyResult<()> {
2559 let order_any = pyobject_to_order_any(py, order)?;
2560 self.update_own_order_book(&order_any);
2561 Ok(())
2562 }
2563
2564 #[pyo3(name = "force_remove_from_own_order_book")]
2570 fn py_force_remove_from_own_order_book(&mut self, client_order_id: ClientOrderId) {
2571 self.force_remove_from_own_order_book(&client_order_id);
2572 }
2573
2574 #[pyo3(name = "audit_own_order_books")]
2581 fn py_audit_own_order_books(&mut self) {
2582 self.audit_own_order_books();
2583 }
2584}
2585
2586#[cfg(feature = "defi")]
2587#[pymethods]
2588impl Cache {
2589 #[pyo3(name = "add_pool")]
2595 fn py_add_pool(&mut self, pool: Pool) -> PyResult<()> {
2596 self.add_pool(pool).map_err(to_pyvalue_err)
2597 }
2598
2599 #[pyo3(name = "pool")]
2601 fn py_pool(&self, instrument_id: InstrumentId) -> Option<Pool> {
2602 self.pool(&instrument_id).cloned()
2603 }
2604
2605 #[pyo3(name = "pool_ids")]
2607 fn py_pool_ids(&self, venue: Option<Venue>) -> Vec<InstrumentId> {
2608 self.pool_ids(venue.as_ref())
2609 }
2610
2611 #[pyo3(name = "pools")]
2613 fn py_pools(&self, venue: Option<Venue>) -> Vec<Pool> {
2614 self.pools(venue.as_ref()).into_iter().cloned().collect()
2615 }
2616
2617 #[pyo3(name = "add_pool_profiler")]
2623 fn py_add_pool_profiler(&mut self, pool_profiler: PoolProfiler) -> PyResult<()> {
2624 self.add_pool_profiler(pool_profiler)
2625 .map_err(to_pyvalue_err)
2626 }
2627
2628 #[pyo3(name = "pool_profiler")]
2630 fn py_pool_profiler(&self, instrument_id: InstrumentId) -> Option<PoolProfiler> {
2631 self.pool_profiler(&instrument_id).cloned()
2632 }
2633
2634 #[pyo3(name = "pool_profiler_ids")]
2636 fn py_pool_profiler_ids(&self, venue: Option<Venue>) -> Vec<InstrumentId> {
2637 self.pool_profiler_ids(venue.as_ref())
2638 }
2639
2640 #[pyo3(name = "pool_profilers")]
2642 fn py_pool_profilers(&self, venue: Option<Venue>) -> Vec<PoolProfiler> {
2643 self.pool_profilers(venue.as_ref())
2644 .into_iter()
2645 .cloned()
2646 .collect()
2647 }
2648}