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_err(to_pyvalue_err)
1124 }
1125
1126 #[pyo3(name = "position_snapshots", signature = (position_id=None, account_id=None))]
1127 fn py_position_snapshots(
1128 &self,
1129 py: Python,
1130 position_id: Option<PositionId>,
1131 account_id: Option<AccountId>,
1132 ) -> PyResult<Vec<Py<PyAny>>> {
1133 let cache = self.0.borrow();
1134 cache
1135 .position_snapshots(position_id.as_ref(), account_id.as_ref())
1136 .into_iter()
1137 .map(|p| Ok(p.into_pyobject(py)?.into()))
1138 .collect()
1139 }
1140}
1141
1142#[cfg(feature = "defi")]
1143#[pymethods]
1144#[pyo3_stub_gen::derive::gen_stub_pymethods]
1145impl PyCache {
1146 #[pyo3(name = "pool")]
1147 fn py_pool(&self, instrument_id: InstrumentId) -> Option<Pool> {
1148 self.0
1149 .try_borrow()
1150 .ok()
1151 .and_then(|cache| cache.pool(&instrument_id).cloned())
1152 }
1153
1154 #[pyo3(name = "pool_profiler")]
1155 fn py_pool_profiler(&self, instrument_id: InstrumentId) -> Option<PoolProfiler> {
1156 self.0
1157 .try_borrow()
1158 .ok()
1159 .and_then(|cache| cache.pool_profiler(&instrument_id).cloned())
1160 }
1161}
1162
1163#[pymethods]
1164#[pyo3_stub_gen::derive::gen_stub_pymethods]
1165impl CacheConfig {
1166 #[new]
1168 #[expect(clippy::too_many_arguments)]
1169 #[pyo3(signature = (
1170 encoding=None,
1171 timestamps_as_iso8601=None,
1172 buffer_interval_ms=None,
1173 bulk_read_batch_size=None,
1174 use_trader_prefix=None,
1175 use_instance_id=None,
1176 flush_on_start=None,
1177 drop_instruments_on_reset=None,
1178 tick_capacity=None,
1179 bar_capacity=None,
1180 save_market_data=None,
1181 persist_account_events=None,
1182 ))]
1183 fn py_new(
1184 encoding: Option<SerializationEncoding>,
1185 timestamps_as_iso8601: Option<bool>,
1186 buffer_interval_ms: Option<usize>,
1187 bulk_read_batch_size: Option<usize>,
1188 use_trader_prefix: Option<bool>,
1189 use_instance_id: Option<bool>,
1190 flush_on_start: Option<bool>,
1191 drop_instruments_on_reset: Option<bool>,
1192 tick_capacity: Option<usize>,
1193 bar_capacity: Option<usize>,
1194 save_market_data: Option<bool>,
1195 persist_account_events: Option<bool>,
1196 ) -> Self {
1197 Self::new(
1198 None, encoding.unwrap_or(SerializationEncoding::MsgPack),
1200 timestamps_as_iso8601.unwrap_or(false),
1201 buffer_interval_ms,
1202 bulk_read_batch_size,
1203 use_trader_prefix.unwrap_or(true),
1204 use_instance_id.unwrap_or(false),
1205 flush_on_start.unwrap_or(false),
1206 drop_instruments_on_reset.unwrap_or(true),
1207 tick_capacity.unwrap_or(10_000),
1208 bar_capacity.unwrap_or(10_000),
1209 persist_account_events.unwrap_or(true),
1210 save_market_data.unwrap_or(false),
1211 )
1212 }
1213
1214 fn __str__(&self) -> String {
1215 format!("{self:?}")
1216 }
1217
1218 fn __repr__(&self) -> String {
1219 format!("{self:?}")
1220 }
1221
1222 #[getter]
1223 fn encoding(&self) -> SerializationEncoding {
1224 self.encoding
1225 }
1226
1227 #[getter]
1228 fn timestamps_as_iso8601(&self) -> bool {
1229 self.timestamps_as_iso8601
1230 }
1231
1232 #[getter]
1233 fn buffer_interval_ms(&self) -> Option<usize> {
1234 self.buffer_interval_ms
1235 }
1236
1237 #[getter]
1238 fn bulk_read_batch_size(&self) -> Option<usize> {
1239 self.bulk_read_batch_size
1240 }
1241
1242 #[getter]
1243 fn use_trader_prefix(&self) -> bool {
1244 self.use_trader_prefix
1245 }
1246
1247 #[getter]
1248 fn use_instance_id(&self) -> bool {
1249 self.use_instance_id
1250 }
1251
1252 #[getter]
1253 fn flush_on_start(&self) -> bool {
1254 self.flush_on_start
1255 }
1256
1257 #[getter]
1258 fn drop_instruments_on_reset(&self) -> bool {
1259 self.drop_instruments_on_reset
1260 }
1261
1262 #[getter]
1263 fn tick_capacity(&self) -> usize {
1264 self.tick_capacity
1265 }
1266
1267 #[getter]
1268 fn bar_capacity(&self) -> usize {
1269 self.bar_capacity
1270 }
1271
1272 #[getter]
1273 fn persist_account_events(&self) -> bool {
1274 self.persist_account_events
1275 }
1276
1277 #[getter]
1278 fn save_market_data(&self) -> bool {
1279 self.save_market_data
1280 }
1281}
1282
1283#[pymethods]
1284impl Cache {
1285 #[new]
1287 fn py_new(config: Option<CacheConfig>) -> Self {
1288 Self::new(config, None)
1289 }
1290
1291 fn __repr__(&self) -> String {
1292 format!("{self:?}")
1293 }
1294
1295 #[pyo3(name = "reset")]
1301 fn py_reset(&mut self) {
1302 self.reset();
1303 }
1304
1305 #[pyo3(name = "dispose")]
1309 fn py_dispose(&mut self) {
1310 self.dispose();
1311 }
1312
1313 #[pyo3(name = "add_currency")]
1319 fn py_add_currency(&mut self, currency: Currency) -> PyResult<()> {
1320 self.add_currency(currency).map_err(to_pyvalue_err)
1321 }
1322
1323 #[pyo3(name = "add_instrument")]
1329 fn py_add_instrument(&mut self, py: Python, instrument: Py<PyAny>) -> PyResult<()> {
1330 let instrument_any = pyobject_to_instrument_any(py, instrument)?;
1331 self.add_instrument(instrument_any).map_err(to_pyvalue_err)
1332 }
1333
1334 #[pyo3(name = "instrument")]
1336 fn py_instrument(
1337 &self,
1338 py: Python,
1339 instrument_id: InstrumentId,
1340 ) -> PyResult<Option<Py<PyAny>>> {
1341 match self.instrument(&instrument_id) {
1342 Some(instrument) => Ok(Some(instrument_any_to_pyobject(py, instrument.clone())?)),
1343 None => Ok(None),
1344 }
1345 }
1346
1347 #[pyo3(name = "instrument_ids")]
1349 fn py_instrument_ids(&self, venue: Option<Venue>) -> Vec<InstrumentId> {
1350 self.instrument_ids(venue.as_ref())
1351 .into_iter()
1352 .copied()
1353 .collect()
1354 }
1355
1356 #[pyo3(name = "instruments")]
1358 fn py_instruments(&self, py: Python, venue: Option<Venue>) -> PyResult<Vec<Py<PyAny>>> {
1359 let mut py_instruments = Vec::new();
1360
1361 match venue {
1362 Some(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 }
1368 None => {
1369 let instrument_ids = self.instrument_ids(None);
1370 for instrument_id in instrument_ids {
1371 if let Some(instrument) = self.instrument(instrument_id) {
1372 py_instruments.push(instrument_any_to_pyobject(py, instrument.clone())?);
1373 }
1374 }
1375 }
1376 }
1377
1378 Ok(py_instruments)
1379 }
1380
1381 #[pyo3(name = "add_order")]
1389 fn py_add_order(
1390 &mut self,
1391 py: Python,
1392 order: Py<PyAny>,
1393 position_id: Option<PositionId>,
1394 client_id: Option<ClientId>,
1395 replace_existing: Option<bool>,
1396 ) -> PyResult<()> {
1397 let order_any = pyobject_to_order_any(py, order)?;
1398 self.add_order(
1399 order_any,
1400 position_id,
1401 client_id,
1402 replace_existing.unwrap_or(false),
1403 )
1404 .map_err(to_pyvalue_err)
1405 }
1406
1407 #[pyo3(name = "order")]
1409 fn py_order(&self, py: Python, client_order_id: ClientOrderId) -> PyResult<Option<Py<PyAny>>> {
1410 match self.order(&client_order_id) {
1411 Some(order) => Ok(Some(order_any_to_pyobject(py, order.clone())?)),
1412 None => Ok(None),
1413 }
1414 }
1415
1416 #[pyo3(name = "order_exists")]
1418 fn py_order_exists(&self, client_order_id: ClientOrderId) -> bool {
1419 self.order_exists(&client_order_id)
1420 }
1421
1422 #[pyo3(name = "is_order_open")]
1424 fn py_is_order_open(&self, client_order_id: ClientOrderId) -> bool {
1425 self.is_order_open(&client_order_id)
1426 }
1427
1428 #[pyo3(name = "is_order_closed")]
1430 fn py_is_order_closed(&self, client_order_id: ClientOrderId) -> bool {
1431 self.is_order_closed(&client_order_id)
1432 }
1433
1434 #[pyo3(name = "is_order_active_local")]
1439 fn py_is_order_active_local(&self, client_order_id: ClientOrderId) -> bool {
1440 self.is_order_active_local(&client_order_id)
1441 }
1442
1443 #[pyo3(name = "orders_active_local")]
1448 fn py_orders_active_local(
1449 &self,
1450 py: Python,
1451 venue: Option<Venue>,
1452 instrument_id: Option<InstrumentId>,
1453 strategy_id: Option<StrategyId>,
1454 account_id: Option<AccountId>,
1455 side: Option<OrderSide>,
1456 ) -> PyResult<Vec<Py<PyAny>>> {
1457 self.orders_active_local(
1458 venue.as_ref(),
1459 instrument_id.as_ref(),
1460 strategy_id.as_ref(),
1461 account_id.as_ref(),
1462 side,
1463 )
1464 .into_iter()
1465 .map(|order| order_any_to_pyobject(py, order.clone()))
1466 .collect()
1467 }
1468
1469 #[pyo3(name = "orders_active_local_count")]
1474 fn py_orders_active_local_count(
1475 &self,
1476 venue: Option<Venue>,
1477 instrument_id: Option<InstrumentId>,
1478 strategy_id: Option<StrategyId>,
1479 account_id: Option<AccountId>,
1480 side: Option<OrderSide>,
1481 ) -> usize {
1482 self.orders_active_local_count(
1483 venue.as_ref(),
1484 instrument_id.as_ref(),
1485 strategy_id.as_ref(),
1486 account_id.as_ref(),
1487 side,
1488 )
1489 }
1490
1491 #[pyo3(name = "orders_open_count")]
1493 fn py_orders_open_count(
1494 &self,
1495 venue: Option<Venue>,
1496 instrument_id: Option<InstrumentId>,
1497 strategy_id: Option<StrategyId>,
1498 account_id: Option<AccountId>,
1499 side: Option<OrderSide>,
1500 ) -> usize {
1501 self.orders_open_count(
1502 venue.as_ref(),
1503 instrument_id.as_ref(),
1504 strategy_id.as_ref(),
1505 account_id.as_ref(),
1506 side,
1507 )
1508 }
1509
1510 #[pyo3(name = "orders_closed_count")]
1512 fn py_orders_closed_count(
1513 &self,
1514 venue: Option<Venue>,
1515 instrument_id: Option<InstrumentId>,
1516 strategy_id: Option<StrategyId>,
1517 account_id: Option<AccountId>,
1518 side: Option<OrderSide>,
1519 ) -> usize {
1520 self.orders_closed_count(
1521 venue.as_ref(),
1522 instrument_id.as_ref(),
1523 strategy_id.as_ref(),
1524 account_id.as_ref(),
1525 side,
1526 )
1527 }
1528
1529 #[pyo3(name = "orders_total_count")]
1531 fn py_orders_total_count(
1532 &self,
1533 venue: Option<Venue>,
1534 instrument_id: Option<InstrumentId>,
1535 strategy_id: Option<StrategyId>,
1536 account_id: Option<AccountId>,
1537 side: Option<OrderSide>,
1538 ) -> usize {
1539 self.orders_total_count(
1540 venue.as_ref(),
1541 instrument_id.as_ref(),
1542 strategy_id.as_ref(),
1543 account_id.as_ref(),
1544 side,
1545 )
1546 }
1547
1548 #[pyo3(name = "add_position")]
1550 #[expect(clippy::needless_pass_by_value)]
1551 fn py_add_position(
1552 &mut self,
1553 py: Python,
1554 position: Py<PyAny>,
1555 oms_type: OmsType,
1556 ) -> PyResult<()> {
1557 let position_obj = position.extract::<Position>(py)?;
1558 self.add_position(&position_obj, oms_type)
1559 .map_err(to_pyvalue_err)
1560 }
1561
1562 #[pyo3(name = "snapshot_position")]
1569 #[expect(clippy::needless_pass_by_value)]
1570 fn py_snapshot_position(&mut self, py: Python, position: Py<PyAny>) -> PyResult<()> {
1571 let position_obj = position.extract::<Position>(py)?;
1572 self.snapshot_position(&position_obj)
1573 .map_err(to_pyvalue_err)
1574 }
1575
1576 #[pyo3(name = "position")]
1578 fn py_position(&self, py: Python, position_id: PositionId) -> PyResult<Option<Py<PyAny>>> {
1579 match self.position(&position_id) {
1580 Some(position) => Ok(Some(position.clone().into_pyobject(py)?.into())),
1581 None => Ok(None),
1582 }
1583 }
1584
1585 #[pyo3(name = "position_exists")]
1587 fn py_position_exists(&self, position_id: PositionId) -> bool {
1588 self.position_exists(&position_id)
1589 }
1590
1591 #[pyo3(name = "is_position_open")]
1593 fn py_is_position_open(&self, position_id: PositionId) -> bool {
1594 self.is_position_open(&position_id)
1595 }
1596
1597 #[pyo3(name = "is_position_closed")]
1599 fn py_is_position_closed(&self, position_id: PositionId) -> bool {
1600 self.is_position_closed(&position_id)
1601 }
1602
1603 #[pyo3(name = "positions_open_count")]
1605 fn py_positions_open_count(
1606 &self,
1607 venue: Option<Venue>,
1608 instrument_id: Option<InstrumentId>,
1609 strategy_id: Option<StrategyId>,
1610 account_id: Option<AccountId>,
1611 side: Option<PositionSide>,
1612 ) -> usize {
1613 self.positions_open_count(
1614 venue.as_ref(),
1615 instrument_id.as_ref(),
1616 strategy_id.as_ref(),
1617 account_id.as_ref(),
1618 side,
1619 )
1620 }
1621
1622 #[pyo3(name = "positions_closed_count")]
1624 fn py_positions_closed_count(
1625 &self,
1626 venue: Option<Venue>,
1627 instrument_id: Option<InstrumentId>,
1628 strategy_id: Option<StrategyId>,
1629 account_id: Option<AccountId>,
1630 side: Option<PositionSide>,
1631 ) -> usize {
1632 self.positions_closed_count(
1633 venue.as_ref(),
1634 instrument_id.as_ref(),
1635 strategy_id.as_ref(),
1636 account_id.as_ref(),
1637 side,
1638 )
1639 }
1640
1641 #[pyo3(name = "positions_total_count")]
1643 fn py_positions_total_count(
1644 &self,
1645 venue: Option<Venue>,
1646 instrument_id: Option<InstrumentId>,
1647 strategy_id: Option<StrategyId>,
1648 account_id: Option<AccountId>,
1649 side: Option<PositionSide>,
1650 ) -> usize {
1651 self.positions_total_count(
1652 venue.as_ref(),
1653 instrument_id.as_ref(),
1654 strategy_id.as_ref(),
1655 account_id.as_ref(),
1656 side,
1657 )
1658 }
1659
1660 #[pyo3(name = "add_quote")]
1666 fn py_add_quote(&mut self, quote: QuoteTick) -> PyResult<()> {
1667 self.add_quote(quote).map_err(to_pyvalue_err)
1668 }
1669
1670 #[pyo3(name = "add_trade")]
1676 fn py_add_trade(&mut self, trade: TradeTick) -> PyResult<()> {
1677 self.add_trade(trade).map_err(to_pyvalue_err)
1678 }
1679
1680 #[pyo3(name = "add_bar")]
1686 fn py_add_bar(&mut self, bar: Bar) -> PyResult<()> {
1687 self.add_bar(bar).map_err(to_pyvalue_err)
1688 }
1689
1690 #[pyo3(name = "quote")]
1692 fn py_quote(&self, instrument_id: InstrumentId) -> Option<QuoteTick> {
1693 self.quote(&instrument_id).copied()
1694 }
1695
1696 #[pyo3(name = "trade")]
1698 fn py_trade(&self, instrument_id: InstrumentId) -> Option<TradeTick> {
1699 self.trade(&instrument_id).copied()
1700 }
1701
1702 #[pyo3(name = "bar")]
1704 fn py_bar(&self, bar_type: BarType) -> Option<Bar> {
1705 self.bar(&bar_type).copied()
1706 }
1707
1708 #[pyo3(name = "quotes")]
1710 fn py_quotes(&self, instrument_id: InstrumentId) -> Option<Vec<QuoteTick>> {
1711 self.quotes(&instrument_id)
1712 }
1713
1714 #[pyo3(name = "trades")]
1716 fn py_trades(&self, instrument_id: InstrumentId) -> Option<Vec<TradeTick>> {
1717 self.trades(&instrument_id)
1718 }
1719
1720 #[pyo3(name = "bars")]
1722 fn py_bars(&self, bar_type: BarType) -> Option<Vec<Bar>> {
1723 self.bars(&bar_type)
1724 }
1725
1726 #[pyo3(name = "has_quote_ticks")]
1728 fn py_has_quote_ticks(&self, instrument_id: InstrumentId) -> bool {
1729 self.has_quote_ticks(&instrument_id)
1730 }
1731
1732 #[pyo3(name = "has_trade_ticks")]
1734 fn py_has_trade_ticks(&self, instrument_id: InstrumentId) -> bool {
1735 self.has_trade_ticks(&instrument_id)
1736 }
1737
1738 #[pyo3(name = "has_bars")]
1740 fn py_has_bars(&self, bar_type: BarType) -> bool {
1741 self.has_bars(&bar_type)
1742 }
1743
1744 #[pyo3(name = "quote_count")]
1746 fn py_quote_count(&self, instrument_id: InstrumentId) -> usize {
1747 self.quote_count(&instrument_id)
1748 }
1749
1750 #[pyo3(name = "trade_count")]
1752 fn py_trade_count(&self, instrument_id: InstrumentId) -> usize {
1753 self.trade_count(&instrument_id)
1754 }
1755
1756 #[pyo3(name = "bar_count")]
1758 fn py_bar_count(&self, bar_type: BarType) -> usize {
1759 self.bar_count(&bar_type)
1760 }
1761
1762 #[pyo3(name = "mark_price")]
1764 fn py_mark_price(&self, instrument_id: InstrumentId) -> Option<MarkPriceUpdate> {
1765 self.mark_price(&instrument_id).copied()
1766 }
1767
1768 #[pyo3(name = "mark_prices")]
1770 fn py_mark_prices(&self, instrument_id: InstrumentId) -> Option<Vec<MarkPriceUpdate>> {
1771 self.mark_prices(&instrument_id)
1772 }
1773
1774 #[pyo3(name = "index_price")]
1776 fn py_index_price(&self, instrument_id: InstrumentId) -> Option<IndexPriceUpdate> {
1777 self.index_price(&instrument_id).copied()
1778 }
1779
1780 #[pyo3(name = "index_prices")]
1782 fn py_index_prices(&self, instrument_id: InstrumentId) -> Option<Vec<IndexPriceUpdate>> {
1783 self.index_prices(&instrument_id)
1784 }
1785
1786 #[pyo3(name = "funding_rate")]
1788 fn py_funding_rate(&self, instrument_id: InstrumentId) -> Option<FundingRateUpdate> {
1789 self.funding_rate(&instrument_id).copied()
1790 }
1791
1792 #[pyo3(name = "instrument_status")]
1794 fn py_instrument_status(&self, instrument_id: InstrumentId) -> Option<InstrumentStatus> {
1795 self.instrument_status(&instrument_id).copied()
1796 }
1797
1798 #[pyo3(name = "instrument_statuses")]
1800 fn py_instrument_statuses(&self, instrument_id: InstrumentId) -> Option<Vec<InstrumentStatus>> {
1801 self.instrument_statuses(&instrument_id)
1802 }
1803
1804 #[pyo3(name = "order_book")]
1806 fn py_order_book(&self, instrument_id: InstrumentId) -> Option<OrderBook> {
1807 self.order_book(&instrument_id).cloned()
1808 }
1809
1810 #[pyo3(name = "has_order_book")]
1812 fn py_has_order_book(&self, instrument_id: InstrumentId) -> bool {
1813 self.has_order_book(&instrument_id)
1814 }
1815
1816 #[pyo3(name = "book_update_count")]
1818 fn py_book_update_count(&self, instrument_id: InstrumentId) -> usize {
1819 self.book_update_count(&instrument_id)
1820 }
1821
1822 #[pyo3(name = "synthetic")]
1824 fn py_synthetic(&self, instrument_id: InstrumentId) -> Option<SyntheticInstrument> {
1825 self.synthetic(&instrument_id).cloned()
1826 }
1827
1828 #[pyo3(name = "synthetic_ids")]
1830 fn py_synthetic_ids(&self) -> Vec<InstrumentId> {
1831 self.synthetic_ids().into_iter().copied().collect()
1832 }
1833
1834 #[pyo3(name = "client_order_ids")]
1836 fn py_client_order_ids(
1837 &self,
1838 venue: Option<Venue>,
1839 instrument_id: Option<InstrumentId>,
1840 strategy_id: Option<StrategyId>,
1841 account_id: Option<AccountId>,
1842 ) -> Vec<ClientOrderId> {
1843 self.client_order_ids(
1844 venue.as_ref(),
1845 instrument_id.as_ref(),
1846 strategy_id.as_ref(),
1847 account_id.as_ref(),
1848 )
1849 .into_iter()
1850 .collect()
1851 }
1852
1853 #[pyo3(name = "client_order_ids_open")]
1855 fn py_client_order_ids_open(
1856 &self,
1857 venue: Option<Venue>,
1858 instrument_id: Option<InstrumentId>,
1859 strategy_id: Option<StrategyId>,
1860 account_id: Option<AccountId>,
1861 ) -> Vec<ClientOrderId> {
1862 self.client_order_ids_open(
1863 venue.as_ref(),
1864 instrument_id.as_ref(),
1865 strategy_id.as_ref(),
1866 account_id.as_ref(),
1867 )
1868 .into_iter()
1869 .collect()
1870 }
1871
1872 #[pyo3(name = "client_order_ids_closed")]
1874 fn py_client_order_ids_closed(
1875 &self,
1876 venue: Option<Venue>,
1877 instrument_id: Option<InstrumentId>,
1878 strategy_id: Option<StrategyId>,
1879 account_id: Option<AccountId>,
1880 ) -> Vec<ClientOrderId> {
1881 self.client_order_ids_closed(
1882 venue.as_ref(),
1883 instrument_id.as_ref(),
1884 strategy_id.as_ref(),
1885 account_id.as_ref(),
1886 )
1887 .into_iter()
1888 .collect()
1889 }
1890
1891 #[pyo3(name = "client_order_ids_emulated")]
1893 fn py_client_order_ids_emulated(
1894 &self,
1895 venue: Option<Venue>,
1896 instrument_id: Option<InstrumentId>,
1897 strategy_id: Option<StrategyId>,
1898 account_id: Option<AccountId>,
1899 ) -> Vec<ClientOrderId> {
1900 self.client_order_ids_emulated(
1901 venue.as_ref(),
1902 instrument_id.as_ref(),
1903 strategy_id.as_ref(),
1904 account_id.as_ref(),
1905 )
1906 .into_iter()
1907 .collect()
1908 }
1909
1910 #[pyo3(name = "client_order_ids_inflight")]
1912 fn py_client_order_ids_inflight(
1913 &self,
1914 venue: Option<Venue>,
1915 instrument_id: Option<InstrumentId>,
1916 strategy_id: Option<StrategyId>,
1917 account_id: Option<AccountId>,
1918 ) -> Vec<ClientOrderId> {
1919 self.client_order_ids_inflight(
1920 venue.as_ref(),
1921 instrument_id.as_ref(),
1922 strategy_id.as_ref(),
1923 account_id.as_ref(),
1924 )
1925 .into_iter()
1926 .collect()
1927 }
1928
1929 #[pyo3(name = "position_ids")]
1931 fn py_position_ids(
1932 &self,
1933 venue: Option<Venue>,
1934 instrument_id: Option<InstrumentId>,
1935 strategy_id: Option<StrategyId>,
1936 account_id: Option<AccountId>,
1937 ) -> Vec<PositionId> {
1938 self.position_ids(
1939 venue.as_ref(),
1940 instrument_id.as_ref(),
1941 strategy_id.as_ref(),
1942 account_id.as_ref(),
1943 )
1944 .into_iter()
1945 .collect()
1946 }
1947
1948 #[pyo3(name = "position_open_ids")]
1950 fn py_position_open_ids(
1951 &self,
1952 venue: Option<Venue>,
1953 instrument_id: Option<InstrumentId>,
1954 strategy_id: Option<StrategyId>,
1955 account_id: Option<AccountId>,
1956 ) -> Vec<PositionId> {
1957 self.position_open_ids(
1958 venue.as_ref(),
1959 instrument_id.as_ref(),
1960 strategy_id.as_ref(),
1961 account_id.as_ref(),
1962 )
1963 .into_iter()
1964 .collect()
1965 }
1966
1967 #[pyo3(name = "position_closed_ids")]
1969 fn py_position_closed_ids(
1970 &self,
1971 venue: Option<Venue>,
1972 instrument_id: Option<InstrumentId>,
1973 strategy_id: Option<StrategyId>,
1974 account_id: Option<AccountId>,
1975 ) -> Vec<PositionId> {
1976 self.position_closed_ids(
1977 venue.as_ref(),
1978 instrument_id.as_ref(),
1979 strategy_id.as_ref(),
1980 account_id.as_ref(),
1981 )
1982 .into_iter()
1983 .collect()
1984 }
1985
1986 #[pyo3(name = "actor_ids")]
1988 fn py_actor_ids(&self) -> Vec<ComponentId> {
1989 self.actor_ids().into_iter().collect()
1990 }
1991
1992 #[pyo3(name = "strategy_ids")]
1994 fn py_strategy_ids(&self) -> Vec<StrategyId> {
1995 self.strategy_ids().into_iter().collect()
1996 }
1997
1998 #[pyo3(name = "exec_algorithm_ids")]
2000 fn py_exec_algorithm_ids(&self) -> Vec<ExecAlgorithmId> {
2001 self.exec_algorithm_ids().into_iter().collect()
2002 }
2003
2004 #[pyo3(name = "client_order_id")]
2006 fn py_client_order_id(&self, venue_order_id: VenueOrderId) -> Option<ClientOrderId> {
2007 self.client_order_id(&venue_order_id).copied()
2008 }
2009
2010 #[pyo3(name = "venue_order_id")]
2012 fn py_venue_order_id(&self, client_order_id: ClientOrderId) -> Option<VenueOrderId> {
2013 self.venue_order_id(&client_order_id).copied()
2014 }
2015
2016 #[pyo3(name = "client_id")]
2018 fn py_client_id(&self, client_order_id: ClientOrderId) -> Option<ClientId> {
2019 self.client_id(&client_order_id).copied()
2020 }
2021
2022 #[pyo3(name = "orders")]
2024 fn py_orders(
2025 &self,
2026 py: Python,
2027 venue: Option<Venue>,
2028 instrument_id: Option<InstrumentId>,
2029 strategy_id: Option<StrategyId>,
2030 account_id: Option<AccountId>,
2031 side: Option<OrderSide>,
2032 ) -> PyResult<Vec<Py<PyAny>>> {
2033 self.orders(
2034 venue.as_ref(),
2035 instrument_id.as_ref(),
2036 strategy_id.as_ref(),
2037 account_id.as_ref(),
2038 side,
2039 )
2040 .into_iter()
2041 .map(|o| order_any_to_pyobject(py, o.clone()))
2042 .collect()
2043 }
2044
2045 #[pyo3(name = "orders_open")]
2047 fn py_orders_open(
2048 &self,
2049 py: Python,
2050 venue: Option<Venue>,
2051 instrument_id: Option<InstrumentId>,
2052 strategy_id: Option<StrategyId>,
2053 account_id: Option<AccountId>,
2054 side: Option<OrderSide>,
2055 ) -> PyResult<Vec<Py<PyAny>>> {
2056 self.orders_open(
2057 venue.as_ref(),
2058 instrument_id.as_ref(),
2059 strategy_id.as_ref(),
2060 account_id.as_ref(),
2061 side,
2062 )
2063 .into_iter()
2064 .map(|o| order_any_to_pyobject(py, o.clone()))
2065 .collect()
2066 }
2067
2068 #[pyo3(name = "orders_closed")]
2070 fn py_orders_closed(
2071 &self,
2072 py: Python,
2073 venue: Option<Venue>,
2074 instrument_id: Option<InstrumentId>,
2075 strategy_id: Option<StrategyId>,
2076 account_id: Option<AccountId>,
2077 side: Option<OrderSide>,
2078 ) -> PyResult<Vec<Py<PyAny>>> {
2079 self.orders_closed(
2080 venue.as_ref(),
2081 instrument_id.as_ref(),
2082 strategy_id.as_ref(),
2083 account_id.as_ref(),
2084 side,
2085 )
2086 .into_iter()
2087 .map(|o| order_any_to_pyobject(py, o.clone()))
2088 .collect()
2089 }
2090
2091 #[pyo3(name = "orders_emulated")]
2093 fn py_orders_emulated(
2094 &self,
2095 py: Python,
2096 venue: Option<Venue>,
2097 instrument_id: Option<InstrumentId>,
2098 strategy_id: Option<StrategyId>,
2099 account_id: Option<AccountId>,
2100 side: Option<OrderSide>,
2101 ) -> PyResult<Vec<Py<PyAny>>> {
2102 self.orders_emulated(
2103 venue.as_ref(),
2104 instrument_id.as_ref(),
2105 strategy_id.as_ref(),
2106 account_id.as_ref(),
2107 side,
2108 )
2109 .into_iter()
2110 .map(|o| order_any_to_pyobject(py, o.clone()))
2111 .collect()
2112 }
2113
2114 #[pyo3(name = "orders_inflight")]
2116 fn py_orders_inflight(
2117 &self,
2118 py: Python,
2119 venue: Option<Venue>,
2120 instrument_id: Option<InstrumentId>,
2121 strategy_id: Option<StrategyId>,
2122 account_id: Option<AccountId>,
2123 side: Option<OrderSide>,
2124 ) -> PyResult<Vec<Py<PyAny>>> {
2125 self.orders_inflight(
2126 venue.as_ref(),
2127 instrument_id.as_ref(),
2128 strategy_id.as_ref(),
2129 account_id.as_ref(),
2130 side,
2131 )
2132 .into_iter()
2133 .map(|o| order_any_to_pyobject(py, o.clone()))
2134 .collect()
2135 }
2136
2137 #[pyo3(name = "orders_for_position")]
2139 fn py_orders_for_position(
2140 &self,
2141 py: Python,
2142 position_id: PositionId,
2143 ) -> PyResult<Vec<Py<PyAny>>> {
2144 self.orders_for_position(&position_id)
2145 .into_iter()
2146 .map(|o| order_any_to_pyobject(py, o.clone()))
2147 .collect()
2148 }
2149
2150 #[pyo3(name = "is_order_emulated")]
2152 fn py_is_order_emulated(&self, client_order_id: ClientOrderId) -> bool {
2153 self.is_order_emulated(&client_order_id)
2154 }
2155
2156 #[pyo3(name = "is_order_inflight")]
2158 fn py_is_order_inflight(&self, client_order_id: ClientOrderId) -> bool {
2159 self.is_order_inflight(&client_order_id)
2160 }
2161
2162 #[pyo3(name = "is_order_pending_cancel_local")]
2164 fn py_is_order_pending_cancel_local(&self, client_order_id: ClientOrderId) -> bool {
2165 self.is_order_pending_cancel_local(&client_order_id)
2166 }
2167
2168 #[pyo3(name = "orders_emulated_count")]
2170 fn py_orders_emulated_count(
2171 &self,
2172 venue: Option<Venue>,
2173 instrument_id: Option<InstrumentId>,
2174 strategy_id: Option<StrategyId>,
2175 account_id: Option<AccountId>,
2176 side: Option<OrderSide>,
2177 ) -> usize {
2178 self.orders_emulated_count(
2179 venue.as_ref(),
2180 instrument_id.as_ref(),
2181 strategy_id.as_ref(),
2182 account_id.as_ref(),
2183 side,
2184 )
2185 }
2186
2187 #[pyo3(name = "orders_inflight_count")]
2189 fn py_orders_inflight_count(
2190 &self,
2191 venue: Option<Venue>,
2192 instrument_id: Option<InstrumentId>,
2193 strategy_id: Option<StrategyId>,
2194 account_id: Option<AccountId>,
2195 side: Option<OrderSide>,
2196 ) -> usize {
2197 self.orders_inflight_count(
2198 venue.as_ref(),
2199 instrument_id.as_ref(),
2200 strategy_id.as_ref(),
2201 account_id.as_ref(),
2202 side,
2203 )
2204 }
2205
2206 #[pyo3(name = "order_list")]
2208 fn py_order_list(&self, order_list_id: OrderListId) -> Option<OrderList> {
2209 self.order_list(&order_list_id).cloned()
2210 }
2211
2212 #[pyo3(name = "order_lists")]
2214 fn py_order_lists(
2215 &self,
2216 venue: Option<Venue>,
2217 instrument_id: Option<InstrumentId>,
2218 strategy_id: Option<StrategyId>,
2219 account_id: Option<AccountId>,
2220 ) -> Vec<OrderList> {
2221 self.order_lists(
2222 venue.as_ref(),
2223 instrument_id.as_ref(),
2224 strategy_id.as_ref(),
2225 account_id.as_ref(),
2226 )
2227 .into_iter()
2228 .cloned()
2229 .collect()
2230 }
2231
2232 #[pyo3(name = "order_list_exists")]
2234 fn py_order_list_exists(&self, order_list_id: OrderListId) -> bool {
2235 self.order_list_exists(&order_list_id)
2236 }
2237
2238 #[pyo3(name = "orders_for_exec_algorithm")]
2241 #[expect(clippy::too_many_arguments)]
2242 fn py_orders_for_exec_algorithm(
2243 &self,
2244 py: Python,
2245 exec_algorithm_id: ExecAlgorithmId,
2246 venue: Option<Venue>,
2247 instrument_id: Option<InstrumentId>,
2248 strategy_id: Option<StrategyId>,
2249 account_id: Option<AccountId>,
2250 side: Option<OrderSide>,
2251 ) -> PyResult<Vec<Py<PyAny>>> {
2252 self.orders_for_exec_algorithm(
2253 &exec_algorithm_id,
2254 venue.as_ref(),
2255 instrument_id.as_ref(),
2256 strategy_id.as_ref(),
2257 account_id.as_ref(),
2258 side,
2259 )
2260 .into_iter()
2261 .map(|o| order_any_to_pyobject(py, o.clone()))
2262 .collect()
2263 }
2264
2265 #[pyo3(name = "orders_for_exec_spawn")]
2267 fn py_orders_for_exec_spawn(
2268 &self,
2269 py: Python,
2270 exec_spawn_id: ClientOrderId,
2271 ) -> PyResult<Vec<Py<PyAny>>> {
2272 self.orders_for_exec_spawn(&exec_spawn_id)
2273 .into_iter()
2274 .map(|o| order_any_to_pyobject(py, o.clone()))
2275 .collect()
2276 }
2277
2278 #[pyo3(name = "exec_spawn_total_quantity")]
2280 fn py_exec_spawn_total_quantity(
2281 &self,
2282 exec_spawn_id: ClientOrderId,
2283 active_only: bool,
2284 ) -> Option<Quantity> {
2285 self.exec_spawn_total_quantity(&exec_spawn_id, active_only)
2286 }
2287
2288 #[pyo3(name = "exec_spawn_total_filled_qty")]
2290 fn py_exec_spawn_total_filled_qty(
2291 &self,
2292 exec_spawn_id: ClientOrderId,
2293 active_only: bool,
2294 ) -> Option<Quantity> {
2295 self.exec_spawn_total_filled_qty(&exec_spawn_id, active_only)
2296 }
2297
2298 #[pyo3(name = "exec_spawn_total_leaves_qty")]
2300 fn py_exec_spawn_total_leaves_qty(
2301 &self,
2302 exec_spawn_id: ClientOrderId,
2303 active_only: bool,
2304 ) -> Option<Quantity> {
2305 self.exec_spawn_total_leaves_qty(&exec_spawn_id, active_only)
2306 }
2307
2308 #[pyo3(name = "position_for_order")]
2310 fn py_position_for_order(
2311 &self,
2312 py: Python,
2313 client_order_id: ClientOrderId,
2314 ) -> PyResult<Option<Py<PyAny>>> {
2315 match self.position_for_order(&client_order_id) {
2316 Some(position) => Ok(Some(position.clone().into_pyobject(py)?.into())),
2317 None => Ok(None),
2318 }
2319 }
2320
2321 #[pyo3(name = "position_id")]
2323 fn py_position_id(&self, client_order_id: ClientOrderId) -> Option<PositionId> {
2324 self.position_id(&client_order_id).copied()
2325 }
2326
2327 #[pyo3(name = "positions")]
2329 fn py_positions(
2330 &self,
2331 py: Python,
2332 venue: Option<Venue>,
2333 instrument_id: Option<InstrumentId>,
2334 strategy_id: Option<StrategyId>,
2335 account_id: Option<AccountId>,
2336 side: Option<PositionSide>,
2337 ) -> PyResult<Vec<Py<PyAny>>> {
2338 self.positions(
2339 venue.as_ref(),
2340 instrument_id.as_ref(),
2341 strategy_id.as_ref(),
2342 account_id.as_ref(),
2343 side,
2344 )
2345 .into_iter()
2346 .map(|p| Ok(p.clone().into_pyobject(py)?.into()))
2347 .collect()
2348 }
2349
2350 #[pyo3(name = "positions_open")]
2352 fn py_positions_open(
2353 &self,
2354 py: Python,
2355 venue: Option<Venue>,
2356 instrument_id: Option<InstrumentId>,
2357 strategy_id: Option<StrategyId>,
2358 account_id: Option<AccountId>,
2359 side: Option<PositionSide>,
2360 ) -> PyResult<Vec<Py<PyAny>>> {
2361 self.positions_open(
2362 venue.as_ref(),
2363 instrument_id.as_ref(),
2364 strategy_id.as_ref(),
2365 account_id.as_ref(),
2366 side,
2367 )
2368 .into_iter()
2369 .map(|p| Ok(p.clone().into_pyobject(py)?.into()))
2370 .collect()
2371 }
2372
2373 #[pyo3(name = "positions_closed")]
2375 fn py_positions_closed(
2376 &self,
2377 py: Python,
2378 venue: Option<Venue>,
2379 instrument_id: Option<InstrumentId>,
2380 strategy_id: Option<StrategyId>,
2381 account_id: Option<AccountId>,
2382 side: Option<PositionSide>,
2383 ) -> PyResult<Vec<Py<PyAny>>> {
2384 self.positions_closed(
2385 venue.as_ref(),
2386 instrument_id.as_ref(),
2387 strategy_id.as_ref(),
2388 account_id.as_ref(),
2389 side,
2390 )
2391 .into_iter()
2392 .map(|p| Ok(p.clone().into_pyobject(py)?.into()))
2393 .collect()
2394 }
2395
2396 #[pyo3(name = "strategy_id_for_order")]
2398 fn py_strategy_id_for_order(&self, client_order_id: ClientOrderId) -> Option<StrategyId> {
2399 self.strategy_id_for_order(&client_order_id).copied()
2400 }
2401
2402 #[pyo3(name = "strategy_id_for_position")]
2404 fn py_strategy_id_for_position(&self, position_id: PositionId) -> Option<StrategyId> {
2405 self.strategy_id_for_position(&position_id).copied()
2406 }
2407
2408 #[pyo3(name = "position_snapshot_bytes")]
2413 fn py_position_snapshot_bytes(&self, position_id: PositionId) -> Option<Vec<Vec<u8>>> {
2414 self.position_snapshot_bytes(&position_id)
2415 }
2416
2417 #[pyo3(name = "position_snapshots", signature = (position_id=None, account_id=None))]
2423 fn py_position_snapshots(
2424 &self,
2425 py: Python,
2426 position_id: Option<PositionId>,
2427 account_id: Option<AccountId>,
2428 ) -> PyResult<Vec<Py<PyAny>>> {
2429 self.position_snapshots(position_id.as_ref(), account_id.as_ref())
2430 .into_iter()
2431 .map(|p| Ok(p.into_pyobject(py)?.into()))
2432 .collect()
2433 }
2434
2435 #[pyo3(name = "account")]
2437 fn py_account(&self, py: Python, account_id: AccountId) -> PyResult<Option<Py<PyAny>>> {
2438 match self.account(&account_id) {
2439 Some(account) => Ok(Some(account_any_to_pyobject(py, account.clone())?)),
2440 None => Ok(None),
2441 }
2442 }
2443
2444 #[pyo3(name = "account_for_venue")]
2446 fn py_account_for_venue(&self, py: Python, venue: Venue) -> PyResult<Option<Py<PyAny>>> {
2447 match self.account_for_venue(&venue) {
2448 Some(account) => Ok(Some(account_any_to_pyobject(py, account.clone())?)),
2449 None => Ok(None),
2450 }
2451 }
2452
2453 #[pyo3(name = "account_id")]
2455 fn py_account_id(&self, venue: Venue) -> Option<AccountId> {
2456 self.account_id(&venue).copied()
2457 }
2458
2459 #[pyo3(name = "get")]
2465 fn py_get(&self, key: &str) -> PyResult<Option<Vec<u8>>> {
2466 match self.get(key).map_err(to_pyvalue_err)? {
2467 Some(bytes) => Ok(Some(bytes.to_vec())),
2468 None => Ok(None),
2469 }
2470 }
2471
2472 #[pyo3(name = "add")]
2474 fn py_add_general(&mut self, key: &str, value: Vec<u8>) -> PyResult<()> {
2475 self.add(key, Bytes::from(value)).map_err(to_pyvalue_err)
2476 }
2477
2478 #[pyo3(name = "price")]
2480 fn py_price(&self, instrument_id: InstrumentId, price_type: PriceType) -> Option<Price> {
2481 self.price(&instrument_id, price_type)
2482 }
2483
2484 #[pyo3(name = "get_xrate")]
2486 fn py_get_xrate(
2487 &self,
2488 venue: Venue,
2489 from_currency: Currency,
2490 to_currency: Currency,
2491 price_type: PriceType,
2492 ) -> Option<f64> {
2493 self.get_xrate(venue, from_currency, to_currency, price_type)
2494 }
2495
2496 #[pyo3(name = "get_mark_xrate")]
2498 fn py_get_mark_xrate(&self, from_currency: Currency, to_currency: Currency) -> Option<f64> {
2499 self.get_mark_xrate(from_currency, to_currency)
2500 }
2501
2502 #[pyo3(name = "set_mark_xrate")]
2504 fn py_set_mark_xrate(&mut self, from_currency: Currency, to_currency: Currency, xrate: f64) {
2505 self.set_mark_xrate(from_currency, to_currency, xrate);
2506 }
2507
2508 #[pyo3(name = "clear_mark_xrate")]
2510 fn py_clear_mark_xrate(&mut self, from_currency: Currency, to_currency: Currency) {
2511 self.clear_mark_xrate(from_currency, to_currency);
2512 }
2513
2514 #[pyo3(name = "clear_mark_xrates")]
2516 fn py_clear_mark_xrates(&mut self) {
2517 self.clear_mark_xrates();
2518 }
2519
2520 #[pyo3(name = "calculate_unrealized_pnl")]
2522 #[expect(clippy::needless_pass_by_value)]
2523 fn py_calculate_unrealized_pnl(
2524 &self,
2525 py: Python,
2526 position: Py<PyAny>,
2527 ) -> PyResult<Option<Money>> {
2528 let position = position.extract::<Position>(py)?;
2529 Ok(self.calculate_unrealized_pnl(&position))
2530 }
2531
2532 #[pyo3(name = "own_order_book")]
2534 fn py_own_order_book(&self, instrument_id: InstrumentId) -> Option<OwnOrderBook> {
2535 self.own_order_book(&instrument_id).cloned()
2536 }
2537
2538 #[pyo3(name = "update_own_order_book")]
2546 fn py_update_own_order_book(&mut self, py: Python, order: Py<PyAny>) -> PyResult<()> {
2547 let order_any = pyobject_to_order_any(py, order)?;
2548 self.update_own_order_book(&order_any);
2549 Ok(())
2550 }
2551
2552 #[pyo3(name = "force_remove_from_own_order_book")]
2558 fn py_force_remove_from_own_order_book(&mut self, client_order_id: ClientOrderId) {
2559 self.force_remove_from_own_order_book(&client_order_id);
2560 }
2561
2562 #[pyo3(name = "audit_own_order_books")]
2569 fn py_audit_own_order_books(&mut self) {
2570 self.audit_own_order_books();
2571 }
2572}
2573
2574#[cfg(feature = "defi")]
2575#[pymethods]
2576impl Cache {
2577 #[pyo3(name = "add_pool")]
2583 fn py_add_pool(&mut self, pool: Pool) -> PyResult<()> {
2584 self.add_pool(pool).map_err(to_pyvalue_err)
2585 }
2586
2587 #[pyo3(name = "pool")]
2589 fn py_pool(&self, instrument_id: InstrumentId) -> Option<Pool> {
2590 self.pool(&instrument_id).cloned()
2591 }
2592
2593 #[pyo3(name = "pool_ids")]
2595 fn py_pool_ids(&self, venue: Option<Venue>) -> Vec<InstrumentId> {
2596 self.pool_ids(venue.as_ref())
2597 }
2598
2599 #[pyo3(name = "pools")]
2601 fn py_pools(&self, venue: Option<Venue>) -> Vec<Pool> {
2602 self.pools(venue.as_ref()).into_iter().cloned().collect()
2603 }
2604
2605 #[pyo3(name = "add_pool_profiler")]
2611 fn py_add_pool_profiler(&mut self, pool_profiler: PoolProfiler) -> PyResult<()> {
2612 self.add_pool_profiler(pool_profiler)
2613 .map_err(to_pyvalue_err)
2614 }
2615
2616 #[pyo3(name = "pool_profiler")]
2618 fn py_pool_profiler(&self, instrument_id: InstrumentId) -> Option<PoolProfiler> {
2619 self.pool_profiler(&instrument_id).cloned()
2620 }
2621
2622 #[pyo3(name = "pool_profiler_ids")]
2624 fn py_pool_profiler_ids(&self, venue: Option<Venue>) -> Vec<InstrumentId> {
2625 self.pool_profiler_ids(venue.as_ref())
2626 }
2627
2628 #[pyo3(name = "pool_profilers")]
2630 fn py_pool_profilers(&self, venue: Option<Venue>) -> Vec<PoolProfiler> {
2631 self.pool_profilers(venue.as_ref())
2632 .into_iter()
2633 .cloned()
2634 .collect()
2635 }
2636}