1use serde::{Deserialize, Serialize};
10use std::convert::TryFrom;
11
12pub mod cancel_reject;
13pub mod cancel_replace_request;
14pub mod cancel_request;
15pub mod execution_report;
16pub mod mass_cancel;
17pub mod mass_status;
18pub mod new_order;
19
20pub use cancel_reject::*;
21pub use cancel_replace_request::*;
22pub use cancel_request::*;
23pub use execution_report::*;
24pub use mass_cancel::*;
25pub use mass_status::*;
26pub use new_order::*;
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
30pub enum OrderSide {
31 Buy,
33 Sell,
35}
36
37impl From<OrderSide> for char {
38 fn from(side: OrderSide) -> Self {
39 match side {
40 OrderSide::Buy => '1',
41 OrderSide::Sell => '2',
42 }
43 }
44}
45
46impl TryFrom<char> for OrderSide {
47 type Error = String;
48
49 fn try_from(value: char) -> Result<Self, Self::Error> {
50 match value {
51 '1' => Ok(OrderSide::Buy),
52 '2' => Ok(OrderSide::Sell),
53 _ => Err(format!("Invalid OrderSide: {value}")),
54 }
55 }
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
60pub enum OrderType {
61 Market,
63 Limit,
65 MarketLimit,
67 StopLimit,
69 MarketIfTouched,
71 StopLimitOnBidOffer,
73}
74
75impl From<OrderType> for char {
76 fn from(order_type: OrderType) -> Self {
77 match order_type {
78 OrderType::Market => '1',
79 OrderType::Limit => '2',
80 OrderType::MarketLimit => 'K',
81 OrderType::StopLimit => '4',
82 OrderType::MarketIfTouched => 'J',
83 OrderType::StopLimitOnBidOffer => 'S',
84 }
85 }
86}
87
88impl TryFrom<char> for OrderType {
89 type Error = String;
90
91 fn try_from(value: char) -> Result<Self, Self::Error> {
92 match value {
93 '1' => Ok(OrderType::Market),
94 '2' => Ok(OrderType::Limit),
95 'K' => Ok(OrderType::MarketLimit),
96 '4' => Ok(OrderType::StopLimit),
97 'J' => Ok(OrderType::MarketIfTouched),
98 'S' => Ok(OrderType::StopLimitOnBidOffer),
99 _ => Err(format!("Invalid OrderType: {value}")),
100 }
101 }
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
106pub enum TimeInForce {
107 GoodTillDay,
109 GoodTillCancelled,
111 ImmediateOrCancel,
113 FillOrKill,
115}
116
117impl From<TimeInForce> for char {
118 fn from(tif: TimeInForce) -> Self {
119 match tif {
120 TimeInForce::GoodTillDay => '0',
121 TimeInForce::GoodTillCancelled => '1',
122 TimeInForce::ImmediateOrCancel => '3',
123 TimeInForce::FillOrKill => '4',
124 }
125 }
126}
127
128impl TryFrom<char> for TimeInForce {
129 type Error = String;
130
131 fn try_from(value: char) -> Result<Self, Self::Error> {
132 match value {
133 '0' => Ok(TimeInForce::GoodTillDay),
134 '1' => Ok(TimeInForce::GoodTillCancelled),
135 '3' => Ok(TimeInForce::ImmediateOrCancel),
136 '4' => Ok(TimeInForce::FillOrKill),
137 _ => Err(format!("Invalid TimeInForce: {value}")),
138 }
139 }
140}
141
142#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
144pub enum OrderStatus {
145 New,
147 PartiallyFilled,
149 Filled,
151 Cancelled,
153 PendingCancel,
155 Rejected,
157}
158
159impl From<OrderStatus> for char {
160 fn from(status: OrderStatus) -> Self {
161 match status {
162 OrderStatus::New => '0',
163 OrderStatus::PartiallyFilled => '1',
164 OrderStatus::Filled => '2',
165 OrderStatus::Cancelled => '4',
166 OrderStatus::PendingCancel => '6',
167 OrderStatus::Rejected => '8',
168 }
169 }
170}
171
172impl TryFrom<char> for OrderStatus {
173 type Error = String;
174
175 fn try_from(value: char) -> Result<Self, Self::Error> {
176 match value {
177 '0' => Ok(OrderStatus::New),
178 '1' => Ok(OrderStatus::PartiallyFilled),
179 '2' => Ok(OrderStatus::Filled),
180 '4' => Ok(OrderStatus::Cancelled),
181 '6' => Ok(OrderStatus::PendingCancel),
182 '8' => Ok(OrderStatus::Rejected),
183 _ => Err(format!("Invalid OrderStatus: {value}")),
184 }
185 }
186}
187
188#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
190pub enum OrderRejectReason {
191 NoReject,
193 UnknownSymbol,
195 ExchangeClosed,
197 OrderExceedsLimit,
199 TooLateToEnter,
201 UnknownOrder,
203 DuplicateOrder,
205 DuplicateVerbalOrder,
207 StaleOrder,
209 TradeAlongRequired,
211 InvalidInvestorId,
213 UnsupportedOrderCharacteristic,
215 SurveillanceOption,
217 IncorrectQuantity,
219 IncorrectAllocatedQuantity,
221 UnknownAccount,
223 PriceExceedsPriceBand,
225 InvalidPriceIncrement,
227 Other,
229}
230
231impl From<OrderRejectReason> for i32 {
232 fn from(reason: OrderRejectReason) -> Self {
233 match reason {
234 OrderRejectReason::NoReject => 0,
235 OrderRejectReason::UnknownSymbol => 1,
236 OrderRejectReason::ExchangeClosed => 2,
237 OrderRejectReason::OrderExceedsLimit => 3,
238 OrderRejectReason::TooLateToEnter => 4,
239 OrderRejectReason::UnknownOrder => 5,
240 OrderRejectReason::DuplicateOrder => 6,
241 OrderRejectReason::DuplicateVerbalOrder => 7,
242 OrderRejectReason::StaleOrder => 8,
243 OrderRejectReason::TradeAlongRequired => 9,
244 OrderRejectReason::InvalidInvestorId => 10,
245 OrderRejectReason::UnsupportedOrderCharacteristic => 11,
246 OrderRejectReason::SurveillanceOption => 12,
247 OrderRejectReason::IncorrectQuantity => 13,
248 OrderRejectReason::IncorrectAllocatedQuantity => 14,
249 OrderRejectReason::UnknownAccount => 15,
250 OrderRejectReason::PriceExceedsPriceBand => 16,
251 OrderRejectReason::InvalidPriceIncrement => 18,
252 OrderRejectReason::Other => 99,
253 }
254 }
255}
256
257impl TryFrom<i32> for OrderRejectReason {
258 type Error = String;
259
260 fn try_from(value: i32) -> Result<Self, Self::Error> {
261 match value {
262 0 => Ok(OrderRejectReason::NoReject),
263 1 => Ok(OrderRejectReason::UnknownSymbol),
264 2 => Ok(OrderRejectReason::ExchangeClosed),
265 3 => Ok(OrderRejectReason::OrderExceedsLimit),
266 4 => Ok(OrderRejectReason::TooLateToEnter),
267 5 => Ok(OrderRejectReason::UnknownOrder),
268 6 => Ok(OrderRejectReason::DuplicateOrder),
269 7 => Ok(OrderRejectReason::DuplicateVerbalOrder),
270 8 => Ok(OrderRejectReason::StaleOrder),
271 9 => Ok(OrderRejectReason::TradeAlongRequired),
272 10 => Ok(OrderRejectReason::InvalidInvestorId),
273 11 => Ok(OrderRejectReason::UnsupportedOrderCharacteristic),
274 12 => Ok(OrderRejectReason::SurveillanceOption),
275 13 => Ok(OrderRejectReason::IncorrectQuantity),
276 14 => Ok(OrderRejectReason::IncorrectAllocatedQuantity),
277 15 => Ok(OrderRejectReason::UnknownAccount),
278 16 => Ok(OrderRejectReason::PriceExceedsPriceBand),
279 18 => Ok(OrderRejectReason::InvalidPriceIncrement),
280 99 => Ok(OrderRejectReason::Other),
281 _ => Err(format!("Invalid OrderRejectReason: {value}")),
282 }
283 }
284}
285
286#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
288pub enum MassCancelRequestType {
289 BySymbol,
291 BySecurityType,
293 AllOrders,
295 ByDeribitLabel,
297}
298
299impl From<MassCancelRequestType> for i32 {
300 fn from(request_type: MassCancelRequestType) -> Self {
301 match request_type {
302 MassCancelRequestType::BySymbol => 1,
303 MassCancelRequestType::BySecurityType => 5,
304 MassCancelRequestType::AllOrders => 7,
305 MassCancelRequestType::ByDeribitLabel => 10,
306 }
307 }
308}
309
310impl TryFrom<i32> for MassCancelRequestType {
311 type Error = String;
312
313 fn try_from(value: i32) -> Result<Self, Self::Error> {
314 match value {
315 1 => Ok(MassCancelRequestType::BySymbol),
316 5 => Ok(MassCancelRequestType::BySecurityType),
317 7 => Ok(MassCancelRequestType::AllOrders),
318 10 => Ok(MassCancelRequestType::ByDeribitLabel),
319 _ => Err(format!("Invalid MassCancelRequestType: {value}")),
320 }
321 }
322}
323
324#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
326pub enum MassStatusRequestType {
327 SpecificOrder,
329 AllOrders,
331 Historical,
333}
334
335impl From<MassStatusRequestType> for i32 {
336 fn from(request_type: MassStatusRequestType) -> Self {
337 match request_type {
338 MassStatusRequestType::SpecificOrder => 1,
339 MassStatusRequestType::AllOrders => 7,
340 MassStatusRequestType::Historical => 10,
341 }
342 }
343}
344
345impl TryFrom<i32> for MassStatusRequestType {
346 type Error = String;
347
348 fn try_from(value: i32) -> Result<Self, Self::Error> {
349 match value {
350 1 => Ok(MassStatusRequestType::SpecificOrder),
351 7 => Ok(MassStatusRequestType::AllOrders),
352 10 => Ok(MassStatusRequestType::Historical),
353 _ => Err(format!("Invalid MassStatusRequestType: {value}")),
354 }
355 }
356}
357
358#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
360pub enum MassStatusRequestIdType {
361 OrigClOrdId,
363 ClOrdId,
365 DeribitLabel,
367}
368
369impl From<MassStatusRequestIdType> for i32 {
370 fn from(id_type: MassStatusRequestIdType) -> Self {
371 match id_type {
372 MassStatusRequestIdType::OrigClOrdId => 0,
373 MassStatusRequestIdType::ClOrdId => 1,
374 MassStatusRequestIdType::DeribitLabel => 2,
375 }
376 }
377}
378
379impl TryFrom<i32> for MassStatusRequestIdType {
380 type Error = String;
381
382 fn try_from(value: i32) -> Result<Self, Self::Error> {
383 match value {
384 0 => Ok(MassStatusRequestIdType::OrigClOrdId),
385 1 => Ok(MassStatusRequestIdType::ClOrdId),
386 2 => Ok(MassStatusRequestIdType::DeribitLabel),
387 _ => Err(format!("Invalid MassStatusRequestIdType: {value}")),
388 }
389 }
390}
391
392#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
394pub enum QuantityType {
395 Units,
397 Contracts,
399}
400
401impl From<QuantityType> for i32 {
402 fn from(qty_type: QuantityType) -> Self {
403 match qty_type {
404 QuantityType::Units => 0,
405 QuantityType::Contracts => 1,
406 }
407 }
408}
409
410impl TryFrom<i32> for QuantityType {
411 type Error = String;
412
413 fn try_from(value: i32) -> Result<Self, Self::Error> {
414 match value {
415 0 => Ok(QuantityType::Units),
416 1 => Ok(QuantityType::Contracts),
417 _ => Err(format!("Invalid QuantityType: {value}")),
418 }
419 }
420}
421
422#[cfg(test)]
423mod tests {
424 use super::*;
425
426 #[test]
427 fn test_order_side_conversion() {
428 assert_eq!(char::from(OrderSide::Buy), '1');
429 assert_eq!(char::from(OrderSide::Sell), '2');
430
431 assert_eq!(OrderSide::try_from('1').unwrap(), OrderSide::Buy);
432 assert_eq!(OrderSide::try_from('2').unwrap(), OrderSide::Sell);
433 assert!(OrderSide::try_from('3').is_err());
434 }
435
436 #[test]
437 fn test_order_type_conversion() {
438 assert_eq!(char::from(OrderType::Market), '1');
439 assert_eq!(char::from(OrderType::Limit), '2');
440 assert_eq!(char::from(OrderType::MarketLimit), 'K');
441
442 assert_eq!(OrderType::try_from('1').unwrap(), OrderType::Market);
443 assert_eq!(OrderType::try_from('2').unwrap(), OrderType::Limit);
444 assert_eq!(OrderType::try_from('K').unwrap(), OrderType::MarketLimit);
445 assert!(OrderType::try_from('Z').is_err());
446 }
447
448 #[test]
449 fn test_time_in_force_conversion() {
450 assert_eq!(char::from(TimeInForce::GoodTillDay), '0');
451 assert_eq!(char::from(TimeInForce::GoodTillCancelled), '1');
452 assert_eq!(char::from(TimeInForce::ImmediateOrCancel), '3');
453 assert_eq!(char::from(TimeInForce::FillOrKill), '4');
454
455 assert_eq!(
456 TimeInForce::try_from('0').unwrap(),
457 TimeInForce::GoodTillDay
458 );
459 assert_eq!(
460 TimeInForce::try_from('1').unwrap(),
461 TimeInForce::GoodTillCancelled
462 );
463 assert_eq!(
464 TimeInForce::try_from('3').unwrap(),
465 TimeInForce::ImmediateOrCancel
466 );
467 assert_eq!(TimeInForce::try_from('4').unwrap(), TimeInForce::FillOrKill);
468 assert!(TimeInForce::try_from('5').is_err());
469 }
470
471 #[test]
472 fn test_order_status_conversion() {
473 assert_eq!(char::from(OrderStatus::New), '0');
474 assert_eq!(char::from(OrderStatus::PartiallyFilled), '1');
475 assert_eq!(char::from(OrderStatus::Filled), '2');
476 assert_eq!(char::from(OrderStatus::Cancelled), '4');
477
478 assert_eq!(OrderStatus::try_from('0').unwrap(), OrderStatus::New);
479 assert_eq!(
480 OrderStatus::try_from('1').unwrap(),
481 OrderStatus::PartiallyFilled
482 );
483 assert_eq!(OrderStatus::try_from('2').unwrap(), OrderStatus::Filled);
484 assert_eq!(OrderStatus::try_from('4').unwrap(), OrderStatus::Cancelled);
485 assert!(OrderStatus::try_from('9').is_err());
486 }
487
488 #[test]
489 fn test_order_reject_reason_conversion() {
490 assert_eq!(i32::from(OrderRejectReason::NoReject), 0);
491 assert_eq!(i32::from(OrderRejectReason::UnknownSymbol), 1);
492 assert_eq!(i32::from(OrderRejectReason::Other), 99);
493
494 assert_eq!(
495 OrderRejectReason::try_from(0).unwrap(),
496 OrderRejectReason::NoReject
497 );
498 assert_eq!(
499 OrderRejectReason::try_from(1).unwrap(),
500 OrderRejectReason::UnknownSymbol
501 );
502 assert_eq!(
503 OrderRejectReason::try_from(99).unwrap(),
504 OrderRejectReason::Other
505 );
506 assert!(OrderRejectReason::try_from(100).is_err());
507 }
508
509 #[test]
510 fn test_mass_cancel_request_type_conversion() {
511 assert_eq!(i32::from(MassCancelRequestType::BySymbol), 1);
512 assert_eq!(i32::from(MassCancelRequestType::BySecurityType), 5);
513 assert_eq!(i32::from(MassCancelRequestType::AllOrders), 7);
514 assert_eq!(i32::from(MassCancelRequestType::ByDeribitLabel), 10);
515
516 assert_eq!(
517 MassCancelRequestType::try_from(1).unwrap(),
518 MassCancelRequestType::BySymbol
519 );
520 assert_eq!(
521 MassCancelRequestType::try_from(5).unwrap(),
522 MassCancelRequestType::BySecurityType
523 );
524 assert_eq!(
525 MassCancelRequestType::try_from(7).unwrap(),
526 MassCancelRequestType::AllOrders
527 );
528 assert_eq!(
529 MassCancelRequestType::try_from(10).unwrap(),
530 MassCancelRequestType::ByDeribitLabel
531 );
532 assert!(MassCancelRequestType::try_from(99).is_err());
533 }
534
535 #[test]
536 fn test_quantity_type_conversion() {
537 assert_eq!(i32::from(QuantityType::Units), 0);
538 assert_eq!(i32::from(QuantityType::Contracts), 1);
539
540 assert_eq!(QuantityType::try_from(0).unwrap(), QuantityType::Units);
541 assert_eq!(QuantityType::try_from(1).unwrap(), QuantityType::Contracts);
542 assert!(QuantityType::try_from(2).is_err());
543 }
544
545 #[test]
546 fn test_mass_status_request_type_conversion() {
547 assert_eq!(i32::from(MassStatusRequestType::SpecificOrder), 1);
548 assert_eq!(i32::from(MassStatusRequestType::AllOrders), 7);
549
550 assert_eq!(
551 MassStatusRequestType::try_from(1).unwrap(),
552 MassStatusRequestType::SpecificOrder
553 );
554 assert_eq!(
555 MassStatusRequestType::try_from(7).unwrap(),
556 MassStatusRequestType::AllOrders
557 );
558 assert!(MassStatusRequestType::try_from(99).is_err());
559 }
560
561 #[test]
562 fn test_mass_status_request_id_type_conversion() {
563 assert_eq!(i32::from(MassStatusRequestIdType::OrigClOrdId), 0);
564 assert_eq!(i32::from(MassStatusRequestIdType::ClOrdId), 1);
565 assert_eq!(i32::from(MassStatusRequestIdType::DeribitLabel), 2);
566
567 assert_eq!(
568 MassStatusRequestIdType::try_from(0).unwrap(),
569 MassStatusRequestIdType::OrigClOrdId
570 );
571 assert_eq!(
572 MassStatusRequestIdType::try_from(1).unwrap(),
573 MassStatusRequestIdType::ClOrdId
574 );
575 assert_eq!(
576 MassStatusRequestIdType::try_from(2).unwrap(),
577 MassStatusRequestIdType::DeribitLabel
578 );
579 assert!(MassStatusRequestIdType::try_from(99).is_err());
580 }
581}