bpx_api_types/
rfq.rs

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}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct RequestForQuoteStream {
70    pub stream: String,
71    pub data: RequestForQuoteUpdate,
72}
73
74/// RequestForQuote updates received from the websocket.
75#[derive(Debug, Clone, Serialize, Deserialize)]
76#[serde(tag = "e", rename_all = "camelCase")] // Discriminates based on "e" field
77pub enum RequestForQuoteUpdate {
78    RfqActive {
79        #[serde(rename = "E")]
80        event_time: i64,
81        #[serde(rename = "R")]
82        rfq_id: u64,
83        #[serde(rename = "C", skip_serializing_if = "Option::is_none")]
84        client_id: Option<u32>,
85        #[serde(rename = "s")]
86        symbol: String,
87        #[serde(rename = "q", skip_serializing_if = "Option::is_none")]
88        quantity: Option<Decimal>,
89        #[serde(rename = "Q", skip_serializing_if = "Option::is_none")]
90        quote_quantity: Option<Decimal>,
91        #[serde(rename = "w")]
92        submission_time: i64,
93        #[serde(rename = "W")]
94        expiry_time: i64,
95        #[serde(rename = "X")]
96        order_status: OrderStatus,
97        #[serde(rename = "T")]
98        timestamp: i64,
99    },
100    RfqRefreshed {
101        #[serde(rename = "E")]
102        event_time: i64,
103        #[serde(rename = "R")]
104        rfq_id: u64,
105        #[serde(rename = "C", skip_serializing_if = "Option::is_none")]
106        client_id: Option<u32>,
107        #[serde(rename = "s")]
108        symbol: String,
109        #[serde(rename = "S")]
110        side: Side,
111        #[serde(rename = "q", skip_serializing_if = "Option::is_none")]
112        quantity: Option<Decimal>,
113        #[serde(rename = "Q", skip_serializing_if = "Option::is_none")]
114        quote_quantity: Option<Decimal>,
115        #[serde(rename = "w")]
116        submission_time: i64,
117        #[serde(rename = "W")]
118        expiry_time: i64,
119        #[serde(rename = "X")]
120        order_status: OrderStatus,
121        #[serde(rename = "T")]
122        timestamp: i64,
123    },
124    RfqAccepted {
125        #[serde(rename = "E")]
126        event_time: i64,
127        #[serde(rename = "R")]
128        rfq_id: u64,
129        #[serde(rename = "C", skip_serializing_if = "Option::is_none")]
130        client_id: Option<u32>,
131        #[serde(rename = "s")]
132        symbol: String,
133        #[serde(rename = "S")]
134        side: Side,
135        #[serde(rename = "q", skip_serializing_if = "Option::is_none")]
136        quantity: Option<Decimal>,
137        #[serde(rename = "Q", skip_serializing_if = "Option::is_none")]
138        quote_quantity: Option<Decimal>,
139        #[serde(rename = "w")]
140        submission_time: i64,
141        #[serde(rename = "W")]
142        expiry_time: i64,
143        #[serde(rename = "X")]
144        order_status: OrderStatus,
145        #[serde(rename = "T")]
146        timestamp: i64,
147    },
148    RfqCancelled {
149        #[serde(rename = "E")]
150        event_time: i64,
151        #[serde(rename = "R")]
152        rfq_id: u64,
153        #[serde(rename = "C", skip_serializing_if = "Option::is_none")]
154        client_id: Option<u32>,
155        #[serde(rename = "s")]
156        symbol: String,
157        #[serde(rename = "S")]
158        side: Side,
159        #[serde(rename = "q", skip_serializing_if = "Option::is_none")]
160        quantity: Option<Decimal>,
161        #[serde(rename = "Q", skip_serializing_if = "Option::is_none")]
162        quote_quantity: Option<Decimal>,
163        #[serde(rename = "w")]
164        submission_time: i64,
165        #[serde(rename = "W")]
166        expiry_time: i64,
167        #[serde(rename = "X")]
168        order_status: OrderStatus,
169        #[serde(rename = "T")]
170        timestamp: i64,
171    },
172    QuoteAccepted {
173        #[serde(rename = "E")]
174        event_time: i64,
175        #[serde(rename = "R")]
176        rfq_id: u64,
177        #[serde(rename = "u")]
178        quote_id: u64,
179        #[serde(rename = "C", skip_serializing_if = "Option::is_none")]
180        client_id: Option<u32>,
181        #[serde(rename = "s")]
182        symbol: String,
183        #[serde(rename = "p", skip_serializing_if = "Option::is_none")]
184        price: Option<Decimal>,
185        #[serde(rename = "X")]
186        order_status: OrderStatus,
187        #[serde(rename = "T")]
188        timestamp: i64,
189    },
190    QuoteCancelled {
191        #[serde(rename = "E")]
192        event_time: i64,
193        #[serde(rename = "R")]
194        rfq_id: u64,
195        #[serde(rename = "u")]
196        quote_id: u64,
197        #[serde(rename = "C", skip_serializing_if = "Option::is_none")]
198        client_id: Option<u32>,
199        #[serde(rename = "s")]
200        symbol: String,
201        #[serde(rename = "p", skip_serializing_if = "Option::is_none")]
202        price: Option<Decimal>,
203        #[serde(rename = "X")]
204        order_status: OrderStatus,
205        #[serde(rename = "T")]
206        timestamp: i64,
207    },
208    RfqCandidate {
209        #[serde(rename = "E")]
210        event_time: i64,
211        #[serde(rename = "R")]
212        rfq_id: u64,
213        #[serde(rename = "u")]
214        quote_id: u64,
215        #[serde(rename = "C", skip_serializing_if = "Option::is_none")]
216        client_id: Option<u32>,
217        #[serde(rename = "s")]
218        symbol: String,
219        #[serde(rename = "S", skip_serializing_if = "Option::is_none")]
220        side: Option<Side>,
221        #[serde(rename = "q", skip_serializing_if = "Option::is_none")]
222        quantity: Option<Decimal>,
223        #[serde(rename = "Q", skip_serializing_if = "Option::is_none")]
224        quote_quantity: Option<Decimal>,
225        #[serde(rename = "p")]
226        price: Decimal,
227        #[serde(rename = "X")]
228        order_status: OrderStatus,
229        #[serde(rename = "T")]
230        timestamp: i64,
231    },
232    RfqFilled {
233        #[serde(rename = "E")]
234        event_time: i64,
235        #[serde(rename = "R")]
236        rfq_id: u64,
237        #[serde(rename = "u")]
238        quote_id: u64,
239        #[serde(rename = "C", skip_serializing_if = "Option::is_none")]
240        client_id: Option<u32>,
241        #[serde(rename = "s")]
242        symbol: String,
243        #[serde(rename = "S")]
244        side: Side,
245        #[serde(rename = "q", skip_serializing_if = "Option::is_none")]
246        quantity: Option<Decimal>,
247        #[serde(rename = "Q", skip_serializing_if = "Option::is_none")]
248        quote_quantity: Option<Decimal>,
249        #[serde(rename = "p", skip_serializing_if = "Option::is_none")]
250        price: Option<Decimal>,
251        #[serde(rename = "X")]
252        order_status: OrderStatus,
253        #[serde(rename = "T")]
254        timestamp: i64,
255    },
256}
257
258#[derive(Debug, Clone, Serialize, Deserialize)]
259#[serde(rename_all = "camelCase")]
260pub struct Quote {
261    /// Unique RFQ order ID assigned by the matching engine.
262    pub rfq_id: String,
263
264    /// Unique RFQ quote ID, assigned by the matching engine.
265    pub quote_id: String,
266
267    /// Custom RFQ quote ID assigned by the maker (optionally)
268    pub client_id: Option<u32>,
269
270    /// Quote Bid Price.
271    pub bid_price: Decimal,
272
273    /// Quote Ask Price.
274    pub ask_price: Decimal,
275
276    /// Status.
277    pub status: OrderStatus,
278
279    /// Time the quote was created.
280    pub created_at: i64,
281}
282
283#[derive(Debug, Clone, Serialize, Deserialize)]
284#[serde(rename_all = "camelCase")]
285pub struct RequestForQuote {
286    pub rfq_id: String,
287    pub client_id: Option<u32>,
288    pub symbol: String,
289    pub side: Side,
290    pub price: Option<Decimal>,
291    pub quantity: Option<Decimal>,
292    pub quote_quantity: Option<Decimal>,
293    pub submission_time: i64,
294    pub expiry_time: i64,
295    pub status: OrderStatus,
296    pub execution_mode: RfqExecutionMode,
297    pub created_at: i64,
298}