1use rust_decimal::Decimal;
2use serde::{Deserialize, Serialize};
3use strum::{Display, EnumString};
4
5use crate::order::{OrderStatus, Side};
6
7#[derive(
8 Debug, Display, Clone, Copy, Serialize, Deserialize, Default, EnumString, PartialEq, Eq, Hash,
9)]
10#[strum(serialize_all = "PascalCase")]
11#[serde(rename_all = "PascalCase")]
12pub enum RfqExecutionMode {
13 #[default]
14 AwaitAccept,
15 Immediate,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
19#[serde(rename_all = "camelCase")]
20pub struct RequestForQuotePayload {
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub client_id: Option<u32>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub quantity: Option<Decimal>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub quote_quantity: Option<Decimal>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub price: Option<Decimal>,
29 pub symbol: String,
30 pub side: Side,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 pub execution_mode: Option<RfqExecutionMode>,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
36#[serde(rename_all = "camelCase")]
37pub struct RequestForQuoteCancelPayload {
38 #[serde(skip_serializing_if = "Option::is_none")]
39 pub rfq_id: Option<String>,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 pub client_id: Option<u32>,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
45#[serde(rename_all = "camelCase")]
46pub struct RequestForQuoteRefreshPayload {
47 pub rfq_id: String,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
51#[serde(rename_all = "camelCase")]
52pub struct QuoteAcceptPayload {
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub rfq_id: Option<String>,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub client_id: Option<u32>,
57 pub quote_id: String,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
61#[serde(rename_all = "camelCase")]
62pub struct QuotePayload {
63 pub rfq_id: String,
64 pub bid_price: Decimal,
65 pub ask_price: Decimal,
66 #[serde(skip_serializing_if = "Option::is_none")]
67 pub client_id: Option<u32>,
68 #[serde(skip_serializing_if = "Option::is_none")]
69 pub auto_lend: Option<bool>,
70 #[serde(skip_serializing_if = "Option::is_none")]
71 pub auto_lend_redeem: Option<bool>,
72 #[serde(skip_serializing_if = "Option::is_none")]
73 pub auto_borrow: Option<bool>,
74 #[serde(skip_serializing_if = "Option::is_none")]
75 pub auto_borrow_repay: Option<bool>,
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct RequestForQuoteStream {
80 pub stream: String,
81 pub data: RequestForQuoteUpdate,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
86#[serde(tag = "e", rename_all = "camelCase")] pub enum RequestForQuoteUpdate {
88 RfqActive {
89 #[serde(rename = "E")]
90 event_time: i64,
91 #[serde(rename = "R")]
92 rfq_id: u64,
93 #[serde(rename = "C", skip_serializing_if = "Option::is_none")]
94 client_id: Option<u32>,
95 #[serde(rename = "s")]
96 symbol: String,
97 #[serde(rename = "q", skip_serializing_if = "Option::is_none")]
98 quantity: Option<Decimal>,
99 #[serde(rename = "Q", skip_serializing_if = "Option::is_none")]
100 quote_quantity: Option<Decimal>,
101 #[serde(rename = "w")]
102 submission_time: i64,
103 #[serde(rename = "W")]
104 expiry_time: i64,
105 #[serde(rename = "X")]
106 order_status: OrderStatus,
107 #[serde(rename = "T")]
108 timestamp: i64,
109 },
110 RfqRefreshed {
111 #[serde(rename = "E")]
112 event_time: i64,
113 #[serde(rename = "R")]
114 rfq_id: u64,
115 #[serde(rename = "C", skip_serializing_if = "Option::is_none")]
116 client_id: Option<u32>,
117 #[serde(rename = "s")]
118 symbol: String,
119 #[serde(rename = "S")]
120 side: Side,
121 #[serde(rename = "q", skip_serializing_if = "Option::is_none")]
122 quantity: Option<Decimal>,
123 #[serde(rename = "Q", skip_serializing_if = "Option::is_none")]
124 quote_quantity: Option<Decimal>,
125 #[serde(rename = "w")]
126 submission_time: i64,
127 #[serde(rename = "W")]
128 expiry_time: i64,
129 #[serde(rename = "X")]
130 order_status: OrderStatus,
131 #[serde(rename = "T")]
132 timestamp: i64,
133 },
134 RfqAccepted {
135 #[serde(rename = "E")]
136 event_time: i64,
137 #[serde(rename = "R")]
138 rfq_id: u64,
139 #[serde(rename = "C", skip_serializing_if = "Option::is_none")]
140 client_id: Option<u32>,
141 #[serde(rename = "s")]
142 symbol: String,
143 #[serde(rename = "S")]
144 side: Side,
145 #[serde(rename = "q", skip_serializing_if = "Option::is_none")]
146 quantity: Option<Decimal>,
147 #[serde(rename = "Q", skip_serializing_if = "Option::is_none")]
148 quote_quantity: Option<Decimal>,
149 #[serde(rename = "w")]
150 submission_time: i64,
151 #[serde(rename = "W")]
152 expiry_time: i64,
153 #[serde(rename = "X")]
154 order_status: OrderStatus,
155 #[serde(rename = "T")]
156 timestamp: i64,
157 },
158 RfqCancelled {
159 #[serde(rename = "E")]
160 event_time: i64,
161 #[serde(rename = "R")]
162 rfq_id: u64,
163 #[serde(rename = "C", skip_serializing_if = "Option::is_none")]
164 client_id: Option<u32>,
165 #[serde(rename = "s")]
166 symbol: String,
167 #[serde(rename = "S")]
168 side: Side,
169 #[serde(rename = "q", skip_serializing_if = "Option::is_none")]
170 quantity: Option<Decimal>,
171 #[serde(rename = "Q", skip_serializing_if = "Option::is_none")]
172 quote_quantity: Option<Decimal>,
173 #[serde(rename = "w")]
174 submission_time: i64,
175 #[serde(rename = "W")]
176 expiry_time: i64,
177 #[serde(rename = "X")]
178 order_status: OrderStatus,
179 #[serde(rename = "T")]
180 timestamp: i64,
181 },
182 QuoteAccepted {
183 #[serde(rename = "E")]
184 event_time: i64,
185 #[serde(rename = "R")]
186 rfq_id: u64,
187 #[serde(rename = "u")]
188 quote_id: u64,
189 #[serde(rename = "C", skip_serializing_if = "Option::is_none")]
190 client_id: Option<u32>,
191 #[serde(rename = "s")]
192 symbol: String,
193 #[serde(rename = "p", skip_serializing_if = "Option::is_none")]
194 price: Option<Decimal>,
195 #[serde(rename = "X")]
196 order_status: OrderStatus,
197 #[serde(rename = "T")]
198 timestamp: i64,
199 },
200 QuoteCancelled {
201 #[serde(rename = "E")]
202 event_time: i64,
203 #[serde(rename = "R")]
204 rfq_id: u64,
205 #[serde(rename = "u")]
206 quote_id: u64,
207 #[serde(rename = "C", skip_serializing_if = "Option::is_none")]
208 client_id: Option<u32>,
209 #[serde(rename = "s")]
210 symbol: String,
211 #[serde(rename = "p", skip_serializing_if = "Option::is_none")]
212 price: Option<Decimal>,
213 #[serde(rename = "X")]
214 order_status: OrderStatus,
215 #[serde(rename = "T")]
216 timestamp: i64,
217 },
218 RfqCandidate {
219 #[serde(rename = "E")]
220 event_time: i64,
221 #[serde(rename = "R")]
222 rfq_id: u64,
223 #[serde(rename = "u")]
224 quote_id: u64,
225 #[serde(rename = "C", skip_serializing_if = "Option::is_none")]
226 client_id: Option<u32>,
227 #[serde(rename = "s")]
228 symbol: String,
229 #[serde(rename = "S", skip_serializing_if = "Option::is_none")]
230 side: Option<Side>,
231 #[serde(rename = "q", skip_serializing_if = "Option::is_none")]
232 quantity: Option<Decimal>,
233 #[serde(rename = "Q", skip_serializing_if = "Option::is_none")]
234 quote_quantity: Option<Decimal>,
235 #[serde(rename = "p")]
236 price: Decimal,
237 #[serde(rename = "X")]
238 order_status: OrderStatus,
239 #[serde(rename = "T")]
240 timestamp: i64,
241 },
242 RfqFilled {
243 #[serde(rename = "E")]
244 event_time: i64,
245 #[serde(rename = "R")]
246 rfq_id: u64,
247 #[serde(rename = "u")]
248 quote_id: u64,
249 #[serde(rename = "C", skip_serializing_if = "Option::is_none")]
250 client_id: Option<u32>,
251 #[serde(rename = "s")]
252 symbol: String,
253 #[serde(rename = "S")]
254 side: Side,
255 #[serde(rename = "q", skip_serializing_if = "Option::is_none")]
256 quantity: Option<Decimal>,
257 #[serde(rename = "Q", skip_serializing_if = "Option::is_none")]
258 quote_quantity: Option<Decimal>,
259 #[serde(rename = "p", skip_serializing_if = "Option::is_none")]
260 price: Option<Decimal>,
261 #[serde(rename = "X")]
262 order_status: OrderStatus,
263 #[serde(rename = "T")]
264 timestamp: i64,
265 },
266}
267
268#[derive(Debug, Clone, Serialize, Deserialize)]
269#[serde(rename_all = "camelCase")]
270pub struct Quote {
271 pub rfq_id: String,
273
274 pub quote_id: String,
276
277 pub client_id: Option<u32>,
279
280 pub bid_price: Decimal,
282
283 pub ask_price: Decimal,
285
286 pub status: OrderStatus,
288
289 pub created_at: i64,
291}
292
293#[derive(Debug, Clone, Serialize, Deserialize)]
294#[serde(rename_all = "camelCase")]
295pub struct RequestForQuote {
296 pub rfq_id: String,
297 pub client_id: Option<u32>,
298 pub symbol: String,
299 pub side: Side,
300 pub price: Option<Decimal>,
301 pub quantity: Option<Decimal>,
302 pub quote_quantity: Option<Decimal>,
303 pub submission_time: i64,
304 pub expiry_time: i64,
305 pub status: OrderStatus,
306 pub execution_mode: RfqExecutionMode,
307 pub created_at: i64,
308}
309
310impl QuotePayload {
311 pub fn new(rfq_id: String, bid_price: Decimal, ask_price: Decimal) -> Self {
312 Self {
313 rfq_id,
314 bid_price,
315 ask_price,
316 client_id: None,
317 auto_lend: None,
318 auto_lend_redeem: None,
319 auto_borrow: None,
320 auto_borrow_repay: None,
321 }
322 }
323
324 pub fn with_client_id(mut self, client_id: u32) -> Self {
325 self.client_id = Some(client_id);
326 self
327 }
328
329 pub fn with_auto_lend(mut self, auto_lend: bool) -> Self {
330 self.auto_lend = Some(auto_lend);
331 self
332 }
333
334 pub fn with_auto_lend_redeem(mut self, auto_lend_redeem: bool) -> Self {
335 self.auto_lend_redeem = Some(auto_lend_redeem);
336 self
337 }
338
339 pub fn with_auto_borrow(mut self, auto_borrow: bool) -> Self {
340 self.auto_borrow = Some(auto_borrow);
341 self
342 }
343
344 pub fn with_auto_borrow_repay(mut self, auto_borrow_repay: bool) -> Self {
345 self.auto_borrow_repay = Some(auto_borrow_repay);
346 self
347 }
348}