rustrade_execution/exchange/mock/
account.rs1use 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}