rustrade_data/subscription/
quote.rs1use super::SubscriptionKind;
2use rust_decimal::Decimal;
3use rustrade_macro::{DeSubKind, SerSubKind};
4use serde::{Deserialize, Serialize};
5
6const BPS_FACTOR: Decimal = Decimal::from_parts(10_000, 0, 0, false, 0);
8
9#[derive(
14 Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default, DeSubKind, SerSubKind,
15)]
16pub struct Quotes;
17
18impl SubscriptionKind for Quotes {
19 type Event = Quote;
20
21 fn as_str(&self) -> &'static str {
22 "quotes"
23 }
24}
25
26impl std::fmt::Display for Quotes {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 write!(f, "{}", self.as_str())
29 }
30}
31
32#[derive(Copy, Clone, PartialEq, PartialOrd, Debug, Deserialize, Serialize)]
34pub struct Quote {
35 pub bid_price: Decimal,
36 pub bid_amount: Decimal,
37 pub ask_price: Decimal,
38 pub ask_amount: Decimal,
39}
40
41impl Quote {
42 pub fn mid_price(&self) -> Decimal {
44 (self.bid_price + self.ask_price) / Decimal::TWO
45 }
46
47 pub fn spread(&self) -> Decimal {
49 self.ask_price - self.bid_price
50 }
51
52 pub fn spread_bps(&self) -> Decimal {
55 let mid = self.mid_price();
56 if mid.is_zero() {
57 Decimal::ZERO
58 } else {
59 (self.spread() / mid) * BPS_FACTOR
60 }
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67 use rust_decimal_macros::dec;
68
69 #[test]
70 fn test_quote_mid_price() {
71 let quote = Quote {
72 bid_price: dec!(100),
73 bid_amount: dec!(10),
74 ask_price: dec!(102),
75 ask_amount: dec!(5),
76 };
77 assert_eq!(quote.mid_price(), dec!(101));
78 }
79
80 #[test]
81 fn test_quote_spread() {
82 let quote = Quote {
83 bid_price: dec!(100),
84 bid_amount: dec!(10),
85 ask_price: dec!(102),
86 ask_amount: dec!(5),
87 };
88 assert_eq!(quote.spread(), dec!(2));
89 }
90
91 #[test]
92 fn test_quote_spread_bps() {
93 let quote = Quote {
94 bid_price: dec!(100),
95 bid_amount: dec!(10),
96 ask_price: dec!(101),
97 ask_amount: dec!(5),
98 };
99 let bps = quote.spread_bps();
101 assert!(bps > dec!(99) && bps < dec!(100), "spread_bps={bps}");
102 }
103}