Skip to main content

rithmic_rs/
types.rs

1//! Order enums with serde support and protobuf conversions.
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6use std::fmt;
7use std::str::FromStr;
8
9use crate::rti::{
10    request_bracket_order, request_modify_order, request_new_order, request_oco_order,
11};
12
13/// Buy or sell.
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
15#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
16pub enum OrderSide {
17    #[default]
18    Buy,
19    Sell,
20}
21
22impl fmt::Display for OrderSide {
23    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24        match self {
25            Self::Buy => write!(f, "BUY"),
26            Self::Sell => write!(f, "SELL"),
27        }
28    }
29}
30
31#[derive(Debug, Clone, PartialEq, Eq)]
32pub struct ParseOrderSideError(String);
33
34impl fmt::Display for ParseOrderSideError {
35    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36        write!(f, "invalid order side: '{}'", self.0)
37    }
38}
39
40impl std::error::Error for ParseOrderSideError {}
41
42impl FromStr for OrderSide {
43    type Err = ParseOrderSideError;
44
45    fn from_str(s: &str) -> Result<Self, Self::Err> {
46        match s.to_uppercase().as_str() {
47            "BUY" | "B" => Ok(Self::Buy),
48            "SELL" | "S" => Ok(Self::Sell),
49            _ => Err(ParseOrderSideError(s.to_string())),
50        }
51    }
52}
53
54impl From<OrderSide> for request_new_order::TransactionType {
55    fn from(side: OrderSide) -> Self {
56        match side {
57            OrderSide::Buy => Self::Buy,
58            OrderSide::Sell => Self::Sell,
59        }
60    }
61}
62
63impl From<OrderSide> for request_bracket_order::TransactionType {
64    fn from(side: OrderSide) -> Self {
65        match side {
66            OrderSide::Buy => Self::Buy,
67            OrderSide::Sell => Self::Sell,
68        }
69    }
70}
71
72impl From<OrderSide> for request_oco_order::TransactionType {
73    fn from(side: OrderSide) -> Self {
74        match side {
75            OrderSide::Buy => Self::Buy,
76            OrderSide::Sell => Self::Sell,
77        }
78    }
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
82#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
83pub enum OrderType {
84    Market,
85    #[default]
86    Limit,
87    StopMarket,
88    StopLimit,
89}
90
91impl fmt::Display for OrderType {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93        match self {
94            Self::Market => write!(f, "MARKET"),
95            Self::Limit => write!(f, "LIMIT"),
96            Self::StopMarket => write!(f, "STOP_MARKET"),
97            Self::StopLimit => write!(f, "STOP_LIMIT"),
98        }
99    }
100}
101
102#[derive(Debug, Clone, PartialEq, Eq)]
103pub struct ParseOrderTypeError(String);
104
105impl fmt::Display for ParseOrderTypeError {
106    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107        write!(f, "invalid order type: '{}'", self.0)
108    }
109}
110
111impl std::error::Error for ParseOrderTypeError {}
112
113impl FromStr for OrderType {
114    type Err = ParseOrderTypeError;
115
116    fn from_str(s: &str) -> Result<Self, Self::Err> {
117        match s.to_uppercase().as_str() {
118            "MARKET" | "MKT" => Ok(Self::Market),
119            "LIMIT" | "LMT" => Ok(Self::Limit),
120            "STOPMARKET" | "STPMKT" | "STOP_MARKET" | "STOP-MARKET" => Ok(Self::StopMarket),
121            "STOPLIMIT" | "STPLMT" | "STOP_LIMIT" | "STOP-LIMIT" => Ok(Self::StopLimit),
122            _ => Err(ParseOrderTypeError(s.to_string())),
123        }
124    }
125}
126
127impl From<OrderType> for request_new_order::PriceType {
128    fn from(order_type: OrderType) -> Self {
129        match order_type {
130            OrderType::Market => Self::Market,
131            OrderType::Limit => Self::Limit,
132            OrderType::StopMarket => Self::StopMarket,
133            OrderType::StopLimit => Self::StopLimit,
134        }
135    }
136}
137
138impl From<OrderType> for request_modify_order::PriceType {
139    fn from(order_type: OrderType) -> Self {
140        match order_type {
141            OrderType::Market => Self::Market,
142            OrderType::Limit => Self::Limit,
143            OrderType::StopMarket => Self::StopMarket,
144            OrderType::StopLimit => Self::StopLimit,
145        }
146    }
147}
148
149impl From<OrderType> for request_bracket_order::PriceType {
150    fn from(order_type: OrderType) -> Self {
151        match order_type {
152            OrderType::Market => Self::Market,
153            OrderType::Limit => Self::Limit,
154            OrderType::StopMarket => Self::StopMarket,
155            OrderType::StopLimit => Self::StopLimit,
156        }
157    }
158}
159
160impl From<OrderType> for request_oco_order::PriceType {
161    fn from(order_type: OrderType) -> Self {
162        match order_type {
163            OrderType::Market => Self::Market,
164            OrderType::Limit => Self::Limit,
165            OrderType::StopMarket => Self::StopMarket,
166            OrderType::StopLimit => Self::StopLimit,
167        }
168    }
169}
170
171#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
172#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
173pub enum TimeInForce {
174    #[default]
175    Day,
176    Gtc,
177    Ioc,
178    Fok,
179}
180
181impl fmt::Display for TimeInForce {
182    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183        match self {
184            Self::Day => write!(f, "DAY"),
185            Self::Gtc => write!(f, "GTC"),
186            Self::Ioc => write!(f, "IOC"),
187            Self::Fok => write!(f, "FOK"),
188        }
189    }
190}
191
192#[derive(Debug, Clone, PartialEq, Eq)]
193pub struct ParseTimeInForceError(String);
194
195impl fmt::Display for ParseTimeInForceError {
196    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197        write!(f, "invalid time-in-force: '{}'", self.0)
198    }
199}
200
201impl std::error::Error for ParseTimeInForceError {}
202
203impl FromStr for TimeInForce {
204    type Err = ParseTimeInForceError;
205
206    fn from_str(s: &str) -> Result<Self, Self::Err> {
207        match s.to_uppercase().as_str() {
208            "DAY" => Ok(Self::Day),
209            "GTC" | "GOODTILLCANCELLED" | "GOOD_TILL_CANCELLED" | "GOOD-TILL-CANCELLED" => {
210                Ok(Self::Gtc)
211            }
212            "IOC" | "IMMEDIATEORCANCEL" | "IMMEDIATE_OR_CANCEL" | "IMMEDIATE-OR-CANCEL" => {
213                Ok(Self::Ioc)
214            }
215            "FOK" | "FILLORKILL" | "FILL_OR_KILL" | "FILL-OR-KILL" => Ok(Self::Fok),
216            _ => Err(ParseTimeInForceError(s.to_string())),
217        }
218    }
219}
220
221impl From<TimeInForce> for request_new_order::Duration {
222    fn from(tif: TimeInForce) -> Self {
223        match tif {
224            TimeInForce::Day => Self::Day,
225            TimeInForce::Gtc => Self::Gtc,
226            TimeInForce::Ioc => Self::Ioc,
227            TimeInForce::Fok => Self::Fok,
228        }
229    }
230}
231
232impl From<TimeInForce> for request_bracket_order::Duration {
233    fn from(tif: TimeInForce) -> Self {
234        match tif {
235            TimeInForce::Day => Self::Day,
236            TimeInForce::Gtc => Self::Gtc,
237            TimeInForce::Ioc => Self::Ioc,
238            TimeInForce::Fok => Self::Fok,
239        }
240    }
241}
242
243impl From<TimeInForce> for request_oco_order::Duration {
244    fn from(tif: TimeInForce) -> Self {
245        match tif {
246            TimeInForce::Day => Self::Day,
247            TimeInForce::Gtc => Self::Gtc,
248            TimeInForce::Ioc => Self::Ioc,
249            TimeInForce::Fok => Self::Fok,
250        }
251    }
252}