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, 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 = "price")]
197 fn py_price(&self, instrument_id: InstrumentId, price_type: PriceType) -> Option<Price> {
198 self.0.borrow().price(&instrument_id, price_type)
199 }
200
201 #[pyo3(name = "order_book")]
202 fn py_order_book(&self, instrument_id: InstrumentId) -> Option<OrderBook> {
203 self.0.borrow().order_book(&instrument_id).cloned()
204 }
205
206 #[pyo3(name = "has_order_book")]
207 fn py_has_order_book(&self, instrument_id: InstrumentId) -> bool {
208 self.0.borrow().has_order_book(&instrument_id)
209 }
210
211 #[pyo3(name = "book_update_count")]
212 fn py_book_update_count(&self, instrument_id: InstrumentId) -> usize {
213 self.0.borrow().book_update_count(&instrument_id)
214 }
215
216 #[pyo3(name = "has_quote_ticks")]
217 fn py_has_quote_ticks(&self, instrument_id: InstrumentId) -> bool {
218 self.0.borrow().has_quote_ticks(&instrument_id)
219 }
220
221 #[pyo3(name = "has_trade_ticks")]
222 fn py_has_trade_ticks(&self, instrument_id: InstrumentId) -> bool {
223 self.0.borrow().has_trade_ticks(&instrument_id)
224 }
225
226 #[pyo3(name = "has_bars")]
227 fn py_has_bars(&self, bar_type: BarType) -> bool {
228 self.0.borrow().has_bars(&bar_type)
229 }
230
231 #[pyo3(name = "quote_count")]
232 fn py_quote_count(&self, instrument_id: InstrumentId) -> usize {
233 self.0.borrow().quote_count(&instrument_id)
234 }
235
236 #[pyo3(name = "trade_count")]
237 fn py_trade_count(&self, instrument_id: InstrumentId) -> usize {
238 self.0.borrow().trade_count(&instrument_id)
239 }
240
241 #[pyo3(name = "bar_count")]
242 fn py_bar_count(&self, bar_type: BarType) -> usize {
243 self.0.borrow().bar_count(&bar_type)
244 }
245
246 #[pyo3(name = "get_xrate")]
247 fn py_get_xrate(
248 &self,
249 venue: Venue,
250 from_currency: Currency,
251 to_currency: Currency,
252 price_type: PriceType,
253 ) -> Option<f64> {
254 self.0
255 .borrow()
256 .get_xrate(venue, from_currency, to_currency, price_type)
257 }
258
259 #[pyo3(name = "get_mark_xrate")]
260 fn py_get_mark_xrate(&self, from_currency: Currency, to_currency: Currency) -> Option<f64> {
261 self.0.borrow().get_mark_xrate(from_currency, to_currency)
262 }
263
264 #[pyo3(name = "own_order_book")]
265 fn py_own_order_book(&self, instrument_id: InstrumentId) -> Option<OwnOrderBook> {
266 self.0.borrow().own_order_book(&instrument_id).cloned()
267 }
268
269 #[pyo3(name = "instrument")]
270 fn py_instrument(
271 &self,
272 py: Python,
273 instrument_id: InstrumentId,
274 ) -> PyResult<Option<Py<PyAny>>> {
275 let cache = self.0.borrow();
276 match cache.instrument(&instrument_id) {
277 Some(instrument) => Ok(Some(instrument_any_to_pyobject(py, instrument.clone())?)),
278 None => Ok(None),
279 }
280 }
281
282 #[pyo3(name = "instrument_ids", signature = (venue=None))]
283 fn py_instrument_ids(&self, venue: Option<Venue>) -> Vec<InstrumentId> {
284 self.0
285 .borrow()
286 .instrument_ids(venue.as_ref())
287 .into_iter()
288 .copied()
289 .collect()
290 }
291
292 #[pyo3(name = "instruments", signature = (venue=None))]
293 fn py_instruments(&self, py: Python, venue: Option<Venue>) -> PyResult<Vec<Py<PyAny>>> {
294 let cache = self.0.borrow();
295 let mut py_instruments = Vec::new();
296 match venue {
297 Some(venue) => {
298 for instrument in cache.instruments(&venue, None) {
299 py_instruments.push(instrument_any_to_pyobject(py, (*instrument).clone())?);
300 }
301 }
302 None => {
303 for instrument_id in cache.instrument_ids(None) {
304 if let Some(instrument) = cache.instrument(instrument_id) {
305 py_instruments.push(instrument_any_to_pyobject(py, instrument.clone())?);
306 }
307 }
308 }
309 }
310 Ok(py_instruments)
311 }
312
313 #[pyo3(name = "synthetic")]
314 fn py_synthetic(&self, instrument_id: InstrumentId) -> Option<SyntheticInstrument> {
315 self.0.borrow().synthetic(&instrument_id).cloned()
316 }
317
318 #[pyo3(name = "synthetic_ids")]
319 fn py_synthetic_ids(&self) -> Vec<InstrumentId> {
320 self.0
321 .borrow()
322 .synthetic_ids()
323 .into_iter()
324 .copied()
325 .collect()
326 }
327
328 #[pyo3(name = "account")]
329 fn py_account(&self, py: Python, account_id: AccountId) -> PyResult<Option<Py<PyAny>>> {
330 let cache = self.0.borrow();
331 match cache.account(&account_id) {
332 Some(account) => Ok(Some(account_any_to_pyobject(py, account.clone())?)),
333 None => Ok(None),
334 }
335 }
336
337 #[pyo3(name = "account_for_venue")]
338 fn py_account_for_venue(&self, py: Python, venue: Venue) -> PyResult<Option<Py<PyAny>>> {
339 let cache = self.0.borrow();
340 match cache.account_for_venue(&venue) {
341 Some(account) => Ok(Some(account_any_to_pyobject(py, account.clone())?)),
342 None => Ok(None),
343 }
344 }
345
346 #[pyo3(name = "account_id")]
347 fn py_account_id(&self, venue: Venue) -> Option<AccountId> {
348 self.0.borrow().account_id(&venue).copied()
349 }
350
351 #[pyo3(name = "client_order_ids", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
352 fn py_client_order_ids(
353 &self,
354 venue: Option<Venue>,
355 instrument_id: Option<InstrumentId>,
356 strategy_id: Option<StrategyId>,
357 account_id: Option<AccountId>,
358 ) -> Vec<ClientOrderId> {
359 self.0
360 .borrow()
361 .client_order_ids(
362 venue.as_ref(),
363 instrument_id.as_ref(),
364 strategy_id.as_ref(),
365 account_id.as_ref(),
366 )
367 .into_iter()
368 .collect()
369 }
370
371 #[pyo3(name = "client_order_ids_open", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
372 fn py_client_order_ids_open(
373 &self,
374 venue: Option<Venue>,
375 instrument_id: Option<InstrumentId>,
376 strategy_id: Option<StrategyId>,
377 account_id: Option<AccountId>,
378 ) -> Vec<ClientOrderId> {
379 self.0
380 .borrow()
381 .client_order_ids_open(
382 venue.as_ref(),
383 instrument_id.as_ref(),
384 strategy_id.as_ref(),
385 account_id.as_ref(),
386 )
387 .into_iter()
388 .collect()
389 }
390
391 #[pyo3(name = "client_order_ids_closed", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
392 fn py_client_order_ids_closed(
393 &self,
394 venue: Option<Venue>,
395 instrument_id: Option<InstrumentId>,
396 strategy_id: Option<StrategyId>,
397 account_id: Option<AccountId>,
398 ) -> Vec<ClientOrderId> {
399 self.0
400 .borrow()
401 .client_order_ids_closed(
402 venue.as_ref(),
403 instrument_id.as_ref(),
404 strategy_id.as_ref(),
405 account_id.as_ref(),
406 )
407 .into_iter()
408 .collect()
409 }
410
411 #[pyo3(name = "client_order_ids_emulated", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
412 fn py_client_order_ids_emulated(
413 &self,
414 venue: Option<Venue>,
415 instrument_id: Option<InstrumentId>,
416 strategy_id: Option<StrategyId>,
417 account_id: Option<AccountId>,
418 ) -> Vec<ClientOrderId> {
419 self.0
420 .borrow()
421 .client_order_ids_emulated(
422 venue.as_ref(),
423 instrument_id.as_ref(),
424 strategy_id.as_ref(),
425 account_id.as_ref(),
426 )
427 .into_iter()
428 .collect()
429 }
430
431 #[pyo3(name = "client_order_ids_inflight", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
432 fn py_client_order_ids_inflight(
433 &self,
434 venue: Option<Venue>,
435 instrument_id: Option<InstrumentId>,
436 strategy_id: Option<StrategyId>,
437 account_id: Option<AccountId>,
438 ) -> Vec<ClientOrderId> {
439 self.0
440 .borrow()
441 .client_order_ids_inflight(
442 venue.as_ref(),
443 instrument_id.as_ref(),
444 strategy_id.as_ref(),
445 account_id.as_ref(),
446 )
447 .into_iter()
448 .collect()
449 }
450
451 #[pyo3(name = "position_ids", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
452 fn py_position_ids(
453 &self,
454 venue: Option<Venue>,
455 instrument_id: Option<InstrumentId>,
456 strategy_id: Option<StrategyId>,
457 account_id: Option<AccountId>,
458 ) -> Vec<PositionId> {
459 self.0
460 .borrow()
461 .position_ids(
462 venue.as_ref(),
463 instrument_id.as_ref(),
464 strategy_id.as_ref(),
465 account_id.as_ref(),
466 )
467 .into_iter()
468 .collect()
469 }
470
471 #[pyo3(name = "position_open_ids", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
472 fn py_position_open_ids(
473 &self,
474 venue: Option<Venue>,
475 instrument_id: Option<InstrumentId>,
476 strategy_id: Option<StrategyId>,
477 account_id: Option<AccountId>,
478 ) -> Vec<PositionId> {
479 self.0
480 .borrow()
481 .position_open_ids(
482 venue.as_ref(),
483 instrument_id.as_ref(),
484 strategy_id.as_ref(),
485 account_id.as_ref(),
486 )
487 .into_iter()
488 .collect()
489 }
490
491 #[pyo3(name = "position_closed_ids", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
492 fn py_position_closed_ids(
493 &self,
494 venue: Option<Venue>,
495 instrument_id: Option<InstrumentId>,
496 strategy_id: Option<StrategyId>,
497 account_id: Option<AccountId>,
498 ) -> Vec<PositionId> {
499 self.0
500 .borrow()
501 .position_closed_ids(
502 venue.as_ref(),
503 instrument_id.as_ref(),
504 strategy_id.as_ref(),
505 account_id.as_ref(),
506 )
507 .into_iter()
508 .collect()
509 }
510
511 #[pyo3(name = "actor_ids")]
512 fn py_actor_ids(&self) -> Vec<ComponentId> {
513 self.0.borrow().actor_ids().into_iter().collect()
514 }
515
516 #[pyo3(name = "strategy_ids")]
517 fn py_strategy_ids(&self) -> Vec<StrategyId> {
518 self.0.borrow().strategy_ids().into_iter().collect()
519 }
520
521 #[pyo3(name = "exec_algorithm_ids")]
522 fn py_exec_algorithm_ids(&self) -> Vec<ExecAlgorithmId> {
523 self.0.borrow().exec_algorithm_ids().into_iter().collect()
524 }
525
526 #[pyo3(name = "order")]
527 fn py_order(&self, py: Python, client_order_id: ClientOrderId) -> PyResult<Option<Py<PyAny>>> {
528 let cache = self.0.borrow();
529 match cache.order(&client_order_id) {
530 Some(order) => Ok(Some(order_any_to_pyobject(py, order.clone())?)),
531 None => Ok(None),
532 }
533 }
534
535 #[pyo3(name = "client_order_id")]
536 fn py_client_order_id(&self, venue_order_id: VenueOrderId) -> Option<ClientOrderId> {
537 self.0.borrow().client_order_id(&venue_order_id).copied()
538 }
539
540 #[pyo3(name = "venue_order_id")]
541 fn py_venue_order_id(&self, client_order_id: ClientOrderId) -> Option<VenueOrderId> {
542 self.0.borrow().venue_order_id(&client_order_id).copied()
543 }
544
545 #[pyo3(name = "client_id")]
546 fn py_client_id(&self, client_order_id: ClientOrderId) -> Option<ClientId> {
547 self.0.borrow().client_id(&client_order_id).copied()
548 }
549
550 #[pyo3(name = "orders", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
551 #[allow(clippy::too_many_arguments)]
552 fn py_orders(
553 &self,
554 py: Python,
555 venue: Option<Venue>,
556 instrument_id: Option<InstrumentId>,
557 strategy_id: Option<StrategyId>,
558 account_id: Option<AccountId>,
559 side: Option<OrderSide>,
560 ) -> PyResult<Vec<Py<PyAny>>> {
561 let cache = self.0.borrow();
562 cache
563 .orders(
564 venue.as_ref(),
565 instrument_id.as_ref(),
566 strategy_id.as_ref(),
567 account_id.as_ref(),
568 side,
569 )
570 .into_iter()
571 .map(|o| order_any_to_pyobject(py, o.clone()))
572 .collect()
573 }
574
575 #[pyo3(name = "orders_open", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
576 #[allow(clippy::too_many_arguments)]
577 fn py_orders_open(
578 &self,
579 py: Python,
580 venue: Option<Venue>,
581 instrument_id: Option<InstrumentId>,
582 strategy_id: Option<StrategyId>,
583 account_id: Option<AccountId>,
584 side: Option<OrderSide>,
585 ) -> PyResult<Vec<Py<PyAny>>> {
586 let cache = self.0.borrow();
587 cache
588 .orders_open(
589 venue.as_ref(),
590 instrument_id.as_ref(),
591 strategy_id.as_ref(),
592 account_id.as_ref(),
593 side,
594 )
595 .into_iter()
596 .map(|o| order_any_to_pyobject(py, o.clone()))
597 .collect()
598 }
599
600 #[pyo3(name = "orders_closed", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
601 #[allow(clippy::too_many_arguments)]
602 fn py_orders_closed(
603 &self,
604 py: Python,
605 venue: Option<Venue>,
606 instrument_id: Option<InstrumentId>,
607 strategy_id: Option<StrategyId>,
608 account_id: Option<AccountId>,
609 side: Option<OrderSide>,
610 ) -> PyResult<Vec<Py<PyAny>>> {
611 let cache = self.0.borrow();
612 cache
613 .orders_closed(
614 venue.as_ref(),
615 instrument_id.as_ref(),
616 strategy_id.as_ref(),
617 account_id.as_ref(),
618 side,
619 )
620 .into_iter()
621 .map(|o| order_any_to_pyobject(py, o.clone()))
622 .collect()
623 }
624
625 #[pyo3(name = "orders_emulated", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
626 #[allow(clippy::too_many_arguments)]
627 fn py_orders_emulated(
628 &self,
629 py: Python,
630 venue: Option<Venue>,
631 instrument_id: Option<InstrumentId>,
632 strategy_id: Option<StrategyId>,
633 account_id: Option<AccountId>,
634 side: Option<OrderSide>,
635 ) -> PyResult<Vec<Py<PyAny>>> {
636 let cache = self.0.borrow();
637 cache
638 .orders_emulated(
639 venue.as_ref(),
640 instrument_id.as_ref(),
641 strategy_id.as_ref(),
642 account_id.as_ref(),
643 side,
644 )
645 .into_iter()
646 .map(|o| order_any_to_pyobject(py, o.clone()))
647 .collect()
648 }
649
650 #[pyo3(name = "orders_inflight", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
651 #[allow(clippy::too_many_arguments)]
652 fn py_orders_inflight(
653 &self,
654 py: Python,
655 venue: Option<Venue>,
656 instrument_id: Option<InstrumentId>,
657 strategy_id: Option<StrategyId>,
658 account_id: Option<AccountId>,
659 side: Option<OrderSide>,
660 ) -> PyResult<Vec<Py<PyAny>>> {
661 let cache = self.0.borrow();
662 cache
663 .orders_inflight(
664 venue.as_ref(),
665 instrument_id.as_ref(),
666 strategy_id.as_ref(),
667 account_id.as_ref(),
668 side,
669 )
670 .into_iter()
671 .map(|o| order_any_to_pyobject(py, o.clone()))
672 .collect()
673 }
674
675 #[pyo3(name = "orders_for_position")]
676 fn py_orders_for_position(
677 &self,
678 py: Python,
679 position_id: PositionId,
680 ) -> PyResult<Vec<Py<PyAny>>> {
681 let cache = self.0.borrow();
682 cache
683 .orders_for_position(&position_id)
684 .into_iter()
685 .map(|o| order_any_to_pyobject(py, o.clone()))
686 .collect()
687 }
688
689 #[pyo3(name = "order_exists")]
690 fn py_order_exists(&self, client_order_id: ClientOrderId) -> bool {
691 self.0.borrow().order_exists(&client_order_id)
692 }
693
694 #[pyo3(name = "is_order_open")]
695 fn py_is_order_open(&self, client_order_id: ClientOrderId) -> bool {
696 self.0.borrow().is_order_open(&client_order_id)
697 }
698
699 #[pyo3(name = "is_order_closed")]
700 fn py_is_order_closed(&self, client_order_id: ClientOrderId) -> bool {
701 self.0.borrow().is_order_closed(&client_order_id)
702 }
703
704 #[pyo3(name = "is_order_emulated")]
705 fn py_is_order_emulated(&self, client_order_id: ClientOrderId) -> bool {
706 self.0.borrow().is_order_emulated(&client_order_id)
707 }
708
709 #[pyo3(name = "is_order_inflight")]
710 fn py_is_order_inflight(&self, client_order_id: ClientOrderId) -> bool {
711 self.0.borrow().is_order_inflight(&client_order_id)
712 }
713
714 #[pyo3(name = "is_order_pending_cancel_local")]
715 fn py_is_order_pending_cancel_local(&self, client_order_id: ClientOrderId) -> bool {
716 self.0
717 .borrow()
718 .is_order_pending_cancel_local(&client_order_id)
719 }
720
721 #[pyo3(name = "orders_open_count", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
722 fn py_orders_open_count(
723 &self,
724 venue: Option<Venue>,
725 instrument_id: Option<InstrumentId>,
726 strategy_id: Option<StrategyId>,
727 account_id: Option<AccountId>,
728 side: Option<OrderSide>,
729 ) -> usize {
730 self.0.borrow().orders_open_count(
731 venue.as_ref(),
732 instrument_id.as_ref(),
733 strategy_id.as_ref(),
734 account_id.as_ref(),
735 side,
736 )
737 }
738
739 #[pyo3(name = "orders_closed_count", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
740 fn py_orders_closed_count(
741 &self,
742 venue: Option<Venue>,
743 instrument_id: Option<InstrumentId>,
744 strategy_id: Option<StrategyId>,
745 account_id: Option<AccountId>,
746 side: Option<OrderSide>,
747 ) -> usize {
748 self.0.borrow().orders_closed_count(
749 venue.as_ref(),
750 instrument_id.as_ref(),
751 strategy_id.as_ref(),
752 account_id.as_ref(),
753 side,
754 )
755 }
756
757 #[pyo3(name = "orders_emulated_count", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
758 fn py_orders_emulated_count(
759 &self,
760 venue: Option<Venue>,
761 instrument_id: Option<InstrumentId>,
762 strategy_id: Option<StrategyId>,
763 account_id: Option<AccountId>,
764 side: Option<OrderSide>,
765 ) -> usize {
766 self.0.borrow().orders_emulated_count(
767 venue.as_ref(),
768 instrument_id.as_ref(),
769 strategy_id.as_ref(),
770 account_id.as_ref(),
771 side,
772 )
773 }
774
775 #[pyo3(name = "orders_inflight_count", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
776 fn py_orders_inflight_count(
777 &self,
778 venue: Option<Venue>,
779 instrument_id: Option<InstrumentId>,
780 strategy_id: Option<StrategyId>,
781 account_id: Option<AccountId>,
782 side: Option<OrderSide>,
783 ) -> usize {
784 self.0.borrow().orders_inflight_count(
785 venue.as_ref(),
786 instrument_id.as_ref(),
787 strategy_id.as_ref(),
788 account_id.as_ref(),
789 side,
790 )
791 }
792
793 #[pyo3(name = "orders_total_count", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
794 fn py_orders_total_count(
795 &self,
796 venue: Option<Venue>,
797 instrument_id: Option<InstrumentId>,
798 strategy_id: Option<StrategyId>,
799 account_id: Option<AccountId>,
800 side: Option<OrderSide>,
801 ) -> usize {
802 self.0.borrow().orders_total_count(
803 venue.as_ref(),
804 instrument_id.as_ref(),
805 strategy_id.as_ref(),
806 account_id.as_ref(),
807 side,
808 )
809 }
810
811 #[pyo3(name = "order_list")]
812 fn py_order_list(&self, py: Python, order_list_id: OrderListId) -> PyResult<Option<Py<PyAny>>> {
813 let cache = self.0.borrow();
814 match cache.order_list(&order_list_id) {
815 Some(order_list) => Ok(Some(order_list.clone().into_pyobject(py)?.into())),
816 None => Ok(None),
817 }
818 }
819
820 #[pyo3(name = "order_lists", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None))]
821 fn py_order_lists(
822 &self,
823 py: Python,
824 venue: Option<Venue>,
825 instrument_id: Option<InstrumentId>,
826 strategy_id: Option<StrategyId>,
827 account_id: Option<AccountId>,
828 ) -> PyResult<Vec<Py<PyAny>>> {
829 let cache = self.0.borrow();
830 cache
831 .order_lists(
832 venue.as_ref(),
833 instrument_id.as_ref(),
834 strategy_id.as_ref(),
835 account_id.as_ref(),
836 )
837 .into_iter()
838 .map(|ol| Ok(ol.clone().into_pyobject(py)?.into()))
839 .collect()
840 }
841
842 #[pyo3(name = "order_list_exists")]
843 fn py_order_list_exists(&self, order_list_id: OrderListId) -> bool {
844 self.0.borrow().order_list_exists(&order_list_id)
845 }
846
847 #[pyo3(name = "orders_for_exec_algorithm", signature = (exec_algorithm_id, venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
848 #[allow(clippy::too_many_arguments)]
849 fn py_orders_for_exec_algorithm(
850 &self,
851 py: Python,
852 exec_algorithm_id: ExecAlgorithmId,
853 venue: Option<Venue>,
854 instrument_id: Option<InstrumentId>,
855 strategy_id: Option<StrategyId>,
856 account_id: Option<AccountId>,
857 side: Option<OrderSide>,
858 ) -> PyResult<Vec<Py<PyAny>>> {
859 let cache = self.0.borrow();
860 cache
861 .orders_for_exec_algorithm(
862 &exec_algorithm_id,
863 venue.as_ref(),
864 instrument_id.as_ref(),
865 strategy_id.as_ref(),
866 account_id.as_ref(),
867 side,
868 )
869 .into_iter()
870 .map(|o| order_any_to_pyobject(py, o.clone()))
871 .collect()
872 }
873
874 #[pyo3(name = "orders_for_exec_spawn")]
875 fn py_orders_for_exec_spawn(
876 &self,
877 py: Python,
878 exec_spawn_id: ClientOrderId,
879 ) -> PyResult<Vec<Py<PyAny>>> {
880 let cache = self.0.borrow();
881 cache
882 .orders_for_exec_spawn(&exec_spawn_id)
883 .into_iter()
884 .map(|o| order_any_to_pyobject(py, o.clone()))
885 .collect()
886 }
887
888 #[pyo3(name = "exec_spawn_total_quantity")]
889 fn py_exec_spawn_total_quantity(
890 &self,
891 exec_spawn_id: ClientOrderId,
892 active_only: bool,
893 ) -> Option<Quantity> {
894 self.0
895 .borrow()
896 .exec_spawn_total_quantity(&exec_spawn_id, active_only)
897 }
898
899 #[pyo3(name = "exec_spawn_total_filled_qty")]
900 fn py_exec_spawn_total_filled_qty(
901 &self,
902 exec_spawn_id: ClientOrderId,
903 active_only: bool,
904 ) -> Option<Quantity> {
905 self.0
906 .borrow()
907 .exec_spawn_total_filled_qty(&exec_spawn_id, active_only)
908 }
909
910 #[pyo3(name = "exec_spawn_total_leaves_qty")]
911 fn py_exec_spawn_total_leaves_qty(
912 &self,
913 exec_spawn_id: ClientOrderId,
914 active_only: bool,
915 ) -> Option<Quantity> {
916 self.0
917 .borrow()
918 .exec_spawn_total_leaves_qty(&exec_spawn_id, active_only)
919 }
920
921 #[pyo3(name = "position")]
922 fn py_position(&self, py: Python, position_id: PositionId) -> PyResult<Option<Py<PyAny>>> {
923 let cache = self.0.borrow();
924 match cache.position(&position_id) {
925 Some(position) => Ok(Some(position.clone().into_pyobject(py)?.into())),
926 None => Ok(None),
927 }
928 }
929
930 #[pyo3(name = "position_for_order")]
931 fn py_position_for_order(
932 &self,
933 py: Python,
934 client_order_id: ClientOrderId,
935 ) -> PyResult<Option<Py<PyAny>>> {
936 let cache = self.0.borrow();
937 match cache.position_for_order(&client_order_id) {
938 Some(position) => Ok(Some(position.clone().into_pyobject(py)?.into())),
939 None => Ok(None),
940 }
941 }
942
943 #[pyo3(name = "position_id")]
944 fn py_position_id(&self, client_order_id: ClientOrderId) -> Option<PositionId> {
945 self.0.borrow().position_id(&client_order_id).copied()
946 }
947
948 #[pyo3(name = "positions", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
949 #[allow(clippy::too_many_arguments)]
950 fn py_positions(
951 &self,
952 py: Python,
953 venue: Option<Venue>,
954 instrument_id: Option<InstrumentId>,
955 strategy_id: Option<StrategyId>,
956 account_id: Option<AccountId>,
957 side: Option<PositionSide>,
958 ) -> PyResult<Vec<Py<PyAny>>> {
959 let cache = self.0.borrow();
960 cache
961 .positions(
962 venue.as_ref(),
963 instrument_id.as_ref(),
964 strategy_id.as_ref(),
965 account_id.as_ref(),
966 side,
967 )
968 .into_iter()
969 .map(|p| Ok(p.clone().into_pyobject(py)?.into()))
970 .collect()
971 }
972
973 #[pyo3(name = "positions_open", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
974 #[allow(clippy::too_many_arguments)]
975 fn py_positions_open(
976 &self,
977 py: Python,
978 venue: Option<Venue>,
979 instrument_id: Option<InstrumentId>,
980 strategy_id: Option<StrategyId>,
981 account_id: Option<AccountId>,
982 side: Option<PositionSide>,
983 ) -> PyResult<Vec<Py<PyAny>>> {
984 let cache = self.0.borrow();
985 cache
986 .positions_open(
987 venue.as_ref(),
988 instrument_id.as_ref(),
989 strategy_id.as_ref(),
990 account_id.as_ref(),
991 side,
992 )
993 .into_iter()
994 .map(|p| Ok(p.clone().into_pyobject(py)?.into()))
995 .collect()
996 }
997
998 #[pyo3(name = "positions_closed", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
999 #[allow(clippy::too_many_arguments)]
1000 fn py_positions_closed(
1001 &self,
1002 py: Python,
1003 venue: Option<Venue>,
1004 instrument_id: Option<InstrumentId>,
1005 strategy_id: Option<StrategyId>,
1006 account_id: Option<AccountId>,
1007 side: Option<PositionSide>,
1008 ) -> PyResult<Vec<Py<PyAny>>> {
1009 let cache = self.0.borrow();
1010 cache
1011 .positions_closed(
1012 venue.as_ref(),
1013 instrument_id.as_ref(),
1014 strategy_id.as_ref(),
1015 account_id.as_ref(),
1016 side,
1017 )
1018 .into_iter()
1019 .map(|p| Ok(p.clone().into_pyobject(py)?.into()))
1020 .collect()
1021 }
1022
1023 #[pyo3(name = "position_exists")]
1024 fn py_position_exists(&self, position_id: PositionId) -> bool {
1025 self.0.borrow().position_exists(&position_id)
1026 }
1027
1028 #[pyo3(name = "is_position_open")]
1029 fn py_is_position_open(&self, position_id: PositionId) -> bool {
1030 self.0.borrow().is_position_open(&position_id)
1031 }
1032
1033 #[pyo3(name = "is_position_closed")]
1034 fn py_is_position_closed(&self, position_id: PositionId) -> bool {
1035 self.0.borrow().is_position_closed(&position_id)
1036 }
1037
1038 #[pyo3(name = "positions_open_count", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
1039 fn py_positions_open_count(
1040 &self,
1041 venue: Option<Venue>,
1042 instrument_id: Option<InstrumentId>,
1043 strategy_id: Option<StrategyId>,
1044 account_id: Option<AccountId>,
1045 side: Option<PositionSide>,
1046 ) -> usize {
1047 self.0.borrow().positions_open_count(
1048 venue.as_ref(),
1049 instrument_id.as_ref(),
1050 strategy_id.as_ref(),
1051 account_id.as_ref(),
1052 side,
1053 )
1054 }
1055
1056 #[pyo3(name = "positions_closed_count", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
1057 fn py_positions_closed_count(
1058 &self,
1059 venue: Option<Venue>,
1060 instrument_id: Option<InstrumentId>,
1061 strategy_id: Option<StrategyId>,
1062 account_id: Option<AccountId>,
1063 side: Option<PositionSide>,
1064 ) -> usize {
1065 self.0.borrow().positions_closed_count(
1066 venue.as_ref(),
1067 instrument_id.as_ref(),
1068 strategy_id.as_ref(),
1069 account_id.as_ref(),
1070 side,
1071 )
1072 }
1073
1074 #[pyo3(name = "positions_total_count", signature = (venue=None, instrument_id=None, strategy_id=None, account_id=None, side=None))]
1075 fn py_positions_total_count(
1076 &self,
1077 venue: Option<Venue>,
1078 instrument_id: Option<InstrumentId>,
1079 strategy_id: Option<StrategyId>,
1080 account_id: Option<AccountId>,
1081 side: Option<PositionSide>,
1082 ) -> usize {
1083 self.0.borrow().positions_total_count(
1084 venue.as_ref(),
1085 instrument_id.as_ref(),
1086 strategy_id.as_ref(),
1087 account_id.as_ref(),
1088 side,
1089 )
1090 }
1091
1092 #[pyo3(name = "strategy_id_for_order")]
1093 fn py_strategy_id_for_order(&self, client_order_id: ClientOrderId) -> Option<StrategyId> {
1094 self.0
1095 .borrow()
1096 .strategy_id_for_order(&client_order_id)
1097 .copied()
1098 }
1099
1100 #[pyo3(name = "strategy_id_for_position")]
1101 fn py_strategy_id_for_position(&self, position_id: PositionId) -> Option<StrategyId> {
1102 self.0
1103 .borrow()
1104 .strategy_id_for_position(&position_id)
1105 .copied()
1106 }
1107
1108 #[pyo3(name = "position_snapshot_bytes")]
1109 fn py_position_snapshot_bytes(&self, position_id: PositionId) -> Option<Vec<u8>> {
1110 self.0.borrow().position_snapshot_bytes(&position_id)
1111 }
1112}
1113
1114#[cfg(feature = "defi")]
1115#[pymethods]
1116#[pyo3_stub_gen::derive::gen_stub_pymethods]
1117impl PyCache {
1118 #[pyo3(name = "pool")]
1119 fn py_pool(&self, instrument_id: InstrumentId) -> Option<Pool> {
1120 self.0
1121 .try_borrow()
1122 .ok()
1123 .and_then(|cache| cache.pool(&instrument_id).cloned())
1124 }
1125
1126 #[pyo3(name = "pool_profiler")]
1127 fn py_pool_profiler(&self, instrument_id: InstrumentId) -> Option<PoolProfiler> {
1128 self.0
1129 .try_borrow()
1130 .ok()
1131 .and_then(|cache| cache.pool_profiler(&instrument_id).cloned())
1132 }
1133}
1134
1135#[pymethods]
1136#[pyo3_stub_gen::derive::gen_stub_pymethods]
1137impl CacheConfig {
1138 #[new]
1140 #[allow(clippy::too_many_arguments)]
1141 fn py_new(
1142 encoding: Option<SerializationEncoding>,
1143 timestamps_as_iso8601: Option<bool>,
1144 buffer_interval_ms: Option<usize>,
1145 bulk_read_batch_size: Option<usize>,
1146 use_trader_prefix: Option<bool>,
1147 use_instance_id: Option<bool>,
1148 flush_on_start: Option<bool>,
1149 drop_instruments_on_reset: Option<bool>,
1150 tick_capacity: Option<usize>,
1151 bar_capacity: Option<usize>,
1152 save_market_data: Option<bool>,
1153 ) -> Self {
1154 Self::new(
1155 None, encoding.unwrap_or(SerializationEncoding::MsgPack),
1157 timestamps_as_iso8601.unwrap_or(false),
1158 buffer_interval_ms,
1159 bulk_read_batch_size,
1160 use_trader_prefix.unwrap_or(true),
1161 use_instance_id.unwrap_or(false),
1162 flush_on_start.unwrap_or(false),
1163 drop_instruments_on_reset.unwrap_or(true),
1164 tick_capacity.unwrap_or(10_000),
1165 bar_capacity.unwrap_or(10_000),
1166 save_market_data.unwrap_or(false),
1167 )
1168 }
1169
1170 fn __str__(&self) -> String {
1171 format!("{self:?}")
1172 }
1173
1174 fn __repr__(&self) -> String {
1175 format!("{self:?}")
1176 }
1177
1178 #[getter]
1179 fn encoding(&self) -> SerializationEncoding {
1180 self.encoding
1181 }
1182
1183 #[getter]
1184 fn timestamps_as_iso8601(&self) -> bool {
1185 self.timestamps_as_iso8601
1186 }
1187
1188 #[getter]
1189 fn buffer_interval_ms(&self) -> Option<usize> {
1190 self.buffer_interval_ms
1191 }
1192
1193 #[getter]
1194 fn bulk_read_batch_size(&self) -> Option<usize> {
1195 self.bulk_read_batch_size
1196 }
1197
1198 #[getter]
1199 fn use_trader_prefix(&self) -> bool {
1200 self.use_trader_prefix
1201 }
1202
1203 #[getter]
1204 fn use_instance_id(&self) -> bool {
1205 self.use_instance_id
1206 }
1207
1208 #[getter]
1209 fn flush_on_start(&self) -> bool {
1210 self.flush_on_start
1211 }
1212
1213 #[getter]
1214 fn drop_instruments_on_reset(&self) -> bool {
1215 self.drop_instruments_on_reset
1216 }
1217
1218 #[getter]
1219 fn tick_capacity(&self) -> usize {
1220 self.tick_capacity
1221 }
1222
1223 #[getter]
1224 fn bar_capacity(&self) -> usize {
1225 self.bar_capacity
1226 }
1227
1228 #[getter]
1229 fn save_market_data(&self) -> bool {
1230 self.save_market_data
1231 }
1232}
1233
1234#[pymethods]
1235impl Cache {
1236 #[new]
1238 fn py_new(config: Option<CacheConfig>) -> Self {
1239 Self::new(config, None)
1240 }
1241
1242 fn __repr__(&self) -> String {
1243 format!("{self:?}")
1244 }
1245
1246 #[pyo3(name = "reset")]
1250 fn py_reset(&mut self) {
1251 self.reset();
1252 }
1253
1254 #[pyo3(name = "dispose")]
1258 fn py_dispose(&mut self) {
1259 self.dispose();
1260 }
1261
1262 #[pyo3(name = "add_currency")]
1268 fn py_add_currency(&mut self, currency: Currency) -> PyResult<()> {
1269 self.add_currency(currency).map_err(to_pyvalue_err)
1270 }
1271
1272 #[pyo3(name = "add_instrument")]
1278 fn py_add_instrument(&mut self, py: Python, instrument: Py<PyAny>) -> PyResult<()> {
1279 let instrument_any = pyobject_to_instrument_any(py, instrument)?;
1280 self.add_instrument(instrument_any).map_err(to_pyvalue_err)
1281 }
1282
1283 #[pyo3(name = "instrument")]
1285 fn py_instrument(
1286 &self,
1287 py: Python,
1288 instrument_id: InstrumentId,
1289 ) -> PyResult<Option<Py<PyAny>>> {
1290 match self.instrument(&instrument_id) {
1291 Some(instrument) => Ok(Some(instrument_any_to_pyobject(py, instrument.clone())?)),
1292 None => Ok(None),
1293 }
1294 }
1295
1296 #[pyo3(name = "instrument_ids")]
1298 fn py_instrument_ids(&self, venue: Option<Venue>) -> Vec<InstrumentId> {
1299 self.instrument_ids(venue.as_ref())
1300 .into_iter()
1301 .copied()
1302 .collect()
1303 }
1304
1305 #[pyo3(name = "instruments")]
1307 fn py_instruments(&self, py: Python, venue: Option<Venue>) -> PyResult<Vec<Py<PyAny>>> {
1308 let mut py_instruments = Vec::new();
1309
1310 match venue {
1311 Some(venue) => {
1312 let instruments = self.instruments(&venue, None);
1313 for instrument in instruments {
1314 py_instruments.push(instrument_any_to_pyobject(py, (*instrument).clone())?);
1315 }
1316 }
1317 None => {
1318 let instrument_ids = self.instrument_ids(None);
1319 for instrument_id in instrument_ids {
1320 if let Some(instrument) = self.instrument(instrument_id) {
1321 py_instruments.push(instrument_any_to_pyobject(py, instrument.clone())?);
1322 }
1323 }
1324 }
1325 }
1326
1327 Ok(py_instruments)
1328 }
1329
1330 #[pyo3(name = "add_order")]
1338 fn py_add_order(
1339 &mut self,
1340 py: Python,
1341 order: Py<PyAny>,
1342 position_id: Option<PositionId>,
1343 client_id: Option<ClientId>,
1344 replace_existing: Option<bool>,
1345 ) -> PyResult<()> {
1346 let order_any = pyobject_to_order_any(py, order)?;
1347 self.add_order(
1348 order_any,
1349 position_id,
1350 client_id,
1351 replace_existing.unwrap_or(false),
1352 )
1353 .map_err(to_pyvalue_err)
1354 }
1355
1356 #[pyo3(name = "order")]
1358 fn py_order(&self, py: Python, client_order_id: ClientOrderId) -> PyResult<Option<Py<PyAny>>> {
1359 match self.order(&client_order_id) {
1360 Some(order) => Ok(Some(order_any_to_pyobject(py, order.clone())?)),
1361 None => Ok(None),
1362 }
1363 }
1364
1365 #[pyo3(name = "order_exists")]
1367 fn py_order_exists(&self, client_order_id: ClientOrderId) -> bool {
1368 self.order_exists(&client_order_id)
1369 }
1370
1371 #[pyo3(name = "is_order_open")]
1373 fn py_is_order_open(&self, client_order_id: ClientOrderId) -> bool {
1374 self.is_order_open(&client_order_id)
1375 }
1376
1377 #[pyo3(name = "is_order_closed")]
1379 fn py_is_order_closed(&self, client_order_id: ClientOrderId) -> bool {
1380 self.is_order_closed(&client_order_id)
1381 }
1382
1383 #[pyo3(name = "is_order_active_local")]
1388 fn py_is_order_active_local(&self, client_order_id: ClientOrderId) -> bool {
1389 self.is_order_active_local(&client_order_id)
1390 }
1391
1392 #[pyo3(name = "orders_active_local")]
1397 fn py_orders_active_local(
1398 &self,
1399 py: Python,
1400 venue: Option<Venue>,
1401 instrument_id: Option<InstrumentId>,
1402 strategy_id: Option<StrategyId>,
1403 account_id: Option<AccountId>,
1404 side: Option<OrderSide>,
1405 ) -> PyResult<Vec<Py<PyAny>>> {
1406 self.orders_active_local(
1407 venue.as_ref(),
1408 instrument_id.as_ref(),
1409 strategy_id.as_ref(),
1410 account_id.as_ref(),
1411 side,
1412 )
1413 .into_iter()
1414 .map(|order| order_any_to_pyobject(py, order.clone()))
1415 .collect()
1416 }
1417
1418 #[pyo3(name = "orders_active_local_count")]
1423 fn py_orders_active_local_count(
1424 &self,
1425 venue: Option<Venue>,
1426 instrument_id: Option<InstrumentId>,
1427 strategy_id: Option<StrategyId>,
1428 account_id: Option<AccountId>,
1429 side: Option<OrderSide>,
1430 ) -> usize {
1431 self.orders_active_local_count(
1432 venue.as_ref(),
1433 instrument_id.as_ref(),
1434 strategy_id.as_ref(),
1435 account_id.as_ref(),
1436 side,
1437 )
1438 }
1439
1440 #[pyo3(name = "orders_open_count")]
1442 fn py_orders_open_count(
1443 &self,
1444 venue: Option<Venue>,
1445 instrument_id: Option<InstrumentId>,
1446 strategy_id: Option<StrategyId>,
1447 account_id: Option<AccountId>,
1448 side: Option<OrderSide>,
1449 ) -> usize {
1450 self.orders_open_count(
1451 venue.as_ref(),
1452 instrument_id.as_ref(),
1453 strategy_id.as_ref(),
1454 account_id.as_ref(),
1455 side,
1456 )
1457 }
1458
1459 #[pyo3(name = "orders_closed_count")]
1461 fn py_orders_closed_count(
1462 &self,
1463 venue: Option<Venue>,
1464 instrument_id: Option<InstrumentId>,
1465 strategy_id: Option<StrategyId>,
1466 account_id: Option<AccountId>,
1467 side: Option<OrderSide>,
1468 ) -> usize {
1469 self.orders_closed_count(
1470 venue.as_ref(),
1471 instrument_id.as_ref(),
1472 strategy_id.as_ref(),
1473 account_id.as_ref(),
1474 side,
1475 )
1476 }
1477
1478 #[pyo3(name = "orders_total_count")]
1480 fn py_orders_total_count(
1481 &self,
1482 venue: Option<Venue>,
1483 instrument_id: Option<InstrumentId>,
1484 strategy_id: Option<StrategyId>,
1485 account_id: Option<AccountId>,
1486 side: Option<OrderSide>,
1487 ) -> usize {
1488 self.orders_total_count(
1489 venue.as_ref(),
1490 instrument_id.as_ref(),
1491 strategy_id.as_ref(),
1492 account_id.as_ref(),
1493 side,
1494 )
1495 }
1496
1497 #[pyo3(name = "add_position")]
1499 #[allow(clippy::needless_pass_by_value)]
1500 fn py_add_position(
1501 &mut self,
1502 py: Python,
1503 position: Py<PyAny>,
1504 oms_type: OmsType,
1505 ) -> PyResult<()> {
1506 let position_obj = position.extract::<Position>(py)?;
1507 self.add_position(&position_obj, oms_type)
1508 .map_err(to_pyvalue_err)
1509 }
1510
1511 #[pyo3(name = "position")]
1513 fn py_position(&self, py: Python, position_id: PositionId) -> PyResult<Option<Py<PyAny>>> {
1514 match self.position(&position_id) {
1515 Some(position) => Ok(Some(position.clone().into_pyobject(py)?.into())),
1516 None => Ok(None),
1517 }
1518 }
1519
1520 #[pyo3(name = "position_exists")]
1522 fn py_position_exists(&self, position_id: PositionId) -> bool {
1523 self.position_exists(&position_id)
1524 }
1525
1526 #[pyo3(name = "is_position_open")]
1528 fn py_is_position_open(&self, position_id: PositionId) -> bool {
1529 self.is_position_open(&position_id)
1530 }
1531
1532 #[pyo3(name = "is_position_closed")]
1534 fn py_is_position_closed(&self, position_id: PositionId) -> bool {
1535 self.is_position_closed(&position_id)
1536 }
1537
1538 #[pyo3(name = "positions_open_count")]
1540 fn py_positions_open_count(
1541 &self,
1542 venue: Option<Venue>,
1543 instrument_id: Option<InstrumentId>,
1544 strategy_id: Option<StrategyId>,
1545 account_id: Option<AccountId>,
1546 side: Option<PositionSide>,
1547 ) -> usize {
1548 self.positions_open_count(
1549 venue.as_ref(),
1550 instrument_id.as_ref(),
1551 strategy_id.as_ref(),
1552 account_id.as_ref(),
1553 side,
1554 )
1555 }
1556
1557 #[pyo3(name = "positions_closed_count")]
1559 fn py_positions_closed_count(
1560 &self,
1561 venue: Option<Venue>,
1562 instrument_id: Option<InstrumentId>,
1563 strategy_id: Option<StrategyId>,
1564 account_id: Option<AccountId>,
1565 side: Option<PositionSide>,
1566 ) -> usize {
1567 self.positions_closed_count(
1568 venue.as_ref(),
1569 instrument_id.as_ref(),
1570 strategy_id.as_ref(),
1571 account_id.as_ref(),
1572 side,
1573 )
1574 }
1575
1576 #[pyo3(name = "positions_total_count")]
1578 fn py_positions_total_count(
1579 &self,
1580 venue: Option<Venue>,
1581 instrument_id: Option<InstrumentId>,
1582 strategy_id: Option<StrategyId>,
1583 account_id: Option<AccountId>,
1584 side: Option<PositionSide>,
1585 ) -> usize {
1586 self.positions_total_count(
1587 venue.as_ref(),
1588 instrument_id.as_ref(),
1589 strategy_id.as_ref(),
1590 account_id.as_ref(),
1591 side,
1592 )
1593 }
1594
1595 #[pyo3(name = "add_quote")]
1601 fn py_add_quote(&mut self, quote: QuoteTick) -> PyResult<()> {
1602 self.add_quote(quote).map_err(to_pyvalue_err)
1603 }
1604
1605 #[pyo3(name = "add_trade")]
1611 fn py_add_trade(&mut self, trade: TradeTick) -> PyResult<()> {
1612 self.add_trade(trade).map_err(to_pyvalue_err)
1613 }
1614
1615 #[pyo3(name = "add_bar")]
1621 fn py_add_bar(&mut self, bar: Bar) -> PyResult<()> {
1622 self.add_bar(bar).map_err(to_pyvalue_err)
1623 }
1624
1625 #[pyo3(name = "quote")]
1627 fn py_quote(&self, instrument_id: InstrumentId) -> Option<QuoteTick> {
1628 self.quote(&instrument_id).copied()
1629 }
1630
1631 #[pyo3(name = "trade")]
1633 fn py_trade(&self, instrument_id: InstrumentId) -> Option<TradeTick> {
1634 self.trade(&instrument_id).copied()
1635 }
1636
1637 #[pyo3(name = "bar")]
1639 fn py_bar(&self, bar_type: BarType) -> Option<Bar> {
1640 self.bar(&bar_type).copied()
1641 }
1642
1643 #[pyo3(name = "quotes")]
1645 fn py_quotes(&self, instrument_id: InstrumentId) -> Option<Vec<QuoteTick>> {
1646 self.quotes(&instrument_id)
1647 }
1648
1649 #[pyo3(name = "trades")]
1651 fn py_trades(&self, instrument_id: InstrumentId) -> Option<Vec<TradeTick>> {
1652 self.trades(&instrument_id)
1653 }
1654
1655 #[pyo3(name = "bars")]
1657 fn py_bars(&self, bar_type: BarType) -> Option<Vec<Bar>> {
1658 self.bars(&bar_type)
1659 }
1660
1661 #[pyo3(name = "has_quote_ticks")]
1663 fn py_has_quote_ticks(&self, instrument_id: InstrumentId) -> bool {
1664 self.has_quote_ticks(&instrument_id)
1665 }
1666
1667 #[pyo3(name = "has_trade_ticks")]
1669 fn py_has_trade_ticks(&self, instrument_id: InstrumentId) -> bool {
1670 self.has_trade_ticks(&instrument_id)
1671 }
1672
1673 #[pyo3(name = "has_bars")]
1675 fn py_has_bars(&self, bar_type: BarType) -> bool {
1676 self.has_bars(&bar_type)
1677 }
1678
1679 #[pyo3(name = "quote_count")]
1681 fn py_quote_count(&self, instrument_id: InstrumentId) -> usize {
1682 self.quote_count(&instrument_id)
1683 }
1684
1685 #[pyo3(name = "trade_count")]
1687 fn py_trade_count(&self, instrument_id: InstrumentId) -> usize {
1688 self.trade_count(&instrument_id)
1689 }
1690
1691 #[pyo3(name = "bar_count")]
1693 fn py_bar_count(&self, bar_type: BarType) -> usize {
1694 self.bar_count(&bar_type)
1695 }
1696
1697 #[pyo3(name = "mark_price")]
1699 fn py_mark_price(&self, instrument_id: InstrumentId) -> Option<MarkPriceUpdate> {
1700 self.mark_price(&instrument_id).copied()
1701 }
1702
1703 #[pyo3(name = "mark_prices")]
1705 fn py_mark_prices(&self, instrument_id: InstrumentId) -> Option<Vec<MarkPriceUpdate>> {
1706 self.mark_prices(&instrument_id)
1707 }
1708
1709 #[pyo3(name = "index_price")]
1711 fn py_index_price(&self, instrument_id: InstrumentId) -> Option<IndexPriceUpdate> {
1712 self.index_price(&instrument_id).copied()
1713 }
1714
1715 #[pyo3(name = "index_prices")]
1717 fn py_index_prices(&self, instrument_id: InstrumentId) -> Option<Vec<IndexPriceUpdate>> {
1718 self.index_prices(&instrument_id)
1719 }
1720
1721 #[pyo3(name = "funding_rate")]
1723 fn py_funding_rate(&self, instrument_id: InstrumentId) -> Option<FundingRateUpdate> {
1724 self.funding_rate(&instrument_id).copied()
1725 }
1726
1727 #[pyo3(name = "order_book")]
1729 fn py_order_book(&self, instrument_id: InstrumentId) -> Option<OrderBook> {
1730 self.order_book(&instrument_id).cloned()
1731 }
1732
1733 #[pyo3(name = "has_order_book")]
1735 fn py_has_order_book(&self, instrument_id: InstrumentId) -> bool {
1736 self.has_order_book(&instrument_id)
1737 }
1738
1739 #[pyo3(name = "book_update_count")]
1741 fn py_book_update_count(&self, instrument_id: InstrumentId) -> usize {
1742 self.book_update_count(&instrument_id)
1743 }
1744
1745 #[pyo3(name = "synthetic")]
1747 fn py_synthetic(&self, instrument_id: InstrumentId) -> Option<SyntheticInstrument> {
1748 self.synthetic(&instrument_id).cloned()
1749 }
1750
1751 #[pyo3(name = "synthetic_ids")]
1753 fn py_synthetic_ids(&self) -> Vec<InstrumentId> {
1754 self.synthetic_ids().into_iter().copied().collect()
1755 }
1756
1757 #[pyo3(name = "client_order_ids")]
1759 fn py_client_order_ids(
1760 &self,
1761 venue: Option<Venue>,
1762 instrument_id: Option<InstrumentId>,
1763 strategy_id: Option<StrategyId>,
1764 account_id: Option<AccountId>,
1765 ) -> Vec<ClientOrderId> {
1766 self.client_order_ids(
1767 venue.as_ref(),
1768 instrument_id.as_ref(),
1769 strategy_id.as_ref(),
1770 account_id.as_ref(),
1771 )
1772 .into_iter()
1773 .collect()
1774 }
1775
1776 #[pyo3(name = "client_order_ids_open")]
1778 fn py_client_order_ids_open(
1779 &self,
1780 venue: Option<Venue>,
1781 instrument_id: Option<InstrumentId>,
1782 strategy_id: Option<StrategyId>,
1783 account_id: Option<AccountId>,
1784 ) -> Vec<ClientOrderId> {
1785 self.client_order_ids_open(
1786 venue.as_ref(),
1787 instrument_id.as_ref(),
1788 strategy_id.as_ref(),
1789 account_id.as_ref(),
1790 )
1791 .into_iter()
1792 .collect()
1793 }
1794
1795 #[pyo3(name = "client_order_ids_closed")]
1797 fn py_client_order_ids_closed(
1798 &self,
1799 venue: Option<Venue>,
1800 instrument_id: Option<InstrumentId>,
1801 strategy_id: Option<StrategyId>,
1802 account_id: Option<AccountId>,
1803 ) -> Vec<ClientOrderId> {
1804 self.client_order_ids_closed(
1805 venue.as_ref(),
1806 instrument_id.as_ref(),
1807 strategy_id.as_ref(),
1808 account_id.as_ref(),
1809 )
1810 .into_iter()
1811 .collect()
1812 }
1813
1814 #[pyo3(name = "client_order_ids_emulated")]
1816 fn py_client_order_ids_emulated(
1817 &self,
1818 venue: Option<Venue>,
1819 instrument_id: Option<InstrumentId>,
1820 strategy_id: Option<StrategyId>,
1821 account_id: Option<AccountId>,
1822 ) -> Vec<ClientOrderId> {
1823 self.client_order_ids_emulated(
1824 venue.as_ref(),
1825 instrument_id.as_ref(),
1826 strategy_id.as_ref(),
1827 account_id.as_ref(),
1828 )
1829 .into_iter()
1830 .collect()
1831 }
1832
1833 #[pyo3(name = "client_order_ids_inflight")]
1835 fn py_client_order_ids_inflight(
1836 &self,
1837 venue: Option<Venue>,
1838 instrument_id: Option<InstrumentId>,
1839 strategy_id: Option<StrategyId>,
1840 account_id: Option<AccountId>,
1841 ) -> Vec<ClientOrderId> {
1842 self.client_order_ids_inflight(
1843 venue.as_ref(),
1844 instrument_id.as_ref(),
1845 strategy_id.as_ref(),
1846 account_id.as_ref(),
1847 )
1848 .into_iter()
1849 .collect()
1850 }
1851
1852 #[pyo3(name = "position_ids")]
1854 fn py_position_ids(
1855 &self,
1856 venue: Option<Venue>,
1857 instrument_id: Option<InstrumentId>,
1858 strategy_id: Option<StrategyId>,
1859 account_id: Option<AccountId>,
1860 ) -> Vec<PositionId> {
1861 self.position_ids(
1862 venue.as_ref(),
1863 instrument_id.as_ref(),
1864 strategy_id.as_ref(),
1865 account_id.as_ref(),
1866 )
1867 .into_iter()
1868 .collect()
1869 }
1870
1871 #[pyo3(name = "position_open_ids")]
1873 fn py_position_open_ids(
1874 &self,
1875 venue: Option<Venue>,
1876 instrument_id: Option<InstrumentId>,
1877 strategy_id: Option<StrategyId>,
1878 account_id: Option<AccountId>,
1879 ) -> Vec<PositionId> {
1880 self.position_open_ids(
1881 venue.as_ref(),
1882 instrument_id.as_ref(),
1883 strategy_id.as_ref(),
1884 account_id.as_ref(),
1885 )
1886 .into_iter()
1887 .collect()
1888 }
1889
1890 #[pyo3(name = "position_closed_ids")]
1892 fn py_position_closed_ids(
1893 &self,
1894 venue: Option<Venue>,
1895 instrument_id: Option<InstrumentId>,
1896 strategy_id: Option<StrategyId>,
1897 account_id: Option<AccountId>,
1898 ) -> Vec<PositionId> {
1899 self.position_closed_ids(
1900 venue.as_ref(),
1901 instrument_id.as_ref(),
1902 strategy_id.as_ref(),
1903 account_id.as_ref(),
1904 )
1905 .into_iter()
1906 .collect()
1907 }
1908
1909 #[pyo3(name = "actor_ids")]
1911 fn py_actor_ids(&self) -> Vec<ComponentId> {
1912 self.actor_ids().into_iter().collect()
1913 }
1914
1915 #[pyo3(name = "strategy_ids")]
1917 fn py_strategy_ids(&self) -> Vec<StrategyId> {
1918 self.strategy_ids().into_iter().collect()
1919 }
1920
1921 #[pyo3(name = "exec_algorithm_ids")]
1923 fn py_exec_algorithm_ids(&self) -> Vec<ExecAlgorithmId> {
1924 self.exec_algorithm_ids().into_iter().collect()
1925 }
1926
1927 #[pyo3(name = "client_order_id")]
1929 fn py_client_order_id(&self, venue_order_id: VenueOrderId) -> Option<ClientOrderId> {
1930 self.client_order_id(&venue_order_id).copied()
1931 }
1932
1933 #[pyo3(name = "venue_order_id")]
1935 fn py_venue_order_id(&self, client_order_id: ClientOrderId) -> Option<VenueOrderId> {
1936 self.venue_order_id(&client_order_id).copied()
1937 }
1938
1939 #[pyo3(name = "client_id")]
1941 fn py_client_id(&self, client_order_id: ClientOrderId) -> Option<ClientId> {
1942 self.client_id(&client_order_id).copied()
1943 }
1944
1945 #[pyo3(name = "orders")]
1947 #[allow(clippy::too_many_arguments)]
1948 fn py_orders(
1949 &self,
1950 py: Python,
1951 venue: Option<Venue>,
1952 instrument_id: Option<InstrumentId>,
1953 strategy_id: Option<StrategyId>,
1954 account_id: Option<AccountId>,
1955 side: Option<OrderSide>,
1956 ) -> PyResult<Vec<Py<PyAny>>> {
1957 self.orders(
1958 venue.as_ref(),
1959 instrument_id.as_ref(),
1960 strategy_id.as_ref(),
1961 account_id.as_ref(),
1962 side,
1963 )
1964 .into_iter()
1965 .map(|o| order_any_to_pyobject(py, o.clone()))
1966 .collect()
1967 }
1968
1969 #[pyo3(name = "orders_open")]
1971 #[allow(clippy::too_many_arguments)]
1972 fn py_orders_open(
1973 &self,
1974 py: Python,
1975 venue: Option<Venue>,
1976 instrument_id: Option<InstrumentId>,
1977 strategy_id: Option<StrategyId>,
1978 account_id: Option<AccountId>,
1979 side: Option<OrderSide>,
1980 ) -> PyResult<Vec<Py<PyAny>>> {
1981 self.orders_open(
1982 venue.as_ref(),
1983 instrument_id.as_ref(),
1984 strategy_id.as_ref(),
1985 account_id.as_ref(),
1986 side,
1987 )
1988 .into_iter()
1989 .map(|o| order_any_to_pyobject(py, o.clone()))
1990 .collect()
1991 }
1992
1993 #[pyo3(name = "orders_closed")]
1995 #[allow(clippy::too_many_arguments)]
1996 fn py_orders_closed(
1997 &self,
1998 py: Python,
1999 venue: Option<Venue>,
2000 instrument_id: Option<InstrumentId>,
2001 strategy_id: Option<StrategyId>,
2002 account_id: Option<AccountId>,
2003 side: Option<OrderSide>,
2004 ) -> PyResult<Vec<Py<PyAny>>> {
2005 self.orders_closed(
2006 venue.as_ref(),
2007 instrument_id.as_ref(),
2008 strategy_id.as_ref(),
2009 account_id.as_ref(),
2010 side,
2011 )
2012 .into_iter()
2013 .map(|o| order_any_to_pyobject(py, o.clone()))
2014 .collect()
2015 }
2016
2017 #[pyo3(name = "orders_emulated")]
2019 #[allow(clippy::too_many_arguments)]
2020 fn py_orders_emulated(
2021 &self,
2022 py: Python,
2023 venue: Option<Venue>,
2024 instrument_id: Option<InstrumentId>,
2025 strategy_id: Option<StrategyId>,
2026 account_id: Option<AccountId>,
2027 side: Option<OrderSide>,
2028 ) -> PyResult<Vec<Py<PyAny>>> {
2029 self.orders_emulated(
2030 venue.as_ref(),
2031 instrument_id.as_ref(),
2032 strategy_id.as_ref(),
2033 account_id.as_ref(),
2034 side,
2035 )
2036 .into_iter()
2037 .map(|o| order_any_to_pyobject(py, o.clone()))
2038 .collect()
2039 }
2040
2041 #[pyo3(name = "orders_inflight")]
2043 #[allow(clippy::too_many_arguments)]
2044 fn py_orders_inflight(
2045 &self,
2046 py: Python,
2047 venue: Option<Venue>,
2048 instrument_id: Option<InstrumentId>,
2049 strategy_id: Option<StrategyId>,
2050 account_id: Option<AccountId>,
2051 side: Option<OrderSide>,
2052 ) -> PyResult<Vec<Py<PyAny>>> {
2053 self.orders_inflight(
2054 venue.as_ref(),
2055 instrument_id.as_ref(),
2056 strategy_id.as_ref(),
2057 account_id.as_ref(),
2058 side,
2059 )
2060 .into_iter()
2061 .map(|o| order_any_to_pyobject(py, o.clone()))
2062 .collect()
2063 }
2064
2065 #[pyo3(name = "orders_for_position")]
2067 fn py_orders_for_position(
2068 &self,
2069 py: Python,
2070 position_id: PositionId,
2071 ) -> PyResult<Vec<Py<PyAny>>> {
2072 self.orders_for_position(&position_id)
2073 .into_iter()
2074 .map(|o| order_any_to_pyobject(py, o.clone()))
2075 .collect()
2076 }
2077
2078 #[pyo3(name = "is_order_emulated")]
2080 fn py_is_order_emulated(&self, client_order_id: ClientOrderId) -> bool {
2081 self.is_order_emulated(&client_order_id)
2082 }
2083
2084 #[pyo3(name = "is_order_inflight")]
2086 fn py_is_order_inflight(&self, client_order_id: ClientOrderId) -> bool {
2087 self.is_order_inflight(&client_order_id)
2088 }
2089
2090 #[pyo3(name = "is_order_pending_cancel_local")]
2092 fn py_is_order_pending_cancel_local(&self, client_order_id: ClientOrderId) -> bool {
2093 self.is_order_pending_cancel_local(&client_order_id)
2094 }
2095
2096 #[pyo3(name = "orders_emulated_count")]
2098 fn py_orders_emulated_count(
2099 &self,
2100 venue: Option<Venue>,
2101 instrument_id: Option<InstrumentId>,
2102 strategy_id: Option<StrategyId>,
2103 account_id: Option<AccountId>,
2104 side: Option<OrderSide>,
2105 ) -> usize {
2106 self.orders_emulated_count(
2107 venue.as_ref(),
2108 instrument_id.as_ref(),
2109 strategy_id.as_ref(),
2110 account_id.as_ref(),
2111 side,
2112 )
2113 }
2114
2115 #[pyo3(name = "orders_inflight_count")]
2117 fn py_orders_inflight_count(
2118 &self,
2119 venue: Option<Venue>,
2120 instrument_id: Option<InstrumentId>,
2121 strategy_id: Option<StrategyId>,
2122 account_id: Option<AccountId>,
2123 side: Option<OrderSide>,
2124 ) -> usize {
2125 self.orders_inflight_count(
2126 venue.as_ref(),
2127 instrument_id.as_ref(),
2128 strategy_id.as_ref(),
2129 account_id.as_ref(),
2130 side,
2131 )
2132 }
2133
2134 #[pyo3(name = "order_list")]
2136 fn py_order_list(&self, order_list_id: OrderListId) -> Option<OrderList> {
2137 self.order_list(&order_list_id).cloned()
2138 }
2139
2140 #[pyo3(name = "order_lists")]
2142 fn py_order_lists(
2143 &self,
2144 venue: Option<Venue>,
2145 instrument_id: Option<InstrumentId>,
2146 strategy_id: Option<StrategyId>,
2147 account_id: Option<AccountId>,
2148 ) -> Vec<OrderList> {
2149 self.order_lists(
2150 venue.as_ref(),
2151 instrument_id.as_ref(),
2152 strategy_id.as_ref(),
2153 account_id.as_ref(),
2154 )
2155 .into_iter()
2156 .cloned()
2157 .collect()
2158 }
2159
2160 #[pyo3(name = "order_list_exists")]
2162 fn py_order_list_exists(&self, order_list_id: OrderListId) -> bool {
2163 self.order_list_exists(&order_list_id)
2164 }
2165
2166 #[pyo3(name = "orders_for_exec_algorithm")]
2169 #[allow(clippy::too_many_arguments)]
2170 fn py_orders_for_exec_algorithm(
2171 &self,
2172 py: Python,
2173 exec_algorithm_id: ExecAlgorithmId,
2174 venue: Option<Venue>,
2175 instrument_id: Option<InstrumentId>,
2176 strategy_id: Option<StrategyId>,
2177 account_id: Option<AccountId>,
2178 side: Option<OrderSide>,
2179 ) -> PyResult<Vec<Py<PyAny>>> {
2180 self.orders_for_exec_algorithm(
2181 &exec_algorithm_id,
2182 venue.as_ref(),
2183 instrument_id.as_ref(),
2184 strategy_id.as_ref(),
2185 account_id.as_ref(),
2186 side,
2187 )
2188 .into_iter()
2189 .map(|o| order_any_to_pyobject(py, o.clone()))
2190 .collect()
2191 }
2192
2193 #[pyo3(name = "orders_for_exec_spawn")]
2195 fn py_orders_for_exec_spawn(
2196 &self,
2197 py: Python,
2198 exec_spawn_id: ClientOrderId,
2199 ) -> PyResult<Vec<Py<PyAny>>> {
2200 self.orders_for_exec_spawn(&exec_spawn_id)
2201 .into_iter()
2202 .map(|o| order_any_to_pyobject(py, o.clone()))
2203 .collect()
2204 }
2205
2206 #[pyo3(name = "exec_spawn_total_quantity")]
2208 fn py_exec_spawn_total_quantity(
2209 &self,
2210 exec_spawn_id: ClientOrderId,
2211 active_only: bool,
2212 ) -> Option<Quantity> {
2213 self.exec_spawn_total_quantity(&exec_spawn_id, active_only)
2214 }
2215
2216 #[pyo3(name = "exec_spawn_total_filled_qty")]
2218 fn py_exec_spawn_total_filled_qty(
2219 &self,
2220 exec_spawn_id: ClientOrderId,
2221 active_only: bool,
2222 ) -> Option<Quantity> {
2223 self.exec_spawn_total_filled_qty(&exec_spawn_id, active_only)
2224 }
2225
2226 #[pyo3(name = "exec_spawn_total_leaves_qty")]
2228 fn py_exec_spawn_total_leaves_qty(
2229 &self,
2230 exec_spawn_id: ClientOrderId,
2231 active_only: bool,
2232 ) -> Option<Quantity> {
2233 self.exec_spawn_total_leaves_qty(&exec_spawn_id, active_only)
2234 }
2235
2236 #[pyo3(name = "position_for_order")]
2238 fn py_position_for_order(
2239 &self,
2240 py: Python,
2241 client_order_id: ClientOrderId,
2242 ) -> PyResult<Option<Py<PyAny>>> {
2243 match self.position_for_order(&client_order_id) {
2244 Some(position) => Ok(Some(position.clone().into_pyobject(py)?.into())),
2245 None => Ok(None),
2246 }
2247 }
2248
2249 #[pyo3(name = "position_id")]
2251 fn py_position_id(&self, client_order_id: ClientOrderId) -> Option<PositionId> {
2252 self.position_id(&client_order_id).copied()
2253 }
2254
2255 #[pyo3(name = "positions")]
2257 #[allow(clippy::too_many_arguments)]
2258 fn py_positions(
2259 &self,
2260 py: Python,
2261 venue: Option<Venue>,
2262 instrument_id: Option<InstrumentId>,
2263 strategy_id: Option<StrategyId>,
2264 account_id: Option<AccountId>,
2265 side: Option<PositionSide>,
2266 ) -> PyResult<Vec<Py<PyAny>>> {
2267 self.positions(
2268 venue.as_ref(),
2269 instrument_id.as_ref(),
2270 strategy_id.as_ref(),
2271 account_id.as_ref(),
2272 side,
2273 )
2274 .into_iter()
2275 .map(|p| Ok(p.clone().into_pyobject(py)?.into()))
2276 .collect()
2277 }
2278
2279 #[pyo3(name = "positions_open")]
2281 #[allow(clippy::too_many_arguments)]
2282 fn py_positions_open(
2283 &self,
2284 py: Python,
2285 venue: Option<Venue>,
2286 instrument_id: Option<InstrumentId>,
2287 strategy_id: Option<StrategyId>,
2288 account_id: Option<AccountId>,
2289 side: Option<PositionSide>,
2290 ) -> PyResult<Vec<Py<PyAny>>> {
2291 self.positions_open(
2292 venue.as_ref(),
2293 instrument_id.as_ref(),
2294 strategy_id.as_ref(),
2295 account_id.as_ref(),
2296 side,
2297 )
2298 .into_iter()
2299 .map(|p| Ok(p.clone().into_pyobject(py)?.into()))
2300 .collect()
2301 }
2302
2303 #[pyo3(name = "positions_closed")]
2305 #[allow(clippy::too_many_arguments)]
2306 fn py_positions_closed(
2307 &self,
2308 py: Python,
2309 venue: Option<Venue>,
2310 instrument_id: Option<InstrumentId>,
2311 strategy_id: Option<StrategyId>,
2312 account_id: Option<AccountId>,
2313 side: Option<PositionSide>,
2314 ) -> PyResult<Vec<Py<PyAny>>> {
2315 self.positions_closed(
2316 venue.as_ref(),
2317 instrument_id.as_ref(),
2318 strategy_id.as_ref(),
2319 account_id.as_ref(),
2320 side,
2321 )
2322 .into_iter()
2323 .map(|p| Ok(p.clone().into_pyobject(py)?.into()))
2324 .collect()
2325 }
2326
2327 #[pyo3(name = "strategy_id_for_order")]
2329 fn py_strategy_id_for_order(&self, client_order_id: ClientOrderId) -> Option<StrategyId> {
2330 self.strategy_id_for_order(&client_order_id).copied()
2331 }
2332
2333 #[pyo3(name = "strategy_id_for_position")]
2335 fn py_strategy_id_for_position(&self, position_id: PositionId) -> Option<StrategyId> {
2336 self.strategy_id_for_position(&position_id).copied()
2337 }
2338
2339 #[pyo3(name = "position_snapshot_bytes")]
2341 fn py_position_snapshot_bytes(&self, position_id: PositionId) -> Option<Vec<u8>> {
2342 self.position_snapshot_bytes(&position_id)
2343 }
2344
2345 #[pyo3(name = "account")]
2347 fn py_account(&self, py: Python, account_id: AccountId) -> PyResult<Option<Py<PyAny>>> {
2348 match self.account(&account_id) {
2349 Some(account) => Ok(Some(account_any_to_pyobject(py, account.clone())?)),
2350 None => Ok(None),
2351 }
2352 }
2353
2354 #[pyo3(name = "account_for_venue")]
2356 fn py_account_for_venue(&self, py: Python, venue: Venue) -> PyResult<Option<Py<PyAny>>> {
2357 match self.account_for_venue(&venue) {
2358 Some(account) => Ok(Some(account_any_to_pyobject(py, account.clone())?)),
2359 None => Ok(None),
2360 }
2361 }
2362
2363 #[pyo3(name = "account_id")]
2365 fn py_account_id(&self, venue: Venue) -> Option<AccountId> {
2366 self.account_id(&venue).copied()
2367 }
2368
2369 #[pyo3(name = "get")]
2375 fn py_get(&self, key: &str) -> PyResult<Option<Vec<u8>>> {
2376 match self.get(key).map_err(to_pyvalue_err)? {
2377 Some(bytes) => Ok(Some(bytes.to_vec())),
2378 None => Ok(None),
2379 }
2380 }
2381
2382 #[pyo3(name = "add")]
2384 fn py_add_general(&mut self, key: &str, value: Vec<u8>) -> PyResult<()> {
2385 self.add(key, Bytes::from(value)).map_err(to_pyvalue_err)
2386 }
2387
2388 #[pyo3(name = "price")]
2390 fn py_price(&self, instrument_id: InstrumentId, price_type: PriceType) -> Option<Price> {
2391 self.price(&instrument_id, price_type)
2392 }
2393
2394 #[pyo3(name = "get_xrate")]
2396 fn py_get_xrate(
2397 &self,
2398 venue: Venue,
2399 from_currency: Currency,
2400 to_currency: Currency,
2401 price_type: PriceType,
2402 ) -> Option<f64> {
2403 self.get_xrate(venue, from_currency, to_currency, price_type)
2404 }
2405
2406 #[pyo3(name = "get_mark_xrate")]
2408 fn py_get_mark_xrate(&self, from_currency: Currency, to_currency: Currency) -> Option<f64> {
2409 self.get_mark_xrate(from_currency, to_currency)
2410 }
2411
2412 #[pyo3(name = "set_mark_xrate")]
2414 fn py_set_mark_xrate(&mut self, from_currency: Currency, to_currency: Currency, xrate: f64) {
2415 self.set_mark_xrate(from_currency, to_currency, xrate);
2416 }
2417
2418 #[pyo3(name = "clear_mark_xrate")]
2420 fn py_clear_mark_xrate(&mut self, from_currency: Currency, to_currency: Currency) {
2421 self.clear_mark_xrate(from_currency, to_currency);
2422 }
2423
2424 #[pyo3(name = "clear_mark_xrates")]
2426 fn py_clear_mark_xrates(&mut self) {
2427 self.clear_mark_xrates();
2428 }
2429
2430 #[pyo3(name = "calculate_unrealized_pnl")]
2432 #[allow(clippy::needless_pass_by_value)]
2433 fn py_calculate_unrealized_pnl(
2434 &self,
2435 py: Python,
2436 position: Py<PyAny>,
2437 ) -> PyResult<Option<Money>> {
2438 let position = position.extract::<Position>(py)?;
2439 Ok(self.calculate_unrealized_pnl(&position))
2440 }
2441
2442 #[pyo3(name = "own_order_book")]
2444 fn py_own_order_book(&self, instrument_id: InstrumentId) -> Option<OwnOrderBook> {
2445 self.own_order_book(&instrument_id).cloned()
2446 }
2447
2448 #[pyo3(name = "update_own_order_book")]
2456 fn py_update_own_order_book(&mut self, py: Python, order: Py<PyAny>) -> PyResult<()> {
2457 let order_any = pyobject_to_order_any(py, order)?;
2458 self.update_own_order_book(&order_any);
2459 Ok(())
2460 }
2461
2462 #[pyo3(name = "force_remove_from_own_order_book")]
2468 fn py_force_remove_from_own_order_book(&mut self, client_order_id: ClientOrderId) {
2469 self.force_remove_from_own_order_book(&client_order_id);
2470 }
2471
2472 #[pyo3(name = "audit_own_order_books")]
2479 fn py_audit_own_order_books(&mut self) {
2480 self.audit_own_order_books();
2481 }
2482}
2483
2484#[cfg(feature = "defi")]
2485#[pymethods]
2486impl Cache {
2487 #[pyo3(name = "add_pool")]
2493 fn py_add_pool(&mut self, pool: Pool) -> PyResult<()> {
2494 self.add_pool(pool).map_err(to_pyvalue_err)
2495 }
2496
2497 #[pyo3(name = "pool")]
2499 fn py_pool(&self, instrument_id: InstrumentId) -> Option<Pool> {
2500 self.pool(&instrument_id).cloned()
2501 }
2502
2503 #[pyo3(name = "pool_ids")]
2505 fn py_pool_ids(&self, venue: Option<Venue>) -> Vec<InstrumentId> {
2506 self.pool_ids(venue.as_ref())
2507 }
2508
2509 #[pyo3(name = "pools")]
2511 fn py_pools(&self, venue: Option<Venue>) -> Vec<Pool> {
2512 self.pools(venue.as_ref()).into_iter().cloned().collect()
2513 }
2514
2515 #[pyo3(name = "add_pool_profiler")]
2521 fn py_add_pool_profiler(&mut self, pool_profiler: PoolProfiler) -> PyResult<()> {
2522 self.add_pool_profiler(pool_profiler)
2523 .map_err(to_pyvalue_err)
2524 }
2525
2526 #[pyo3(name = "pool_profiler")]
2528 fn py_pool_profiler(&self, instrument_id: InstrumentId) -> Option<PoolProfiler> {
2529 self.pool_profiler(&instrument_id).cloned()
2530 }
2531
2532 #[pyo3(name = "pool_profiler_ids")]
2534 fn py_pool_profiler_ids(&self, venue: Option<Venue>) -> Vec<InstrumentId> {
2535 self.pool_profiler_ids(venue.as_ref())
2536 }
2537
2538 #[pyo3(name = "pool_profilers")]
2540 fn py_pool_profilers(&self, venue: Option<Venue>) -> Vec<PoolProfiler> {
2541 self.pool_profilers(venue.as_ref())
2542 .into_iter()
2543 .cloned()
2544 .collect()
2545 }
2546}