Skip to main content

rust_okx/api/public_data/requests/
edge.rs

1use serde::Serialize;
2
3/// Query parameters for `GET /api/v5/public/opt-summary`.
4#[derive(Debug, Clone, Serialize)]
5pub struct OptionSummaryRequest {
6    #[serde(rename = "instFamily")]
7    inst_family: String,
8    #[serde(rename = "expTime", skip_serializing_if = "Option::is_none")]
9    exp_time: Option<String>,
10}
11
12impl OptionSummaryRequest {
13    /// Create a query for an option instrument family, such as `BTC-USD`.
14    pub fn new(inst_family: impl Into<String>) -> Self {
15        Self {
16            inst_family: inst_family.into(),
17            exp_time: None,
18        }
19    }
20
21    /// Restrict the result to one expiration timestamp in milliseconds.
22    pub fn expiration(mut self, value: impl Into<String>) -> Self {
23        self.exp_time = Some(value.into());
24        self
25    }
26}
27
28/// Empty query for `GET /api/v5/public/interest-rate-loan-quota`.
29#[derive(Debug, Clone, Default, Serialize)]
30pub struct InterestRateLoanQuotaRequest {}
31
32impl InterestRateLoanQuotaRequest {
33    /// Create the parameterless query.
34    pub fn new() -> Self {
35        Self::default()
36    }
37}
38
39/// Query parameters for `GET /api/v5/public/instrument-tick-bands`.
40#[derive(Debug, Clone, Serialize)]
41pub struct InstrumentTickBandsRequest {
42    #[serde(rename = "instType")]
43    inst_type: String,
44}
45
46impl InstrumentTickBandsRequest {
47    /// Create a tick-band query for `FUTURES` or `OPTION` instruments.
48    pub fn new(inst_type: impl Into<String>) -> Self {
49        Self {
50            inst_type: inst_type.into(),
51        }
52    }
53}
54
55/// Query parameters for `GET /api/v5/public/underlying`.
56#[derive(Debug, Clone, Serialize)]
57pub struct UnderlyingRequest {
58    #[serde(rename = "instType")]
59    inst_type: String,
60}
61
62impl UnderlyingRequest {
63    /// Create a query for `SWAP`, `FUTURES`, or `OPTION` instruments.
64    pub fn new(inst_type: impl Into<String>) -> Self {
65        Self {
66            inst_type: inst_type.into(),
67        }
68    }
69}
70
71/// Query parameters for `GET /api/v5/public/option-trades`.
72#[derive(Debug, Clone, Default, Serialize)]
73pub struct PublicOptionTradesRequest {
74    #[serde(rename = "instId", skip_serializing_if = "Option::is_none")]
75    inst_id: Option<String>,
76    #[serde(rename = "instFamily", skip_serializing_if = "Option::is_none")]
77    inst_family: Option<String>,
78    #[serde(rename = "optType", skip_serializing_if = "Option::is_none")]
79    option_type: Option<String>,
80}
81
82impl PublicOptionTradesRequest {
83    /// Create an unfiltered option-trades query.
84    pub fn new() -> Self {
85        Self::default()
86    }
87
88    /// Restrict results to one option instrument.
89    pub fn inst_id(mut self, value: impl Into<String>) -> Self {
90        self.inst_id = Some(value.into());
91        self
92    }
93
94    /// Restrict results to one option instrument family.
95    pub fn inst_family(mut self, value: impl Into<String>) -> Self {
96        self.inst_family = Some(value.into());
97        self
98    }
99
100    /// Restrict results to calls (`C`) or puts (`P`).
101    pub fn option_type(mut self, value: impl Into<String>) -> Self {
102        self.option_type = Some(value.into());
103        self
104    }
105}
106
107/// Query parameters for `GET /api/v5/public/market-data-history`.
108#[derive(Debug, Clone, Default, Serialize)]
109pub struct MarketDataHistoryRequest {
110    #[serde(skip_serializing_if = "Option::is_none")]
111    module: Option<String>,
112    #[serde(rename = "instType", skip_serializing_if = "Option::is_none")]
113    inst_type: Option<String>,
114    #[serde(rename = "instIdList", skip_serializing_if = "Option::is_none")]
115    inst_id_list: Option<String>,
116    #[serde(rename = "dateAggrType", skip_serializing_if = "Option::is_none")]
117    date_aggr_type: Option<String>,
118    #[serde(skip_serializing_if = "Option::is_none")]
119    begin: Option<String>,
120    #[serde(skip_serializing_if = "Option::is_none")]
121    end: Option<String>,
122}
123
124impl MarketDataHistoryRequest {
125    /// Create an empty market-data-history query.
126    pub fn new() -> Self {
127        Self::default()
128    }
129
130    /// Set the OKX market-data module identifier.
131    pub fn module(mut self, value: impl Into<String>) -> Self {
132        self.module = Some(value.into());
133        self
134    }
135
136    /// Set the instrument type filter.
137    pub fn inst_type(mut self, value: impl Into<String>) -> Self {
138        self.inst_type = Some(value.into());
139        self
140    }
141
142    /// Set a comma-separated instrument-ID list.
143    pub fn inst_id_list(mut self, value: impl Into<String>) -> Self {
144        self.inst_id_list = Some(value.into());
145        self
146    }
147
148    /// Set the documented date aggregation type.
149    pub fn date_aggregation(mut self, value: impl Into<String>) -> Self {
150        self.date_aggr_type = Some(value.into());
151        self
152    }
153
154    /// Set the inclusive begin timestamp in milliseconds.
155    pub fn begin(mut self, value: impl Into<String>) -> Self {
156        self.begin = Some(value.into());
157        self
158    }
159
160    /// Set the inclusive end timestamp in milliseconds.
161    pub fn end(mut self, value: impl Into<String>) -> Self {
162        self.end = Some(value.into());
163        self
164    }
165}
166
167#[cfg(test)]
168mod tests {
169    use super::*;
170
171    #[test]
172    fn market_history_uses_okx_field_names() {
173        let request = MarketDataHistoryRequest::new()
174            .module("2")
175            .inst_type("SPOT")
176            .inst_id_list("BTC-USDT")
177            .date_aggregation("daily");
178        let value = serde_json::to_value(request).unwrap();
179        assert_eq!(value["instType"], "SPOT");
180        assert_eq!(value["instIdList"], "BTC-USDT");
181        assert_eq!(value["dateAggrType"], "daily");
182    }
183}