1use crate::{
2 folio::FolioMessage, orderflow::*, symbology::market::NormalizedMarketInfo, Dir, Str,
3};
4use chrono::{DateTime, Utc};
5#[cfg(feature = "netidx")]
6use derive::FromValue;
7use log::error;
8#[cfg(feature = "netidx")]
9use netidx_derive::Pack;
10use rust_decimal::Decimal;
11use schemars::JsonSchema;
12use serde::{Deserialize, Serialize};
13use std::ops::{Deref, DerefMut};
14
15#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
16#[cfg_attr(feature = "netidx", derive(Pack))]
17pub struct CoinbasePrimeMarketInfo {
18 pub base_increment: Decimal,
19 pub quote_increment: Decimal,
20 pub base_min_size: Decimal,
21 pub quote_min_size: Decimal,
22 pub base_max_size: Decimal,
23 pub quote_max_size: Decimal,
24}
25
26impl NormalizedMarketInfo for CoinbasePrimeMarketInfo {
27 fn tick_size(&self) -> Decimal {
28 self.quote_increment
29 }
30
31 fn step_size(&self) -> Decimal {
32 self.base_increment
33 }
34
35 fn is_delisted(&self) -> bool {
36 false
37 }
38}
39
40impl std::fmt::Display for CoinbasePrimeMarketInfo {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 write!(f, "{}", serde_json::to_string_pretty(self).unwrap())?;
43 Ok(())
44 }
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
48#[cfg_attr(feature = "netidx", derive(Pack))]
49#[cfg_attr(feature = "netidx", derive(FromValue))]
50pub enum CoinbasePrimeMessage {
51 Order(CoinbasePrimeOrder),
52 Cancel(Cancel),
53 Ack(Ack),
54 Reject(Reject),
55 Fill(CoinbasePrimeFill),
56 Out(Out),
57 ExchangeExecutionReport(ExchangeExecutionReport),
58 Folio(FolioMessage),
59}
60
61impl TryInto<CoinbasePrimeMessage> for &OrderflowMessage {
62 type Error = ();
63
64 fn try_into(self) -> Result<CoinbasePrimeMessage, ()> {
65 match self {
66 OrderflowMessage::Order(o) => {
67 Ok(CoinbasePrimeMessage::Order(CoinbasePrimeOrder { order: *o }))
68 }
69 OrderflowMessage::Ack(a) => Ok(CoinbasePrimeMessage::Ack(*a)),
70 OrderflowMessage::Cancel(c) => Ok(CoinbasePrimeMessage::Cancel(*c)),
71 OrderflowMessage::Reject(r) => Ok(CoinbasePrimeMessage::Reject(r.clone())),
72 OrderflowMessage::Fill(f) => {
73 Ok(CoinbasePrimeMessage::Fill(CoinbasePrimeFill { fill: *f }))
74 }
75 OrderflowMessage::Out(o) => Ok(CoinbasePrimeMessage::Out(*o)),
76 OrderflowMessage::CancelAll(_) => {
77 Err(error!("Cancel all not implemented for CoinbasePrime"))
78 }
79 }
80 }
81}
82
83impl TryInto<OrderflowMessage> for &CoinbasePrimeMessage {
84 type Error = ();
85
86 fn try_into(self) -> Result<OrderflowMessage, ()> {
87 match self {
88 CoinbasePrimeMessage::Order(o) => Ok(OrderflowMessage::Order(**o)),
89 CoinbasePrimeMessage::Ack(a) => Ok(OrderflowMessage::Ack(*a)),
90 CoinbasePrimeMessage::Cancel(c) => Ok(OrderflowMessage::Cancel(*c)),
91 CoinbasePrimeMessage::Reject(r) => Ok(OrderflowMessage::Reject(r.clone())),
92 CoinbasePrimeMessage::Fill(f) => Ok(OrderflowMessage::Fill(**f)),
93 CoinbasePrimeMessage::Out(o) => Ok(OrderflowMessage::Out(*o)),
94 CoinbasePrimeMessage::Folio(_)
95 | CoinbasePrimeMessage::ExchangeExecutionReport(_) => Err(()),
96 }
97 }
98}
99
100impl TryInto<FolioMessage> for &CoinbasePrimeMessage {
101 type Error = ();
102
103 fn try_into(self) -> Result<FolioMessage, ()> {
104 match self {
105 CoinbasePrimeMessage::Folio(f) => Ok(f.clone()),
106 _ => Err(()),
107 }
108 }
109}
110
111impl TryFrom<&FolioMessage> for CoinbasePrimeMessage {
112 type Error = ();
113
114 fn try_from(f: &FolioMessage) -> Result<Self, ()> {
115 Ok(Self::Folio(f.clone()))
116 }
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
120#[cfg_attr(feature = "netidx", derive(Pack))]
121#[cfg_attr(feature = "netidx", derive(FromValue))]
122pub enum ExchangeExecType {
123 NewOrder,
124 PartialFill,
125 Filled,
126 Done,
127 Canceled,
128 PendingCancel,
129 Stopped,
130 Rejected,
131 Restated,
132 PendingNew,
133 OrderStatus,
134}
135
136#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
137#[cfg_attr(feature = "netidx", derive(Pack))]
138#[cfg_attr(feature = "netidx", derive(FromValue))]
139pub struct ExchangeExecutionReport {
140 pub order_average_price: Decimal,
141 pub client_order_id: Str,
142 pub commission: Option<Decimal>,
143 pub cum_qty: Decimal,
144 pub execution_id: Str,
145 pub last_price: Option<Decimal>,
146 pub last_qty: Option<Decimal>,
147 pub order_id: Str,
148 pub order_qty: Decimal,
149 pub order_status: Str,
150 pub sender_sub_id: Str,
151 pub side: Dir,
152 pub symbol: Str,
153 pub order_reject_reason: Option<ExchangeOrderRejectReason>,
154 pub exec_type: ExchangeExecType,
155 pub leaves_qty: Decimal,
156 pub last_mkt: Option<Str>,
158 pub transact_time: DateTime<Utc>,
159}
160
161#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
162#[cfg_attr(feature = "netidx", derive(Pack))]
163#[cfg_attr(feature = "netidx", derive(FromValue))]
164pub enum ExchangeOrderRejectReason {
165 BrokerOption,
166 UnknownSymbol,
167 ExchangeClosed,
168 OrderExceedsLimit,
169 TooLateToEnter,
170 UnknownOrder,
171 DuplicateOrder,
172}
173
174#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
175#[cfg_attr(feature = "netidx", derive(Pack))]
176#[cfg_attr(feature = "netidx", derive(FromValue))]
177pub struct CoinbasePrimeOrder {
178 #[serde(flatten)]
179 pub order: Order,
180}
181
182impl From<Order> for CoinbasePrimeOrder {
183 fn from(order: Order) -> Self {
184 Self { order }
185 }
186}
187
188impl Deref for CoinbasePrimeOrder {
189 type Target = Order;
190
191 fn deref(&self) -> &Self::Target {
192 &self.order
193 }
194}
195
196impl DerefMut for CoinbasePrimeOrder {
197 fn deref_mut(&mut self) -> &mut Self::Target {
198 &mut self.order
199 }
200}
201
202#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
203#[cfg_attr(feature = "netidx", derive(Pack))]
204pub struct CoinbasePrimeFill {
205 #[serde(flatten)]
206 pub fill: Result<Fill, AberrantFill>,
207}
208
209impl Deref for CoinbasePrimeFill {
210 type Target = Result<Fill, AberrantFill>;
211
212 fn deref(&self) -> &Self::Target {
213 &self.fill
214 }
215}