Skip to main content

rust_okx/api/trade/
requests.rs

1use serde::Serialize;
2
3use crate::model::{OrderSide, OrderState, OrderType, PositionSide, RequestParams, TradeMode};
4
5/// Request body for placing an algo order.
6pub type AlgoOrderRequest = RequestParams;
7
8/// Request body for canceling an algo order.
9pub type CancelAlgoOrderRequest = RequestParams;
10
11/// Request body for amending an algo order.
12pub type AmendAlgoOrderRequest = RequestParams;
13
14/// Query parameters for pending algo orders.
15pub type AlgoOrderListRequest = RequestParams;
16
17/// Query parameters for historical algo orders.
18pub type AlgoOrderHistoryRequest = RequestParams;
19
20/// Query parameters for a single algo order.
21pub type AlgoOrderDetailsRequest = RequestParams;
22
23/// Request body for easy convert.
24pub type EasyConvertRequest = RequestParams;
25
26/// Query parameters for easy-convert history.
27pub type EasyConvertHistoryRequest = RequestParams;
28
29/// Query parameters for one-click-repay currency lists.
30pub type OneClickRepayCurrencyListRequest = RequestParams;
31
32/// Request body for one-click repay.
33pub type OneClickRepayRequest = RequestParams;
34
35/// Query parameters for one-click-repay history.
36pub type OneClickRepayHistoryRequest = RequestParams;
37
38/// A request to place an order.
39///
40/// Construct with [`PlaceOrderRequest::new`] (required fields) and chain setters
41/// for optional fields. Optional fields are omitted from the request body when
42/// unset.
43#[derive(Debug, Clone, Serialize)]
44pub struct PlaceOrderRequest {
45    #[serde(rename = "instId")]
46    inst_id: String,
47    #[serde(rename = "tdMode")]
48    td_mode: TradeMode,
49    side: OrderSide,
50    #[serde(rename = "ordType")]
51    ord_type: OrderType,
52    sz: String,
53    #[serde(skip_serializing_if = "Option::is_none")]
54    ccy: Option<String>,
55    #[serde(skip_serializing_if = "Option::is_none")]
56    tag: Option<String>,
57    #[serde(rename = "px", skip_serializing_if = "Option::is_none")]
58    px: Option<String>,
59    #[serde(rename = "posSide", skip_serializing_if = "Option::is_none")]
60    pos_side: Option<PositionSide>,
61    #[serde(rename = "clOrdId", skip_serializing_if = "Option::is_none")]
62    cl_ord_id: Option<String>,
63    #[serde(rename = "reduceOnly", skip_serializing_if = "Option::is_none")]
64    reduce_only: Option<bool>,
65    #[serde(rename = "tgtCcy", skip_serializing_if = "Option::is_none")]
66    tgt_ccy: Option<String>,
67}
68
69impl PlaceOrderRequest {
70    /// Create a new order request with the required fields.
71    pub fn new(
72        inst_id: impl Into<String>,
73        td_mode: TradeMode,
74        side: OrderSide,
75        ord_type: OrderType,
76        sz: impl Into<String>,
77    ) -> Self {
78        Self {
79            inst_id: inst_id.into(),
80            td_mode,
81            side,
82            ord_type,
83            sz: sz.into(),
84            ccy: None,
85            tag: None,
86            px: None,
87            pos_side: None,
88            cl_ord_id: None,
89            reduce_only: None,
90            tgt_ccy: None,
91        }
92    }
93
94    /// Set the order price (required for `limit`-style orders).
95    pub fn price(mut self, px: impl Into<String>) -> Self {
96        self.px = Some(px.into());
97        self
98    }
99
100    /// Set the position side (`long`/`short`/`net`).
101    pub fn position_side(mut self, pos_side: PositionSide) -> Self {
102        self.pos_side = Some(pos_side);
103        self
104    }
105
106    /// Set a client-supplied order ID.
107    pub fn client_order_id(mut self, cl_ord_id: impl Into<String>) -> Self {
108        self.cl_ord_id = Some(cl_ord_id.into());
109        self
110    }
111
112    /// Mark the order as reduce-only.
113    pub fn reduce_only(mut self, reduce_only: bool) -> Self {
114        self.reduce_only = Some(reduce_only);
115        self
116    }
117
118    /// Set the quantity unit for spot market orders (`base_ccy`/`quote_ccy`).
119    pub fn target_ccy(mut self, tgt_ccy: impl Into<String>) -> Self {
120        self.tgt_ccy = Some(tgt_ccy.into());
121        self
122    }
123
124    /// Set the margin currency.
125    pub fn currency(mut self, ccy: impl Into<String>) -> Self {
126        self.ccy = Some(ccy.into());
127        self
128    }
129
130    /// Set an order tag.
131    pub fn tag(mut self, tag: impl Into<String>) -> Self {
132        self.tag = Some(tag.into());
133        self
134    }
135}
136
137/// A request to cancel an order.
138#[derive(Debug, Clone, Serialize)]
139pub struct CancelOrderRequest {
140    #[serde(rename = "instId")]
141    inst_id: String,
142    #[serde(rename = "ordId", skip_serializing_if = "Option::is_none")]
143    ord_id: Option<String>,
144    #[serde(rename = "clOrdId", skip_serializing_if = "Option::is_none")]
145    cl_ord_id: Option<String>,
146}
147
148impl CancelOrderRequest {
149    /// Cancel by OKX order ID.
150    pub fn by_order_id(inst_id: impl Into<String>, ord_id: impl Into<String>) -> Self {
151        Self {
152            inst_id: inst_id.into(),
153            ord_id: Some(ord_id.into()),
154            cl_ord_id: None,
155        }
156    }
157
158    /// Cancel by client order ID.
159    pub fn by_client_order_id(inst_id: impl Into<String>, cl_ord_id: impl Into<String>) -> Self {
160        Self {
161            inst_id: inst_id.into(),
162            ord_id: None,
163            cl_ord_id: Some(cl_ord_id.into()),
164        }
165    }
166}
167
168/// A request to amend an order.
169#[derive(Debug, Clone, Serialize)]
170pub struct AmendOrderRequest {
171    #[serde(rename = "instId")]
172    inst_id: String,
173    #[serde(rename = "ordId", skip_serializing_if = "Option::is_none")]
174    ord_id: Option<String>,
175    #[serde(rename = "clOrdId", skip_serializing_if = "Option::is_none")]
176    cl_ord_id: Option<String>,
177    #[serde(rename = "reqId", skip_serializing_if = "Option::is_none")]
178    req_id: Option<String>,
179    #[serde(rename = "cxlOnFail", skip_serializing_if = "Option::is_none")]
180    cxl_on_fail: Option<bool>,
181    #[serde(rename = "newSz", skip_serializing_if = "Option::is_none")]
182    new_sz: Option<String>,
183    #[serde(rename = "newPx", skip_serializing_if = "Option::is_none")]
184    new_px: Option<String>,
185}
186
187impl AmendOrderRequest {
188    /// Create an amend-order request for an instrument.
189    pub fn new(inst_id: impl Into<String>) -> Self {
190        Self {
191            inst_id: inst_id.into(),
192            ord_id: None,
193            cl_ord_id: None,
194            req_id: None,
195            cxl_on_fail: None,
196            new_sz: None,
197            new_px: None,
198        }
199    }
200
201    /// Set the OKX order ID.
202    pub fn order_id(mut self, ord_id: impl Into<String>) -> Self {
203        self.ord_id = Some(ord_id.into());
204        self
205    }
206
207    /// Set the client order ID.
208    pub fn client_order_id(mut self, cl_ord_id: impl Into<String>) -> Self {
209        self.cl_ord_id = Some(cl_ord_id.into());
210        self
211    }
212
213    /// Set a request ID.
214    pub fn request_id(mut self, req_id: impl Into<String>) -> Self {
215        self.req_id = Some(req_id.into());
216        self
217    }
218
219    /// Set whether OKX should cancel the order if amendment fails.
220    pub fn cancel_on_fail(mut self, cxl_on_fail: bool) -> Self {
221        self.cxl_on_fail = Some(cxl_on_fail);
222        self
223    }
224
225    /// Set the new order size.
226    pub fn new_size(mut self, new_sz: impl Into<String>) -> Self {
227        self.new_sz = Some(new_sz.into());
228        self
229    }
230
231    /// Set the new order price.
232    pub fn new_price(mut self, new_px: impl Into<String>) -> Self {
233        self.new_px = Some(new_px.into());
234        self
235    }
236}
237
238/// A request to close positions.
239#[derive(Debug, Clone, Serialize)]
240pub struct ClosePositionRequest {
241    #[serde(rename = "instId")]
242    inst_id: String,
243    #[serde(rename = "mgnMode")]
244    mgn_mode: TradeMode,
245    #[serde(rename = "posSide", skip_serializing_if = "Option::is_none")]
246    pos_side: Option<PositionSide>,
247    #[serde(skip_serializing_if = "Option::is_none")]
248    ccy: Option<String>,
249    #[serde(rename = "autoCxl", skip_serializing_if = "Option::is_none")]
250    auto_cancel: Option<bool>,
251    #[serde(rename = "clOrdId", skip_serializing_if = "Option::is_none")]
252    cl_ord_id: Option<String>,
253    #[serde(skip_serializing_if = "Option::is_none")]
254    tag: Option<String>,
255}
256
257impl ClosePositionRequest {
258    /// Create a close-position request.
259    pub fn new(inst_id: impl Into<String>, mgn_mode: TradeMode) -> Self {
260        Self {
261            inst_id: inst_id.into(),
262            mgn_mode,
263            pos_side: None,
264            ccy: None,
265            auto_cancel: None,
266            cl_ord_id: None,
267            tag: None,
268        }
269    }
270
271    /// Set the position side.
272    pub fn position_side(mut self, pos_side: PositionSide) -> Self {
273        self.pos_side = Some(pos_side);
274        self
275    }
276
277    /// Set the margin currency.
278    pub fn currency(mut self, ccy: impl Into<String>) -> Self {
279        self.ccy = Some(ccy.into());
280        self
281    }
282
283    /// Set whether pending orders should be canceled automatically.
284    pub fn auto_cancel(mut self, auto_cancel: bool) -> Self {
285        self.auto_cancel = Some(auto_cancel);
286        self
287    }
288
289    /// Set the client order ID.
290    pub fn client_order_id(mut self, cl_ord_id: impl Into<String>) -> Self {
291        self.cl_ord_id = Some(cl_ord_id.into());
292        self
293    }
294
295    /// Set an order tag.
296    pub fn tag(mut self, tag: impl Into<String>) -> Self {
297        self.tag = Some(tag.into());
298        self
299    }
300}
301
302/// Query parameters for pending order lists.
303#[derive(Debug, Clone, Default, Serialize)]
304pub struct OrderListRequest {
305    #[serde(rename = "instType", skip_serializing_if = "Option::is_none")]
306    inst_type: Option<crate::model::InstType>,
307    #[serde(rename = "uly", skip_serializing_if = "Option::is_none")]
308    underlying: Option<String>,
309    #[serde(rename = "instId", skip_serializing_if = "Option::is_none")]
310    inst_id: Option<String>,
311    #[serde(rename = "ordType", skip_serializing_if = "Option::is_none")]
312    ord_type: Option<OrderType>,
313    #[serde(skip_serializing_if = "Option::is_none")]
314    state: Option<OrderState>,
315    #[serde(skip_serializing_if = "Option::is_none")]
316    after: Option<String>,
317    #[serde(skip_serializing_if = "Option::is_none")]
318    before: Option<String>,
319    #[serde(skip_serializing_if = "Option::is_none")]
320    limit: Option<u32>,
321    #[serde(rename = "instFamily", skip_serializing_if = "Option::is_none")]
322    inst_family: Option<String>,
323}
324
325impl OrderListRequest {
326    /// Create an empty order-list query.
327    pub fn new() -> Self {
328        Self::default()
329    }
330
331    /// Set the instrument type filter.
332    pub fn inst_type(mut self, inst_type: crate::model::InstType) -> Self {
333        self.inst_type = Some(inst_type);
334        self
335    }
336
337    /// Set the underlying filter.
338    pub fn underlying(mut self, underlying: impl Into<String>) -> Self {
339        self.underlying = Some(underlying.into());
340        self
341    }
342
343    /// Set the instrument ID filter.
344    pub fn inst_id(mut self, inst_id: impl Into<String>) -> Self {
345        self.inst_id = Some(inst_id.into());
346        self
347    }
348
349    /// Set the order type filter.
350    pub fn order_type(mut self, ord_type: OrderType) -> Self {
351        self.ord_type = Some(ord_type);
352        self
353    }
354
355    /// Set the order state filter.
356    pub fn state(mut self, state: OrderState) -> Self {
357        self.state = Some(state);
358        self
359    }
360
361    /// Return records after this pagination cursor.
362    pub fn after(mut self, after: impl Into<String>) -> Self {
363        self.after = Some(after.into());
364        self
365    }
366
367    /// Return records before this pagination cursor.
368    pub fn before(mut self, before: impl Into<String>) -> Self {
369        self.before = Some(before.into());
370        self
371    }
372
373    /// Set the maximum number of rows to return.
374    pub fn limit(mut self, limit: u32) -> Self {
375        self.limit = Some(limit);
376        self
377    }
378
379    /// Set the instrument family filter.
380    pub fn inst_family(mut self, inst_family: impl Into<String>) -> Self {
381        self.inst_family = Some(inst_family.into());
382        self
383    }
384}
385
386/// Query parameters for order history.
387#[derive(Debug, Clone, Serialize)]
388pub struct OrderHistoryRequest {
389    #[serde(flatten)]
390    base: OrderListRequest,
391    #[serde(skip_serializing_if = "Option::is_none")]
392    begin: Option<String>,
393    #[serde(skip_serializing_if = "Option::is_none")]
394    end: Option<String>,
395}
396
397impl OrderHistoryRequest {
398    /// Create an order-history query with the required instrument type.
399    pub fn new(inst_type: crate::model::InstType) -> Self {
400        Self {
401            base: OrderListRequest::new().inst_type(inst_type),
402            begin: None,
403            end: None,
404        }
405    }
406
407    /// Set the common order-list filters.
408    pub fn filters(mut self, base: OrderListRequest) -> Self {
409        self.base = base;
410        self
411    }
412
413    /// Set the begin timestamp.
414    pub fn begin(mut self, begin: impl Into<String>) -> Self {
415        self.begin = Some(begin.into());
416        self
417    }
418
419    /// Set the end timestamp.
420    pub fn end(mut self, end: impl Into<String>) -> Self {
421        self.end = Some(end.into());
422        self
423    }
424}
425
426/// Query parameters for fills.
427#[derive(Debug, Clone, Default, Serialize)]
428pub struct FillsRequest {
429    #[serde(rename = "instType", skip_serializing_if = "Option::is_none")]
430    inst_type: Option<crate::model::InstType>,
431    #[serde(rename = "uly", skip_serializing_if = "Option::is_none")]
432    underlying: Option<String>,
433    #[serde(rename = "instId", skip_serializing_if = "Option::is_none")]
434    inst_id: Option<String>,
435    #[serde(rename = "ordId", skip_serializing_if = "Option::is_none")]
436    ord_id: Option<String>,
437    #[serde(skip_serializing_if = "Option::is_none")]
438    after: Option<String>,
439    #[serde(skip_serializing_if = "Option::is_none")]
440    before: Option<String>,
441    #[serde(skip_serializing_if = "Option::is_none")]
442    begin: Option<String>,
443    #[serde(skip_serializing_if = "Option::is_none")]
444    end: Option<String>,
445    #[serde(skip_serializing_if = "Option::is_none")]
446    limit: Option<u32>,
447    #[serde(rename = "instFamily", skip_serializing_if = "Option::is_none")]
448    inst_family: Option<String>,
449}
450
451impl FillsRequest {
452    /// Create an empty fills query.
453    pub fn new() -> Self {
454        Self::default()
455    }
456
457    /// Set the instrument type filter.
458    pub fn inst_type(mut self, inst_type: crate::model::InstType) -> Self {
459        self.inst_type = Some(inst_type);
460        self
461    }
462
463    /// Set the underlying filter.
464    pub fn underlying(mut self, underlying: impl Into<String>) -> Self {
465        self.underlying = Some(underlying.into());
466        self
467    }
468
469    /// Set the instrument ID filter.
470    pub fn inst_id(mut self, inst_id: impl Into<String>) -> Self {
471        self.inst_id = Some(inst_id.into());
472        self
473    }
474
475    /// Set the order ID filter.
476    pub fn order_id(mut self, ord_id: impl Into<String>) -> Self {
477        self.ord_id = Some(ord_id.into());
478        self
479    }
480
481    /// Return records after this pagination cursor.
482    pub fn after(mut self, after: impl Into<String>) -> Self {
483        self.after = Some(after.into());
484        self
485    }
486
487    /// Return records before this pagination cursor.
488    pub fn before(mut self, before: impl Into<String>) -> Self {
489        self.before = Some(before.into());
490        self
491    }
492
493    /// Set the begin timestamp.
494    pub fn begin(mut self, begin: impl Into<String>) -> Self {
495        self.begin = Some(begin.into());
496        self
497    }
498
499    /// Set the end timestamp.
500    pub fn end(mut self, end: impl Into<String>) -> Self {
501        self.end = Some(end.into());
502        self
503    }
504
505    /// Set the maximum number of rows to return.
506    pub fn limit(mut self, limit: u32) -> Self {
507        self.limit = Some(limit);
508        self
509    }
510
511    /// Set the instrument family filter.
512    pub fn inst_family(mut self, inst_family: impl Into<String>) -> Self {
513        self.inst_family = Some(inst_family.into());
514        self
515    }
516}