Skip to main content

df_hyperliquid_core/markets/
side.rs

1//! The side of an order, a fill, a trade or a book level: `B` and `A` on the wire, one type
2//! wherever the venue writes it.
3
4use std::fmt;
5
6use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
7
8use crate::utils::dec::Round;
9
10/// `B` a buy or a bid, `A` a sell or an ask. On a trade it is the aggressor's
11/// side, on a fill the account's own, on a resting order the side of the book
12/// it rests on. A bid sorts before an ask.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
14pub enum Side {
15    Buy,
16    Sell,
17}
18
19impl Side {
20    pub const ALL: [Side; 2] = [Side::Buy, Side::Sell];
21
22    /// `B` or `A`, exactly as the venue writes it.
23    #[must_use]
24    pub fn parse(said: &str) -> Option<Side> {
25        match said {
26            "B" => Some(Side::Buy),
27            "A" => Some(Side::Sell),
28            _ => None,
29        }
30    }
31
32    /// `B` or `A`.
33    #[must_use]
34    pub const fn wire(self) -> &'static str {
35        match self {
36            Side::Buy => "B",
37            Side::Sell => "A",
38        }
39    }
40
41    #[must_use]
42    pub const fn is_buy(self) -> bool {
43        matches!(self, Side::Buy)
44    }
45
46    #[must_use]
47    pub const fn other(self) -> Side {
48        match self {
49            Side::Buy => Side::Sell,
50            Side::Sell => Side::Buy,
51        }
52    }
53
54    /// How a price for this side rounds onto the grid, never against the trader: a buy rounds
55    /// down, a sell up.
56    #[must_use]
57    pub const fn price_rounding(self) -> Round {
58        match self {
59            Side::Buy => Round::Down,
60            Side::Sell => Round::Up,
61        }
62    }
63}
64
65impl fmt::Display for Side {
66    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67        f.write_str(self.wire())
68    }
69}
70
71impl Serialize for Side {
72    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
73        serializer.serialize_str(self.wire())
74    }
75}
76
77impl<'de> Deserialize<'de> for Side {
78    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
79        let said = <std::borrow::Cow<'de, str>>::deserialize(deserializer)?;
80        Side::parse(&said).ok_or_else(|| de::Error::custom(format!("`{said}` is not a side; expected B or A")))
81    }
82}
83
84#[cfg(test)]
85#[path = "tests/side.rs"]
86mod tests;