1use serde::{Deserialize, Serialize};
4use smartstring::alias::String as SmartString;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8#[repr(u8)]
9pub enum OrderSide {
10 Buy = 0,
12 Sell = 1,
14}
15
16impl OrderSide {
17 #[must_use]
19 pub const fn opposite(self) -> Self {
20 match self {
21 Self::Buy => Self::Sell,
22 Self::Sell => Self::Buy,
23 }
24 }
25}
26
27impl std::fmt::Display for OrderSide {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 match self {
30 Self::Buy => write!(f, "Buy"),
31 Self::Sell => write!(f, "Sell"),
32 }
33 }
34}
35
36impl Serialize for OrderSide {
37 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
38 where
39 S: serde::Serializer,
40 {
41 serializer.serialize_u8(*self as u8)
42 }
43}
44
45impl<'de> Deserialize<'de> for OrderSide {
46 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
47 where
48 D: serde::Deserializer<'de>,
49 {
50 match u8::deserialize(deserializer)? {
51 0 => Ok(Self::Buy),
52 1 => Ok(Self::Sell),
53 _ => Err(serde::de::Error::custom("invalid OrderSide")),
54 }
55 }
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
60#[repr(u8)]
61pub enum OrderType {
62 Market = 0,
64 Limit = 1,
66 Stop = 2,
68 StopLimit = 3,
70 FillOrKill = 4,
72 ImmediateOrCancel = 5,
74 PostOnly = 6,
76}
77
78impl std::fmt::Display for OrderType {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 match self {
81 Self::Market => write!(f, "Market"),
82 Self::Limit => write!(f, "Limit"),
83 Self::Stop => write!(f, "Stop"),
84 Self::StopLimit => write!(f, "StopLimit"),
85 Self::FillOrKill => write!(f, "FillOrKill"),
86 Self::ImmediateOrCancel => write!(f, "ImmediateOrCancel"),
87 Self::PostOnly => write!(f, "PostOnly"),
88 }
89 }
90}
91
92impl Serialize for OrderType {
93 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
94 where
95 S: serde::Serializer,
96 {
97 serializer.serialize_u8(*self as u8)
98 }
99}
100
101impl<'de> Deserialize<'de> for OrderType {
102 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
103 where
104 D: serde::Deserializer<'de>,
105 {
106 match u8::deserialize(deserializer)? {
107 0 => Ok(Self::Market),
108 1 => Ok(Self::Limit),
109 2 => Ok(Self::Stop),
110 3 => Ok(Self::StopLimit),
111 4 => Ok(Self::FillOrKill),
112 5 => Ok(Self::ImmediateOrCancel),
113 6 => Ok(Self::PostOnly),
114 _ => Err(serde::de::Error::custom("invalid OrderType")),
115 }
116 }
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
121#[repr(u8)]
122pub enum TimeInForce {
123 GTC = 0,
125 IOC = 1,
127 FOK = 2,
129 GTD = 3,
131 GTX = 4,
133}
134
135impl std::fmt::Display for TimeInForce {
136 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137 match self {
138 Self::GTC => write!(f, "GTC"),
139 Self::IOC => write!(f, "IOC"),
140 Self::FOK => write!(f, "FOK"),
141 Self::GTD => write!(f, "GTD"),
142 Self::GTX => write!(f, "GTX"),
143 }
144 }
145}
146
147impl Serialize for TimeInForce {
148 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
149 where
150 S: serde::Serializer,
151 {
152 serializer.serialize_u8(*self as u8)
153 }
154}
155
156impl<'de> Deserialize<'de> for TimeInForce {
157 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
158 where
159 D: serde::Deserializer<'de>,
160 {
161 match u8::deserialize(deserializer)? {
162 0 => Ok(Self::GTC),
163 1 => Ok(Self::IOC),
164 2 => Ok(Self::FOK),
165 3 => Ok(Self::GTD),
166 4 => Ok(Self::GTX),
167 _ => Err(serde::de::Error::custom("invalid TimeInForce")),
168 }
169 }
170}
171
172#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
174#[repr(u8)]
175pub enum OrderStatus {
176 New = 0,
178 Open = 1,
180 PartiallyFilled = 2,
182 Filled = 3,
184 Cancelled = 4,
186 Rejected = 5,
188 Expired = 6,
190 Pending = 7,
192 PendingCancel = 8,
194 Unknown = 9,
196}
197
198impl std::fmt::Display for OrderStatus {
199 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200 match self {
201 Self::New => write!(f, "New"),
202 Self::Open => write!(f, "Open"),
203 Self::PartiallyFilled => write!(f, "PartiallyFilled"),
204 Self::Filled => write!(f, "Filled"),
205 Self::Cancelled => write!(f, "Cancelled"),
206 Self::Rejected => write!(f, "Rejected"),
207 Self::Expired => write!(f, "Expired"),
208 Self::Pending => write!(f, "Pending"),
209 Self::PendingCancel => write!(f, "PendingCancel"),
210 Self::Unknown => write!(f, "Unknown"),
211 }
212 }
213}
214
215impl Serialize for OrderStatus {
216 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
217 where
218 S: serde::Serializer,
219 {
220 serializer.serialize_u8(*self as u8)
221 }
222}
223
224impl<'de> Deserialize<'de> for OrderStatus {
225 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
226 where
227 D: serde::Deserializer<'de>,
228 {
229 match u8::deserialize(deserializer)? {
230 0 => Ok(Self::New),
231 1 => Ok(Self::Open),
232 2 => Ok(Self::PartiallyFilled),
233 3 => Ok(Self::Filled),
234 4 => Ok(Self::Cancelled),
235 5 => Ok(Self::Rejected),
236 6 => Ok(Self::Expired),
237 7 => Ok(Self::Pending),
238 8 => Ok(Self::PendingCancel),
239 9 => Ok(Self::Unknown),
240 _ => Err(serde::de::Error::custom("invalid OrderStatus")),
241 }
242 }
243}
244
245#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
247#[repr(u8)]
248pub enum InstrumentType {
249 Spot = 1,
251 Future = 2,
253 Option = 3,
255 Perpetual = 4,
257}
258
259impl std::fmt::Display for InstrumentType {
260 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
261 match self {
262 Self::Spot => write!(f, "Spot"),
263 Self::Future => write!(f, "Future"),
264 Self::Option => write!(f, "Option"),
265 Self::Perpetual => write!(f, "Perpetual"),
266 }
267 }
268}
269
270impl Serialize for InstrumentType {
271 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
272 where
273 S: serde::Serializer,
274 {
275 serializer.serialize_u8(*self as u8)
276 }
277}
278
279impl<'de> Deserialize<'de> for InstrumentType {
280 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
281 where
282 D: serde::Deserializer<'de>,
283 {
284 match u8::deserialize(deserializer)? {
285 1 => Ok(Self::Spot),
286 2 => Ok(Self::Future),
287 3 => Ok(Self::Option),
288 4 => Ok(Self::Perpetual),
289 _ => Err(serde::de::Error::custom("invalid InstrumentType")),
290 }
291 }
292}
293
294#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
296#[repr(u8)]
297pub enum AssetType {
298 Cryptocurrency = 1,
300 Fiat = 2,
302 Stablecoin = 3,
304}
305
306impl std::fmt::Display for AssetType {
307 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
308 match self {
309 Self::Cryptocurrency => write!(f, "Cryptocurrency"),
310 Self::Fiat => write!(f, "Fiat"),
311 Self::Stablecoin => write!(f, "Stablecoin"),
312 }
313 }
314}
315
316impl Serialize for AssetType {
317 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
318 where
319 S: serde::Serializer,
320 {
321 serializer.serialize_u8(*self as u8)
322 }
323}
324
325impl<'de> Deserialize<'de> for AssetType {
326 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
327 where
328 D: serde::Deserializer<'de>,
329 {
330 match u8::deserialize(deserializer)? {
331 1 => Ok(Self::Cryptocurrency),
332 2 => Ok(Self::Fiat),
333 3 => Ok(Self::Stablecoin),
334 _ => Err(serde::de::Error::custom("invalid AssetType")),
335 }
336 }
337}
338
339#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
341#[repr(u8)]
342pub enum PriceType {
343 Bid = 1,
345 Ask = 2,
347 Mid = 3,
349 Last = 4,
351 Mark = 5,
353 Index = 6,
355}
356
357impl std::fmt::Display for PriceType {
358 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
359 match self {
360 Self::Bid => write!(f, "Bid"),
361 Self::Ask => write!(f, "Ask"),
362 Self::Mid => write!(f, "Mid"),
363 Self::Last => write!(f, "Last"),
364 Self::Mark => write!(f, "Mark"),
365 Self::Index => write!(f, "Index"),
366 }
367 }
368}
369
370impl Serialize for PriceType {
371 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
372 where
373 S: serde::Serializer,
374 {
375 serializer.serialize_u8(*self as u8)
376 }
377}
378
379impl<'de> Deserialize<'de> for PriceType {
380 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
381 where
382 D: serde::Deserializer<'de>,
383 {
384 match u8::deserialize(deserializer)? {
385 1 => Ok(Self::Bid),
386 2 => Ok(Self::Ask),
387 3 => Ok(Self::Mid),
388 4 => Ok(Self::Last),
389 5 => Ok(Self::Mark),
390 6 => Ok(Self::Index),
391 _ => Err(serde::de::Error::custom("invalid PriceType")),
392 }
393 }
394}
395
396#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
398pub enum Exchange {
399 Binance,
401 Coinbase,
403 Bybit,
405 Upbit,
407 Bithumb,
409 Virtual,
411}
412
413impl std::fmt::Display for Exchange {
414 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
415 match self {
416 Self::Binance => write!(f, "Binance"),
417 Self::Coinbase => write!(f, "Coinbase"),
418 Self::Bybit => write!(f, "Bybit"),
419 Self::Upbit => write!(f, "Upbit"),
420 Self::Bithumb => write!(f, "Bithumb"),
421 Self::Virtual => write!(f, "Virtual"),
422 }
423 }
424}
425
426impl Serialize for Exchange {
427 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
428 where
429 S: serde::Serializer,
430 {
431 let s = match self {
432 Self::Binance => "binance",
433 Self::Coinbase => "coinbase",
434 Self::Bybit => "bybit",
435 Self::Upbit => "upbit",
436 Self::Bithumb => "bithumb",
437 Self::Virtual => "virtual",
438 };
439 serializer.serialize_str(s)
440 }
441}
442
443impl<'de> Deserialize<'de> for Exchange {
444 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
445 where
446 D: serde::Deserializer<'de>,
447 {
448 let s = SmartString::deserialize(deserializer)?;
449 match s.to_lowercase().as_str() {
450 "binance" => Ok(Self::Binance),
451 "coinbase" => Ok(Self::Coinbase),
452 "bybit" => Ok(Self::Bybit),
453 "upbit" => Ok(Self::Upbit),
454 "bithumb" => Ok(Self::Bithumb),
455 "virtual" => Ok(Self::Virtual),
456 _ => Err(serde::de::Error::custom(format!("unknown exchange: {s}"))),
457 }
458 }
459}
460
461#[cfg(test)]
462mod tests {
463 use super::*;
464 use rusty_common::json;
465
466 #[test]
467 fn test_order_side() {
468 assert_eq!(format!("{}", OrderSide::Buy), "Buy");
469 assert_eq!(format!("{}", OrderSide::Sell), "Sell");
470 assert_eq!(OrderSide::Buy.opposite(), OrderSide::Sell);
471 assert_eq!(OrderSide::Sell.opposite(), OrderSide::Buy);
472
473 assert_eq!(json::to_smartstring(&OrderSide::Buy).unwrap(), "0");
475 assert_eq!(json::to_smartstring(&OrderSide::Sell).unwrap(), "1");
476
477 assert_eq!(json::parse::<OrderSide>("0").unwrap(), OrderSide::Buy);
479 assert_eq!(json::parse::<OrderSide>("1").unwrap(), OrderSide::Sell);
480 }
481
482 #[test]
483 fn test_order_side_opposite_const_context() {
484 const BUY_SIDE: OrderSide = OrderSide::Buy;
486 const SELL_SIDE: OrderSide = OrderSide::Sell;
487 const BUY_OPPOSITE: OrderSide = BUY_SIDE.opposite();
488 const SELL_OPPOSITE: OrderSide = SELL_SIDE.opposite();
489
490 assert_eq!(BUY_OPPOSITE, OrderSide::Sell);
491 assert_eq!(SELL_OPPOSITE, OrderSide::Buy);
492 }
493
494 #[test]
495 fn test_order_type() {
496 let types = vec![
497 (OrderType::Market, "0", "Market"),
498 (OrderType::Limit, "1", "Limit"),
499 (OrderType::Stop, "2", "Stop"),
500 (OrderType::StopLimit, "3", "StopLimit"),
501 (OrderType::FillOrKill, "4", "FillOrKill"),
502 (OrderType::ImmediateOrCancel, "5", "ImmediateOrCancel"),
503 (OrderType::PostOnly, "6", "PostOnly"),
504 ];
505
506 for (ot, num, name) in types {
507 assert_eq!(format!("{ot}"), name);
508 assert_eq!(json::to_smartstring(&ot).unwrap(), num);
509 assert_eq!(json::parse::<OrderType>(num).unwrap(), ot);
510 }
511 }
512
513 #[test]
514 fn test_exchange() {
515 assert_eq!(format!("{}", Exchange::Binance), "Binance");
516 assert_eq!(
517 json::to_smartstring(&Exchange::Binance).unwrap(),
518 "\"binance\""
519 );
520 assert_eq!(
521 json::parse::<Exchange>("\"binance\"").unwrap(),
522 Exchange::Binance
523 );
524 assert_eq!(
525 json::parse::<Exchange>("\"BINANCE\"").unwrap(),
526 Exchange::Binance
527 );
528 }
529}