nautilus_model/accounts/
any.rs1use std::collections::HashMap;
17
18use serde::{Deserialize, Serialize};
19
20use crate::{
21 accounts::{base::Account, cash::CashAccount, margin::MarginAccount},
22 enums::{AccountType, LiquiditySide},
23 events::{AccountState, OrderFilled},
24 identifiers::AccountId,
25 instruments::InstrumentAny,
26 position::Position,
27 types::{AccountBalance, Currency, Money, Price, Quantity},
28};
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub enum AccountAny {
31 Margin(MarginAccount),
32 Cash(CashAccount),
33}
34
35impl AccountAny {
36 #[must_use]
37 pub fn id(&self) -> AccountId {
38 match self {
39 AccountAny::Margin(margin) => margin.id,
40 AccountAny::Cash(cash) => cash.id,
41 }
42 }
43
44 pub fn last_event(&self) -> Option<AccountState> {
45 match self {
46 AccountAny::Margin(margin) => margin.last_event(),
47 AccountAny::Cash(cash) => cash.last_event(),
48 }
49 }
50
51 pub fn events(&self) -> Vec<AccountState> {
52 match self {
53 AccountAny::Margin(margin) => margin.events(),
54 AccountAny::Cash(cash) => cash.events(),
55 }
56 }
57
58 pub fn apply(&mut self, event: AccountState) {
59 match self {
60 AccountAny::Margin(margin) => margin.apply(event),
61 AccountAny::Cash(cash) => cash.apply(event),
62 }
63 }
64
65 pub fn balances(&self) -> HashMap<Currency, AccountBalance> {
66 match self {
67 AccountAny::Margin(margin) => margin.balances(),
68 AccountAny::Cash(cash) => cash.balances(),
69 }
70 }
71
72 pub fn balances_locked(&self) -> HashMap<Currency, Money> {
73 match self {
74 AccountAny::Margin(margin) => margin.balances_locked(),
75 AccountAny::Cash(cash) => cash.balances_locked(),
76 }
77 }
78
79 pub fn base_currency(&self) -> Option<Currency> {
80 match self {
81 AccountAny::Margin(margin) => margin.base_currency(),
82 AccountAny::Cash(cash) => cash.base_currency(),
83 }
84 }
85
86 pub fn from_events(events: Vec<AccountState>) -> anyhow::Result<Self> {
87 if events.is_empty() {
88 anyhow::bail!("No order events provided to create `AccountAny`");
89 }
90
91 let init_event = events.first().unwrap();
92 let mut account = Self::from(init_event.clone());
93 for event in events.iter().skip(1) {
94 account.apply(event.clone());
95 }
96 Ok(account)
97 }
98
99 pub fn calculate_pnls(
100 &self,
101 instrument: InstrumentAny,
102 fill: OrderFilled,
103 position: Option<Position>,
104 ) -> anyhow::Result<Vec<Money>> {
105 match self {
106 AccountAny::Margin(margin) => margin.calculate_pnls(instrument, fill, position),
107 AccountAny::Cash(cash) => cash.calculate_pnls(instrument, fill, position),
108 }
109 }
110
111 pub fn calculate_commission(
112 &self,
113 instrument: InstrumentAny,
114 last_qty: Quantity,
115 last_px: Price,
116 liquidity_side: LiquiditySide,
117 use_quote_for_inverse: Option<bool>,
118 ) -> anyhow::Result<Money> {
119 match self {
120 AccountAny::Margin(margin) => margin.calculate_commission(
121 instrument,
122 last_qty,
123 last_px,
124 liquidity_side,
125 use_quote_for_inverse,
126 ),
127 AccountAny::Cash(cash) => cash.calculate_commission(
128 instrument,
129 last_qty,
130 last_px,
131 liquidity_side,
132 use_quote_for_inverse,
133 ),
134 }
135 }
136
137 pub fn balance(&self, currency: Option<Currency>) -> Option<&AccountBalance> {
138 match self {
139 AccountAny::Margin(margin) => margin.balance(currency),
140 AccountAny::Cash(cash) => cash.balance(currency),
141 }
142 }
143}
144
145impl From<AccountState> for AccountAny {
146 fn from(event: AccountState) -> Self {
147 match event.account_type {
148 AccountType::Margin => AccountAny::Margin(MarginAccount::new(event, false)),
149 AccountType::Cash => AccountAny::Cash(CashAccount::new(event, false)),
150 AccountType::Betting => todo!("Betting account not implemented"),
151 }
152 }
153}
154
155impl PartialEq for AccountAny {
156 fn eq(&self, other: &Self) -> bool {
157 self.id() == other.id()
158 }
159}