cxmr_exchanges/
orders.rs

1//! Crypto-bank exchange orders primitives.
2
3use cxmr_currency::{Currency, CurrencyPair};
4
5use super::Error;
6
7/// Currency order details.
8#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
9pub struct Order {
10    /// Order side, which is an `Ask` or a `Bid`.
11    pub side: OrderSide,
12    /// Price rate is a price of a unit.
13    pub rate: f64,
14    /// Order amount.
15    pub amount: f64,
16}
17
18impl Order {
19    /// Returns true if order side is Bid.
20    pub fn is_bid(&self) -> bool {
21        match self.side {
22            OrderSide::Ask => false,
23            OrderSide::Bid => true,
24        }
25    }
26
27    /// Gets total order value from struct.
28    /// It is calculated if `total` contains `None` value.
29    pub fn total(&self) -> f64 {
30        self.rate * self.amount
31    }
32}
33
34/// Order status.
35#[derive(Serialize, Deserialize, Clone, Debug)]
36pub enum OrderStatus {
37    New,
38    PartiallyFilled,
39    Filled,
40    Canceled,
41    PendingCancel,
42    Rejected,
43    Expired,
44}
45
46impl Default for OrderStatus {
47    fn default() -> Self {
48        OrderStatus::New
49    }
50}
51
52/// Order type.
53#[derive(Serialize, Deserialize, Clone, Debug)]
54pub enum OrderType {
55    Limit,
56    Market,
57    StopLoss,
58    StopLossLimit,
59    TakeProfit,
60    TakeProfitLimit,
61    LimitMaker,
62}
63
64/// Order filling time.
65#[derive(Serialize, Deserialize, Clone, Debug)]
66pub enum OrderTime {
67    GoodTilCancel,
68    ImmediateOrCancel,
69    FillOrKill,
70}
71
72/// Order side can be either `Ask` when we are selling
73/// or a `Bid` when we are trying to buy something.
74#[derive(Serialize, Deserialize, PartialEq, Clone)]
75pub enum OrderSide {
76    /// Ask or a sell.
77    Ask,
78    /// Bid or a buy.
79    Bid,
80}
81
82/// Tries to convert from integer to `OrderSide`.
83/// Ask is `0` and Bid is `1.
84impl std::convert::TryFrom<i64> for OrderSide {
85    type Error = Error;
86
87    fn try_from(k: i64) -> Result<Self, Self::Error> {
88        match k {
89            0 => Ok(OrderSide::Ask),
90            1 => Ok(OrderSide::Bid),
91            _ => Err(Error::InvalidOrderSideId(k)),
92        }
93    }
94}
95
96impl std::fmt::Debug for OrderSide {
97    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
98        // TODOL colored
99        // use colored::*;
100        // match self {
101        //     OrderSide::Ask => write!(f, "{}", "ASK".red()),
102        //     OrderSide::Bid => write!(f, "{}", "BID".green()),
103        // }
104        match self {
105            OrderSide::Ask => write!(f, "{}", "ASK"),
106            OrderSide::Bid => write!(f, "{}", "BID"),
107        }
108    }
109}
110
111/// Market exchange order.
112#[derive(Serialize, Deserialize, Clone, Debug)]
113pub struct ExchangeOrder {
114    pub id: Option<String>,
115    pub pair: CurrencyPair,
116    pub side: OrderSide,
117    pub kind: OrderType,
118    pub amount: u64,
119    pub rate: Option<u64>,
120    pub stop: Option<u64>,
121    pub time: OrderTime,
122}
123
124/// Market order execution report.
125///
126/// Response of order creation.
127#[derive(Serialize, Deserialize, Clone, Debug, Default)]
128pub struct OrderExecution {
129    /// Order status.
130    pub status: OrderStatus,
131    /// Order rate.
132    #[serde(skip_serializing_if = "Option::is_none")]
133    pub rate: Option<u64>,
134    /// Order stop rate.
135    #[serde(skip_serializing_if = "Option::is_none")]
136    pub stop: Option<u64>,
137    /// Cumulative order quantity.
138    #[serde(skip_serializing_if = "Option::is_none")]
139    pub amount: Option<u64>,
140    /// Cumulative executed quantity.
141    #[serde(skip_serializing_if = "Option::is_none")]
142    pub executed: Option<u64>,
143    /// Order fills.
144    #[serde(skip_serializing_if = "Option::is_none")]
145    pub fills: Option<Vec<OrderFill>>,
146    // pub iceberg: Option<u64>,
147}
148
149/// Market order fill data.
150#[derive(Serialize, Deserialize, Clone, Debug)]
151pub struct OrderFill {
152    /// Order rate.
153    pub rate: u64,
154    /// Order amount.
155    pub amount: u64,
156    /// Order fee.
157    #[serde(skip_serializing_if = "Option::is_none")]
158    pub fee: Option<OrderFee>,
159}
160
161/// Order fee structure.
162#[derive(Serialize, Deserialize, Clone, Debug)]
163pub struct OrderFee {
164    pub amount: u64,
165    pub currency: Currency,
166}
167
168impl OrderFee {
169    pub fn new(amount: u64, currency: Currency) -> Self {
170        OrderFee {
171            amount: amount,
172            currency: currency,
173        }
174    }
175}
176
177/// Market order.
178#[derive(Serialize, Deserialize, Clone, Debug)]
179pub struct MarketOrder {
180    pub id: String,
181    pub pair: CurrencyPair,
182    pub side: OrderSide,
183    pub kind: OrderType,
184    pub rate: u64,
185    pub stop: Option<u64>,
186    pub amount: u64,
187    pub time: OrderTime,
188    pub status: OrderStatus,
189    pub executed: Option<u64>,
190    pub created_at: u64,
191    pub updated_at: u64,
192    // pub iceberg: Option<u64>,
193}