1use nautilus_model::identifiers::AccountId;
19use nautilus_network::websocket::TransportBackend;
20use pyo3::prelude::*;
21
22use crate::{
23 common::enums::{OKXEnvironment, OKXInstrumentType, OKXMarginMode, OKXRegion, OKXVipLevel},
24 config::{OKXDataClientConfig, OKXExecutionClientConfig},
25};
26
27#[pymethods]
28#[pyo3_stub_gen::derive::gen_stub_pymethods]
29impl OKXDataClientConfig {
30 #[new]
32 #[pyo3(signature = (
33 instrument_types = None,
34 environment = None,
35 region = None,
36 api_key = None,
37 api_secret = None,
38 api_passphrase = None,
39 base_url_http = None,
40 base_url_ws_public = None,
41 base_url_ws_business = None,
42 proxy_url = None,
43 http_timeout_secs = None,
44 max_retries = None,
45 retry_delay_initial_ms = None,
46 retry_delay_max_ms = None,
47 update_instruments_interval_mins = None,
48 book_stale_check_interval_secs = None,
49 book_stale_threshold_secs = None,
50 book_snapshot_timeout_secs = None,
51 vip_level = None,
52 load_spreads = false,
53 transport_backend = None,
54 instrument_families = None,
55 ))]
56 #[expect(clippy::too_many_arguments)]
57 fn py_new(
58 instrument_types: Option<Vec<OKXInstrumentType>>,
59 environment: Option<OKXEnvironment>,
60 region: Option<OKXRegion>,
61 api_key: Option<String>,
62 api_secret: Option<String>,
63 api_passphrase: Option<String>,
64 base_url_http: Option<String>,
65 base_url_ws_public: Option<String>,
66 base_url_ws_business: Option<String>,
67 proxy_url: Option<String>,
68 http_timeout_secs: Option<u64>,
69 max_retries: Option<u32>,
70 retry_delay_initial_ms: Option<u64>,
71 retry_delay_max_ms: Option<u64>,
72 update_instruments_interval_mins: Option<u64>,
73 book_stale_check_interval_secs: Option<u64>,
74 book_stale_threshold_secs: Option<u64>,
75 book_snapshot_timeout_secs: Option<u64>,
76 vip_level: Option<OKXVipLevel>,
77 load_spreads: bool,
78 transport_backend: Option<TransportBackend>,
79 instrument_families: Option<Vec<String>>,
80 ) -> Self {
81 let defaults = Self::default();
82 Self {
83 api_key,
84 api_secret,
85 api_passphrase,
86 instrument_types: instrument_types.unwrap_or(defaults.instrument_types),
87 contract_types: None,
88 load_spreads,
89 instrument_families,
90 base_url_http,
91 base_url_ws_public,
92 base_url_ws_business,
93 proxy_url,
94 environment: environment.unwrap_or(defaults.environment),
95 region: region.unwrap_or(defaults.region),
96 http_timeout_secs: http_timeout_secs.unwrap_or(defaults.http_timeout_secs),
97 max_retries: max_retries.unwrap_or(defaults.max_retries),
98 retry_delay_initial_ms: retry_delay_initial_ms
99 .unwrap_or(defaults.retry_delay_initial_ms),
100 retry_delay_max_ms: retry_delay_max_ms.unwrap_or(defaults.retry_delay_max_ms),
101 update_instruments_interval_mins: update_instruments_interval_mins
102 .unwrap_or(defaults.update_instruments_interval_mins),
103 book_stale_check_interval_secs: book_stale_check_interval_secs
104 .unwrap_or(defaults.book_stale_check_interval_secs),
105 book_stale_threshold_secs: book_stale_threshold_secs
106 .unwrap_or(defaults.book_stale_threshold_secs),
107 book_snapshot_timeout_secs: book_snapshot_timeout_secs
108 .unwrap_or(defaults.book_snapshot_timeout_secs),
109 vip_level,
110 transport_backend: transport_backend.unwrap_or(defaults.transport_backend),
111 }
112 }
113
114 #[getter]
115 const fn has_proxy_url(&self) -> bool {
116 self.proxy_url.is_some()
117 }
118
119 fn __repr__(&self) -> String {
120 stringify!(OKXDataClientConfig).to_string()
121 }
122}
123
124#[pymethods]
125#[pyo3_stub_gen::derive::gen_stub_pymethods]
126impl OKXExecutionClientConfig {
127 #[new]
129 #[pyo3(signature = (
130 account_id,
131 instrument_types = None,
132 environment = None,
133 region = None,
134 api_key = None,
135 api_secret = None,
136 api_passphrase = None,
137 base_url_http = None,
138 base_url_ws_private = None,
139 base_url_ws_business = None,
140 proxy_url = None,
141 http_timeout_secs = None,
142 max_retries = None,
143 retry_delay_initial_ms = None,
144 retry_delay_max_ms = None,
145 margin_mode = None,
146 load_spreads = false,
147 auth_timeout_secs = None,
148 transport_backend = None,
149 ))]
150 #[expect(clippy::too_many_arguments)]
151 fn py_new(
152 account_id: AccountId,
153 instrument_types: Option<Vec<OKXInstrumentType>>,
154 environment: Option<OKXEnvironment>,
155 region: Option<OKXRegion>,
156 api_key: Option<String>,
157 api_secret: Option<String>,
158 api_passphrase: Option<String>,
159 base_url_http: Option<String>,
160 base_url_ws_private: Option<String>,
161 base_url_ws_business: Option<String>,
162 proxy_url: Option<String>,
163 http_timeout_secs: Option<u64>,
164 max_retries: Option<u32>,
165 retry_delay_initial_ms: Option<u64>,
166 retry_delay_max_ms: Option<u64>,
167 margin_mode: Option<OKXMarginMode>,
168 load_spreads: bool,
169 auth_timeout_secs: Option<u64>,
170 transport_backend: Option<TransportBackend>,
171 ) -> Self {
172 let defaults = Self::default();
173 Self {
174 account_id,
175 api_key,
176 api_secret,
177 api_passphrase,
178 instrument_types: instrument_types.unwrap_or(defaults.instrument_types),
179 contract_types: None,
180 instrument_families: None,
181 base_url_http,
182 base_url_ws_private,
183 base_url_ws_business,
184 proxy_url,
185 environment: environment.unwrap_or(defaults.environment),
186 region: region.unwrap_or(defaults.region),
187 http_timeout_secs: http_timeout_secs.unwrap_or(defaults.http_timeout_secs),
188 use_mm_mass_cancel: defaults.use_mm_mass_cancel,
189 max_retries: max_retries.unwrap_or(defaults.max_retries),
190 retry_delay_initial_ms: retry_delay_initial_ms
191 .unwrap_or(defaults.retry_delay_initial_ms),
192 retry_delay_max_ms: retry_delay_max_ms.unwrap_or(defaults.retry_delay_max_ms),
193 margin_mode,
194 load_spreads,
195 use_spot_margin: defaults.use_spot_margin,
196 auth_timeout_secs,
197 transport_backend: transport_backend.unwrap_or(defaults.transport_backend),
198 }
199 }
200
201 #[getter]
202 const fn has_proxy_url(&self) -> bool {
203 self.proxy_url.is_some()
204 }
205
206 fn __repr__(&self) -> String {
207 stringify!(OKXExecutionClientConfig).to_string()
208 }
209}
210
211#[cfg(test)]
212mod tests {
213 use rstest::rstest;
214
215 use super::*;
216
217 #[rstest]
218 fn test_data_config_py_new() {
219 let config = OKXDataClientConfig::py_new(
220 None,
221 None,
222 None,
223 None,
224 None,
225 None,
226 None,
227 None,
228 None,
229 None,
230 None,
231 None,
232 None,
233 None,
234 None,
235 None,
236 None,
237 None,
238 None,
239 true,
240 None,
241 Some(vec!["BTC-USD".to_string()]),
242 );
243
244 assert_eq!(
245 config.instrument_families,
246 Some(vec!["BTC-USD".to_string()]),
247 );
248 assert!(config.load_spreads);
249 assert_eq!(config.book_stale_check_interval_secs, 5);
250 assert_eq!(config.book_stale_threshold_secs, 30);
251 assert_eq!(config.book_snapshot_timeout_secs, 3);
252 }
253
254 #[rstest]
255 fn test_exec_config_py_new_load_spreads() {
256 let config = OKXExecutionClientConfig::py_new(
257 AccountId::from("OKX-001"),
258 None,
259 None,
260 None,
261 None,
262 None,
263 None,
264 None,
265 None,
266 None,
267 None,
268 None,
269 None,
270 None,
271 None,
272 None,
273 true,
274 None,
275 None,
276 );
277
278 assert!(config.load_spreads);
279 assert_eq!(config.auth_timeout_secs, None);
280 }
281}