architect_api/cpty/
deribit.rs

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        // recv_time: DateTime<Utc>,
241    ) -> 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            // recv_time,
255        };
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}