1use crate::{
2 folio::FolioMessage,
3 orderflow::{
4 self, AberrantFill, Ack, Cancel, Fill, Order, OrderSource, OrderStateFlags,
5 OrderType, OrderflowMessage, Out, Reject, TimeInForce,
6 },
7 symbology::{market::NormalizedMarketInfo, CptyId, MarketId},
8 AccountId, Address, Dir, HalfOpenRange, OrderId, Str, UserId,
9};
10use anyhow::Result;
11use chrono::{DateTime, Utc};
12#[cfg(feature = "netidx")]
13use derive::FromValue;
14#[cfg(feature = "netidx")]
15use netidx_derive::Pack;
16use rust_decimal::Decimal;
17use schemars::JsonSchema;
18use serde_derive::{Deserialize, Serialize};
19use std::ops::{Deref, DerefMut};
20
21#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
22#[cfg_attr(feature = "netidx", derive(Pack))]
23pub struct DeribitMarketInfo {
24 pub tick_size: Decimal,
25 pub min_trade_amount: Decimal,
26 pub is_active: bool,
27}
28
29impl NormalizedMarketInfo for DeribitMarketInfo {
30 fn tick_size(&self) -> Decimal {
31 self.tick_size
32 }
33
34 fn step_size(&self) -> Decimal {
35 self.min_trade_amount
36 }
37
38 fn is_delisted(&self) -> bool {
39 !self.is_active
40 }
41}
42
43impl std::fmt::Display for DeribitMarketInfo {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 write!(f, "{}", serde_json::to_string_pretty(self).unwrap())?;
46 Ok(())
47 }
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
51#[cfg_attr(feature = "netidx", derive(Pack))]
52#[cfg_attr(feature = "netidx", derive(FromValue))]
53pub enum DeribitMessage {
54 Order(DeribitOrder),
55 Cancel(DeribitCancel),
56 CancelAll(CancelAll),
57 Reject(Reject),
58 Ack(Ack),
59 Fill(DeribitFill),
60 Out(Out),
61 Folio(FolioMessage),
62 ExchangeOrderUpdate(DeribitExternalOrderAck),
63 ExchangeAck(OrderId, DeribitExchangeId),
64 ExchangeFill(DeribitExternalFill),
65 ExchangeOrderOut(u64),
66 BalanceRequest(DeribitBalanceQuery),
67 TradeQueryRequest(DeribitTradeQuery),
68 SupportedCurrencies(Vec<String>),
69 FolioMessagesAllowed(bool),
70}
71
72impl TryInto<DeribitMessage> for &OrderflowMessage {
73 type Error = ();
74
75 fn try_into(self) -> Result<DeribitMessage, ()> {
76 match self {
77 OrderflowMessage::Order(o) => {
78 Ok(DeribitMessage::Order(DeribitOrder { order: *o }))
79 }
80 OrderflowMessage::Cancel(c) => Ok(DeribitMessage::Cancel(DeribitCancel {
81 cancel: *c,
82 exchange_id: None,
83 })),
84 OrderflowMessage::Reject(r) => Ok(DeribitMessage::Reject(r.clone())),
85 OrderflowMessage::Ack(a) => Ok(DeribitMessage::Ack(*a)),
86 OrderflowMessage::Fill(_) => Err(()),
87 OrderflowMessage::Out(o) => Ok(DeribitMessage::Out(*o)),
88 OrderflowMessage::CancelAll(_) => Ok(DeribitMessage::CancelAll(CancelAll {})),
89 }
90 }
91}
92
93impl TryInto<FolioMessage> for &DeribitMessage {
94 type Error = ();
95
96 fn try_into(self) -> Result<FolioMessage, ()> {
97 match self {
98 DeribitMessage::Folio(f) => Ok(f.clone()),
99 _ => Err(()),
100 }
101 }
102}
103
104impl TryFrom<&FolioMessage> for DeribitMessage {
105 type Error = ();
106
107 fn try_from(f: &FolioMessage) -> Result<Self, ()> {
108 Ok(Self::Folio(f.clone()))
109 }
110}
111
112impl TryInto<OrderflowMessage> for &DeribitMessage {
113 type Error = ();
114
115 fn try_into(self) -> Result<OrderflowMessage, ()> {
116 match self {
117 DeribitMessage::Order(o) => Ok(OrderflowMessage::Order(**o)),
118 DeribitMessage::Cancel(c) => Ok(OrderflowMessage::Cancel(**c)),
119 DeribitMessage::Reject(r) => Ok(OrderflowMessage::Reject(r.clone())),
120 DeribitMessage::Ack(a) => Ok(OrderflowMessage::Ack(*a)),
121 DeribitMessage::Fill(f) => Ok(OrderflowMessage::Fill(**f)),
122 DeribitMessage::CancelAll(_) => {
123 Ok(OrderflowMessage::CancelAll(orderflow::CancelAll::default()))
124 }
125 DeribitMessage::Out(o) => Ok(OrderflowMessage::Out(*o)),
126 DeribitMessage::Folio(..)
127 | DeribitMessage::SupportedCurrencies(..)
128 | DeribitMessage::FolioMessagesAllowed(..)
129 | DeribitMessage::BalanceRequest(..)
130 | DeribitMessage::TradeQueryRequest(..)
131 | DeribitMessage::ExchangeOrderUpdate(..)
132 | DeribitMessage::ExchangeAck(..)
133 | DeribitMessage::ExchangeFill(..)
134 | DeribitMessage::ExchangeOrderOut(..) => Err(()),
135 }
136 }
137}
138
139pub type DeribitExchangeId = String;
140pub type DeribitUserRef = u64;
141
142#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
143#[cfg_attr(feature = "netidx", derive(Pack))]
144pub struct CancelAll {}
145
146#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
147#[cfg_attr(feature = "netidx", derive(Pack))]
148pub struct DeribitOrder {
149 #[serde(flatten)]
150 pub order: Order,
151}
152
153impl From<Order> for DeribitOrder {
154 fn from(order: Order) -> Self {
155 Self { order }
156 }
157}
158
159impl Deref for DeribitOrder {
160 type Target = Order;
161
162 fn deref(&self) -> &Self::Target {
163 &self.order
164 }
165}
166
167impl DerefMut for DeribitOrder {
168 fn deref_mut(&mut self) -> &mut Self::Target {
169 &mut self.order
170 }
171}
172
173#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
174#[cfg_attr(feature = "netidx", derive(Pack))]
175pub struct DeribitCancel {
176 #[serde(flatten)]
177 pub cancel: Cancel,
178 pub exchange_id: Option<Str>,
179}
180
181impl From<Cancel> for DeribitCancel {
182 fn from(cancel: Cancel) -> Self {
183 Self { cancel, exchange_id: None }
184 }
185}
186
187impl Deref for DeribitCancel {
188 type Target = Cancel;
189
190 fn deref(&self) -> &Self::Target {
191 &self.cancel
192 }
193}
194
195impl DerefMut for DeribitCancel {
196 fn deref_mut(&mut self) -> &mut Self::Target {
197 &mut self.cancel
198 }
199}
200
201#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
202#[cfg_attr(feature = "netidx", derive(Pack))]
203pub struct DeribitFill {
204 #[serde(flatten)]
205 pub fill: Result<Fill, AberrantFill>,
206 pub exchange_trade_id: DeribitExchangeId,
207 pub exchange_order_id: DeribitExchangeId,
208}
209
210impl Deref for DeribitFill {
211 type Target = Result<Fill, AberrantFill>;
212
213 fn deref(&self) -> &Self::Target {
214 &self.fill
215 }
216}
217
218#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
219#[cfg_attr(feature = "netidx", derive(Pack))]
220pub struct DeribitExternalOrderAck {
221 pub exchange_symbol: String,
222 pub exchange_order_id: DeribitExchangeId,
223 pub user_reference_id: DeribitUserRef,
224 pub quantity: Decimal,
225 pub trigger_price: Option<Decimal>,
226 pub dir: Dir,
227 pub expiration: Option<DateTime<Utc>>,
228 pub order_type: OrderType,
229 pub time_in_force: TimeInForce,
230 pub order_state: OrderStateFlags,
231}
232
233impl DeribitExternalOrderAck {
234 pub fn to_deribit_order(
235 &mut self,
236 oid: OrderId,
237 mid: MarketId,
238 trader: Option<UserId>,
239 account: Option<AccountId>,
240 ) -> Result<DeribitOrder> {
242 let order = Order {
243 id: oid,
244 market: mid,
245 dir: self.dir,
246 quantity: self.quantity,
247 trader,
248 account,
249 order_type: self.order_type,
250 time_in_force: self.time_in_force,
251 quote_id: None,
252 source: OrderSource::External,
253 parent_order: None,
254 };
256 Ok(DeribitOrder { order })
257 }
258}
259
260#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
261#[cfg_attr(feature = "netidx", derive(Pack))]
262pub struct DeribitExternalFill {
263 pub exchange_order_id: DeribitExchangeId,
264 pub exchange_trade_id: DeribitExchangeId,
265 pub user_reference_id: Option<DeribitUserRef>,
266 pub time: DateTime<Utc>,
267 pub quantity: Decimal,
268 pub price: Decimal,
269 pub dir: Dir,
270 pub status: FillOrderStatus,
271 pub unique_fill_id: String,
272 pub fee: Option<Decimal>,
273 pub fee_currency: Option<String>,
274 pub exchange_symbol: Option<String>,
275 pub is_maker: Option<bool>,
276}
277
278#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
279#[cfg_attr(feature = "netidx", derive(Pack))]
280pub enum FillOrderStatus {
281 #[serde(alias = "open")]
282 Open,
283 #[serde(alias = "filled")]
284 Filled,
285 #[serde(alias = "rejected")]
286 Rejected,
287 #[serde(alias = "cancelled")]
288 Cancelled,
289 #[serde(alias = "untriggered")]
290 Untriggered,
291 #[serde(alias = "archive")]
292 Archive,
293 Unknown,
294}
295
296#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
297#[cfg_attr(feature = "netidx", derive(Pack))]
298pub struct DeribitBalanceQuery {
299 pub cpty_id: CptyId,
300 pub reply_to: Address,
301}
302
303#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
304#[cfg_attr(feature = "netidx", derive(Pack))]
305pub struct DeribitTradeQuery {
306 pub cpty_id: CptyId,
307 pub reply_to: Address,
308 pub range: HalfOpenRange<Option<DateTime<Utc>>>,
309}