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