1use cxmr_balances::points;
4use cxmr_exchanges::{Order, OrderSide, Trade};
5
6use super::{Error, OrderBook};
7
8#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
10pub enum Event {
11 OrderBook(OrderBook),
13
14 Trade(Trade),
16
17 InsertOrder(Order),
19
20 ResetOrder(Order),
22
23 RemoveOrder(Order),
25}
26
27impl Event {
28 pub fn is_order_book(&self) -> bool {
29 match self {
30 &Event::OrderBook(_) => true,
31 _ => false,
32 }
33 }
34}
35
36impl From<EventData> for Event {
37 fn from(row: EventData) -> Event {
38 let side = if row.is_bid {
39 OrderSide::Bid
40 } else {
41 OrderSide::Ask
42 };
43 let order = Order {
44 side: side,
45 rate: row.rate.into(),
46 amount: row.amount.into(),
47 };
48 if row.is_trade {
49 Event::Trade(Trade {
50 id: None,
51 order: order,
52 timestamp: row.ts,
53 })
54 } else {
55 Event::ResetOrder(order)
56 }
57 }
58}
59
60#[derive(Clone, Debug, Default)]
62pub struct EventData {
63 pub ts: u64,
65 pub is_trade: bool,
68 pub is_bid: bool,
71 pub rate: f32,
73 pub amount: f32,
75}
76
77impl EventData {
78 pub fn from_event(event: &Event, ts: u64) -> Result<EventData, Error> {
80 let (rate, amount, is_bid, is_trade) = match event {
81 Event::Trade(trade) => Ok((
82 trade.order.rate,
83 trade.order.amount,
84 trade.order.is_bid(),
85 true,
86 )),
87 Event::RemoveOrder(order) => Ok((order.rate, -order.amount, order.is_bid(), false)),
88 Event::ResetOrder(order) => Ok((order.rate, order.amount, order.is_bid(), false)),
89 Event::InsertOrder(order) => Ok((order.rate, order.amount, order.is_bid(), false)),
90 _ => Err(Error::InvalidEventKind),
91 }?;
92 Ok(EventData {
93 ts: ts,
94 rate: rate as f32,
95 amount: amount as f32,
96 is_bid: is_bid,
97 is_trade: is_trade,
98 })
99 }
100
101 pub fn to_csv(&self) -> String {
103 format!(
104 r#"{},{},{},{},{}"#,
105 self.ts / 1000,
106 if self.is_trade { 1 } else { 0 },
107 if self.is_bid { 1 } else { 0 },
108 points(self.rate as f64),
109 points(self.amount as f64)
110 )
111 }
112
113 pub fn to_trade_csv(&self) -> String {
116 format!(
117 r#"{},{},{},{}"#,
118 self.ts / 1000,
119 if self.is_bid { 1 } else { 0 },
120 points(self.rate as f64),
121 points(self.amount as f64)
122 )
123 }
124}
125
126impl PartialEq for EventData {
127 fn eq(&self, other: &EventData) -> bool {
128 self.ts == other.ts
129 }
130}
131
132impl From<&Event> for Vec<EventData> {
133 fn from(ev: &Event) -> Vec<EventData> {
134 match ev {
135 Event::OrderBook(book) => {
136 let mut res = Vec::with_capacity(book.asks.len() + book.bids.len());
137 for order in &book.asks {
138 res.push(EventData {
139 ts: 0,
140 is_bid: false,
141 is_trade: false,
142 rate: order.rate as f32,
143 amount: order.amount as f32,
144 })
145 }
146 for order in &book.bids {
147 res.push(EventData {
148 ts: 0,
149 is_bid: true,
150 is_trade: false,
151 rate: order.rate as f32,
152 amount: order.amount as f32,
153 })
154 }
155 res
156 }
157 _ => vec![EventData::from_event(ev, 0).unwrap()],
158 }
159 }
160}