Skip to main content

rustrade_execution/exchange/mock/
account.rs

1use crate::{
2    UnindexedAccountSnapshot,
3    balance::AssetBalance,
4    order::{
5        Order,
6        id::ClientOrderId,
7        state::{ActiveOrderState, Cancelled, InactiveOrderState, Open, OrderState},
8    },
9    trade::Trade,
10};
11use chrono::{DateTime, Utc};
12use derive_more::Constructor;
13use fnv::FnvHashMap;
14use rustrade_instrument::{
15    asset::name::AssetNameExchange, exchange::ExchangeId, instrument::name::InstrumentNameExchange,
16};
17
18#[derive(Debug, Constructor)]
19pub struct AccountState {
20    balances: FnvHashMap<AssetNameExchange, AssetBalance<AssetNameExchange>>,
21    orders_open: FnvHashMap<ClientOrderId, Order<ExchangeId, InstrumentNameExchange, Open>>,
22    orders_cancelled:
23        FnvHashMap<ClientOrderId, Order<ExchangeId, InstrumentNameExchange, Cancelled>>,
24    trades: Vec<Trade<AssetNameExchange, InstrumentNameExchange>>,
25}
26
27impl AccountState {
28    pub fn update_time_exchange(&mut self, time_exchange: DateTime<Utc>) {
29        for balance in self.balances.values_mut() {
30            balance.time_exchange = time_exchange;
31        }
32
33        for order in self.orders_open.values_mut() {
34            order.state.time_exchange = time_exchange;
35        }
36    }
37
38    pub fn balances(&self) -> impl Iterator<Item = &AssetBalance<AssetNameExchange>> + '_ {
39        self.balances.values()
40    }
41
42    pub fn orders_open(
43        &self,
44    ) -> impl Iterator<Item = &Order<ExchangeId, InstrumentNameExchange, Open>> + '_ {
45        self.orders_open.values()
46    }
47
48    pub fn orders_cancelled(
49        &self,
50    ) -> impl Iterator<Item = &Order<ExchangeId, InstrumentNameExchange, Cancelled>> + '_ {
51        self.orders_cancelled.values()
52    }
53
54    pub fn trades(
55        &self,
56        time_since: DateTime<Utc>,
57    ) -> impl Iterator<Item = &Trade<AssetNameExchange, InstrumentNameExchange>> + '_ {
58        self.trades
59            .iter()
60            .filter(move |trade| trade.time_exchange >= time_since)
61    }
62
63    pub fn balance_mut(
64        &mut self,
65        asset: &AssetNameExchange,
66    ) -> Option<&mut AssetBalance<AssetNameExchange>> {
67        self.balances.get_mut(asset)
68    }
69
70    pub fn ack_trade(&mut self, trade: Trade<AssetNameExchange, InstrumentNameExchange>) {
71        self.trades.push(trade);
72    }
73}
74
75impl From<UnindexedAccountSnapshot> for AccountState {
76    fn from(value: UnindexedAccountSnapshot) -> Self {
77        let UnindexedAccountSnapshot {
78            exchange: _,
79            balances,
80            instruments,
81        } = value;
82
83        let balances = balances
84            .into_iter()
85            .map(|asset_balance| (asset_balance.asset.clone(), asset_balance))
86            .collect();
87
88        let (orders_open, orders_cancelled) = instruments.into_iter().fold(
89            (FnvHashMap::default(), FnvHashMap::default()),
90            |(mut orders_open, mut orders_cancelled), snapshot| {
91                for order in snapshot.orders {
92                    match order.state {
93                        OrderState::Active(ActiveOrderState::Open(open)) => {
94                            orders_open.insert(
95                                order.key.cid.clone(),
96                                Order {
97                                    key: order.key,
98                                    side: order.side,
99                                    price: order.price,
100                                    quantity: order.quantity,
101                                    kind: order.kind,
102                                    time_in_force: order.time_in_force,
103                                    state: open,
104                                },
105                            );
106                        }
107                        OrderState::Inactive(InactiveOrderState::Cancelled(cancelled)) => {
108                            orders_cancelled.insert(
109                                order.key.cid.clone(),
110                                Order {
111                                    key: order.key,
112                                    side: order.side,
113                                    price: order.price,
114                                    quantity: order.quantity,
115                                    kind: order.kind,
116                                    time_in_force: order.time_in_force,
117                                    state: cancelled,
118                                },
119                            );
120                        }
121                        _ => {}
122                    }
123                }
124
125                (orders_open, orders_cancelled)
126            },
127        );
128
129        Self {
130            balances,
131            orders_open,
132            orders_cancelled,
133            trades: vec![],
134        }
135    }
136}