trading_types/
symbol.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{Currency, Exchange};
4
5/// Symbol represents usual pair with extra exchange info
6#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub struct Symbol {
8    pub eg: Exchange,
9    pub bs: Currency, // base currency, always uppercased
10    pub qt: Currency, // quote currency, always uppercased
11}
12
13impl Symbol {
14    pub fn new(eg: Exchange, cb: Currency, cq: Currency) -> Self {
15        Self {
16            eg,
17            bs: cb.to_uppercase(),
18            qt: cq.to_uppercase(),
19        }
20    }
21}
22
23impl std::fmt::Display for Symbol {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        write!(f, "{}:{}/{}", self.eg, self.bs, self.qt)
26    }
27}
28
29#[derive(thiserror::Error, Debug)]
30pub enum SymbolError {
31    #[error("bad symbol {0}")]
32    BadSymbol(String),
33}
34
35impl TryFrom<(Exchange, &str)> for Symbol {
36    type Error = SymbolError;
37
38    fn try_from((eg, text): (Exchange, &str)) -> Result<Self, Self::Error> {
39        let parts1 = text.split('/').collect::<Vec<&str>>();
40        if parts1.len() != 2 {
41            return Err(SymbolError::BadSymbol(text.to_string()));
42        }
43        let cb = parts1[0];
44        let cq = parts1[1];
45        Ok(Self::new(eg, cb.to_string(), cq.to_string()))
46    }
47}
48
49impl TryFrom<&str> for Symbol {
50    type Error = SymbolError;
51
52    fn try_from(text: &str) -> Result<Self, Self::Error> {
53        let parts0 = text.split(':').collect::<Vec<&str>>();
54        if parts0.len() != 2 {
55            return Err(SymbolError::BadSymbol(text.to_string()));
56        }
57        Self::try_from((parts0[0].to_string(), parts0[1]))
58    }
59}
60
61impl TryFrom<String> for Symbol {
62    type Error = SymbolError;
63
64    fn try_from(text: String) -> Result<Self, Self::Error> {
65        Self::try_from(text.as_str())
66    }
67}