architect_api/cpty/
wintermute.rs

1use crate::{
2    folio::FolioMessage,
3    orderflow::*,
4    symbology::{market::NormalizedMarketInfo, ProductId},
5    Dir, Str,
6};
7use arcstr::ArcStr;
8use chrono::{DateTime, Utc};
9#[cfg(feature = "netidx")]
10use derive::FromValue;
11use log::error;
12#[cfg(feature = "netidx")]
13use netidx_derive::Pack;
14use rust_decimal::Decimal;
15use schemars::JsonSchema;
16use serde_derive::{Deserialize, Serialize};
17use std::ops::{Deref, DerefMut};
18
19#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
20#[cfg_attr(feature = "netidx", derive(Pack))]
21pub struct WintermuteMarketInfo {
22    pub tick_size: Decimal,
23    pub step_size: Decimal,
24    pub is_delisted: bool,
25}
26
27impl NormalizedMarketInfo for WintermuteMarketInfo {
28    fn tick_size(&self) -> Decimal {
29        self.tick_size
30    }
31
32    fn step_size(&self) -> Decimal {
33        self.step_size
34    }
35
36    fn is_delisted(&self) -> bool {
37        self.is_delisted
38    }
39}
40
41impl std::fmt::Display for WintermuteMarketInfo {
42    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43        write!(f, "{}", serde_json::to_string_pretty(self).unwrap())?;
44        Ok(())
45    }
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
49#[cfg_attr(feature = "netidx", derive(Pack))]
50#[cfg_attr(feature = "netidx", derive(FromValue))]
51pub enum WintermuteMessage {
52    Order(WintermuteOrder),
53    Ack(Ack),
54    Reject(Reject),
55    Fill(WintermuteFill),
56    Out(Out),
57    ExecutionReport(ExecutionReport),
58    Balances(Vec<(ProductId, Decimal)>),
59    Folio(FolioMessage),
60}
61
62impl TryInto<WintermuteMessage> for &OrderflowMessage {
63    type Error = ();
64
65    fn try_into(self) -> Result<WintermuteMessage, ()> {
66        match self {
67            OrderflowMessage::Order(o) => {
68                Ok(WintermuteMessage::Order(WintermuteOrder { order: *o }))
69            }
70            OrderflowMessage::Ack(a) => Ok(WintermuteMessage::Ack(*a)),
71            OrderflowMessage::Cancel(_) => Err(()),
72            OrderflowMessage::Reject(r) => Ok(WintermuteMessage::Reject(r.clone())),
73            OrderflowMessage::CancelAll(_) => {
74                Err(error!("Cancel all not implemented for Wintermute"))
75            }
76            OrderflowMessage::Fill(f) => {
77                Ok(WintermuteMessage::Fill(WintermuteFill { fill: *f }))
78            }
79            OrderflowMessage::Out(o) => Ok(WintermuteMessage::Out(*o)),
80        }
81    }
82}
83
84impl TryInto<OrderflowMessage> for &WintermuteMessage {
85    type Error = ();
86
87    fn try_into(self) -> Result<OrderflowMessage, ()> {
88        match self {
89            WintermuteMessage::Order(o) => Ok(OrderflowMessage::Order(**o)),
90            WintermuteMessage::Ack(a) => Ok(OrderflowMessage::Ack(*a)),
91            WintermuteMessage::Reject(r) => Ok(OrderflowMessage::Reject(r.clone())),
92            WintermuteMessage::Fill(f) => Ok(OrderflowMessage::Fill(**f)),
93            WintermuteMessage::Out(o) => Ok(OrderflowMessage::Out(*o)),
94            WintermuteMessage::Balances(_)
95            | WintermuteMessage::Folio(_)
96            | WintermuteMessage::ExecutionReport(_) => Err(()),
97        }
98    }
99}
100
101impl TryInto<FolioMessage> for &WintermuteMessage {
102    type Error = ();
103
104    fn try_into(self) -> Result<FolioMessage, ()> {
105        match self {
106            WintermuteMessage::Folio(f) => Ok(f.clone()),
107            _ => Err(()),
108        }
109    }
110}
111
112impl TryFrom<&FolioMessage> for WintermuteMessage {
113    type Error = ();
114
115    fn try_from(f: &FolioMessage) -> Result<Self, ()> {
116        Ok(Self::Folio(f.clone()))
117    }
118}
119
120#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
121#[cfg_attr(feature = "netidx", derive(Pack))]
122#[cfg_attr(feature = "netidx", derive(FromValue))]
123pub struct ExecutionReport {
124    pub client_order_id: Str,
125    pub order_id: Str,
126    pub execution_id: Str,
127    pub exec_type: ExecType,
128    pub order_status: Str,
129    pub symbol: Str,
130    pub product: Str,
131    pub currency: Str,
132    pub side: Dir,
133    pub order_qty: Decimal,
134    pub last_qty: Decimal,
135    pub cum_qty: Decimal,
136    pub leaves_qty: Decimal,
137    pub price: Option<Decimal>,
138    pub transact_time: DateTime<Utc>,
139    pub text: Option<ArcStr>,
140}
141
142#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
143#[cfg_attr(feature = "netidx", derive(Pack))]
144#[cfg_attr(feature = "netidx", derive(FromValue))]
145pub enum ExecType {
146    Canceled,
147    Rejected,
148    Expired,
149    Trade,
150}
151
152#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
153#[cfg_attr(feature = "netidx", derive(Pack))]
154pub struct WintermuteOrder {
155    #[serde(flatten)]
156    pub order: Order,
157}
158
159impl From<Order> for WintermuteOrder {
160    fn from(order: Order) -> Self {
161        Self { order }
162    }
163}
164
165impl Deref for WintermuteOrder {
166    type Target = Order;
167
168    fn deref(&self) -> &Self::Target {
169        &self.order
170    }
171}
172
173impl DerefMut for WintermuteOrder {
174    fn deref_mut(&mut self) -> &mut Self::Target {
175        &mut self.order
176    }
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
180#[cfg_attr(feature = "netidx", derive(Pack))]
181pub struct WintermuteFill {
182    #[serde(flatten)]
183    pub fill: Result<Fill, AberrantFill>,
184}
185
186impl Deref for WintermuteFill {
187    type Target = Result<Fill, AberrantFill>;
188
189    fn deref(&self) -> &Self::Target {
190        &self.fill
191    }
192}