use std::{
cell::RefCell,
rc::Rc,
sync::atomic::{AtomicBool, Ordering},
};
use nautilus_common::cache::Cache;
use nautilus_model::{
enums::{AccountType, OmsType},
identifiers::{AccountId, ClientId, ClientOrderId, TraderId, Venue},
orders::{OrderAny, OrderList},
types::Currency,
};
#[derive(Debug)]
pub struct ExecutionClientCore {
pub trader_id: TraderId,
pub client_id: ClientId,
pub venue: Venue,
pub oms_type: OmsType,
pub account_id: AccountId,
pub account_type: AccountType,
pub base_currency: Option<Currency>,
connected: AtomicBool,
started: AtomicBool,
instruments_initialized: AtomicBool,
cache: Rc<RefCell<Cache>>,
}
impl Clone for ExecutionClientCore {
fn clone(&self) -> Self {
Self {
trader_id: self.trader_id,
client_id: self.client_id,
venue: self.venue,
oms_type: self.oms_type,
account_id: self.account_id,
account_type: self.account_type,
base_currency: self.base_currency,
connected: AtomicBool::new(self.connected.load(Ordering::Acquire)),
started: AtomicBool::new(self.started.load(Ordering::Acquire)),
instruments_initialized: AtomicBool::new(
self.instruments_initialized.load(Ordering::Acquire),
),
cache: self.cache.clone(),
}
}
}
impl ExecutionClientCore {
#[expect(clippy::too_many_arguments)]
#[must_use]
pub fn new(
trader_id: TraderId,
client_id: ClientId,
venue: Venue,
oms_type: OmsType,
account_id: AccountId,
account_type: AccountType,
base_currency: Option<Currency>,
cache: Rc<RefCell<Cache>>,
) -> Self {
Self {
trader_id,
client_id,
venue,
oms_type,
account_id,
account_type,
base_currency,
connected: AtomicBool::new(false),
started: AtomicBool::new(false),
instruments_initialized: AtomicBool::new(false),
cache,
}
}
pub fn cache(&self) -> std::cell::Ref<'_, Cache> {
self.cache.borrow()
}
pub fn cache_mut(&self) -> std::cell::RefMut<'_, Cache> {
self.cache.borrow_mut()
}
pub fn get_order(&self, client_order_id: &ClientOrderId) -> anyhow::Result<OrderAny> {
self.cache
.borrow()
.order(client_order_id)
.cloned()
.ok_or_else(|| anyhow::anyhow!("Order not found in cache: {client_order_id}"))
}
pub fn get_orders_for_list(&self, order_list: &OrderList) -> anyhow::Result<Vec<OrderAny>> {
order_list
.client_order_ids
.iter()
.map(|id| self.get_order(id))
.collect()
}
#[must_use]
pub fn is_connected(&self) -> bool {
self.connected.load(Ordering::Acquire)
}
#[must_use]
pub fn is_disconnected(&self) -> bool {
!self.is_connected()
}
pub fn set_connected(&self) {
self.connected.store(true, Ordering::Release);
}
pub fn set_disconnected(&self) {
self.connected.store(false, Ordering::Release);
}
#[must_use]
pub fn is_started(&self) -> bool {
self.started.load(Ordering::Acquire)
}
#[must_use]
pub fn is_stopped(&self) -> bool {
!self.is_started()
}
pub fn set_started(&self) {
self.started.store(true, Ordering::Release);
}
pub fn set_stopped(&self) {
self.started.store(false, Ordering::Release);
}
#[must_use]
pub fn instruments_initialized(&self) -> bool {
self.instruments_initialized.load(Ordering::Acquire)
}
pub fn set_instruments_initialized(&self) {
self.instruments_initialized.store(true, Ordering::Release);
}
pub const fn set_account_id(&mut self, account_id: AccountId) {
self.account_id = account_id;
}
}