Skip to main content

nautilus_okx/python/
config.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Python bindings for OKX configuration.
17
18use nautilus_model::identifiers::{AccountId, TraderId};
19use pyo3::prelude::*;
20
21use crate::{
22    common::enums::{OKXEnvironment, OKXInstrumentType, OKXMarginMode, OKXRegion, OKXVipLevel},
23    config::{OKXDataClientConfig, OKXExecClientConfig},
24};
25
26#[pymethods]
27#[pyo3_stub_gen::derive::gen_stub_pymethods]
28impl OKXDataClientConfig {
29    /// Configuration for the OKX data client.
30    #[new]
31    #[pyo3(signature = (
32        instrument_types = None,
33        environment = None,
34        region = None,
35        api_key = None,
36        api_secret = None,
37        api_passphrase = None,
38        base_url_http = None,
39        base_url_ws_public = None,
40        base_url_ws_business = None,
41        proxy_url = None,
42        http_timeout_secs = None,
43        max_retries = None,
44        retry_delay_initial_ms = None,
45        retry_delay_max_ms = None,
46        update_instruments_interval_mins = None,
47        vip_level = None,
48        load_spreads = false,
49    ))]
50    #[expect(clippy::too_many_arguments)]
51    fn py_new(
52        instrument_types: Option<Vec<OKXInstrumentType>>,
53        environment: Option<OKXEnvironment>,
54        region: Option<OKXRegion>,
55        api_key: Option<String>,
56        api_secret: Option<String>,
57        api_passphrase: Option<String>,
58        base_url_http: Option<String>,
59        base_url_ws_public: Option<String>,
60        base_url_ws_business: Option<String>,
61        proxy_url: Option<String>,
62        http_timeout_secs: Option<u64>,
63        max_retries: Option<u32>,
64        retry_delay_initial_ms: Option<u64>,
65        retry_delay_max_ms: Option<u64>,
66        update_instruments_interval_mins: Option<u64>,
67        vip_level: Option<OKXVipLevel>,
68        load_spreads: bool,
69    ) -> Self {
70        let defaults = Self::default();
71        Self {
72            api_key,
73            api_secret,
74            api_passphrase,
75            instrument_types: instrument_types.unwrap_or(defaults.instrument_types),
76            contract_types: None,
77            load_spreads,
78            instrument_families: None,
79            base_url_http,
80            base_url_ws_public,
81            base_url_ws_business,
82            proxy_url,
83            environment: environment.unwrap_or(defaults.environment),
84            region: region.unwrap_or(defaults.region),
85            http_timeout_secs: http_timeout_secs.unwrap_or(defaults.http_timeout_secs),
86            max_retries: max_retries.unwrap_or(defaults.max_retries),
87            retry_delay_initial_ms: retry_delay_initial_ms
88                .unwrap_or(defaults.retry_delay_initial_ms),
89            retry_delay_max_ms: retry_delay_max_ms.unwrap_or(defaults.retry_delay_max_ms),
90            update_instruments_interval_mins: update_instruments_interval_mins
91                .unwrap_or(defaults.update_instruments_interval_mins),
92            vip_level,
93            transport_backend: defaults.transport_backend,
94        }
95    }
96
97    fn __repr__(&self) -> String {
98        format!("{self:?}")
99    }
100}
101
102#[pymethods]
103#[pyo3_stub_gen::derive::gen_stub_pymethods]
104impl OKXExecClientConfig {
105    /// Configuration for the OKX execution client.
106    #[new]
107    #[pyo3(signature = (
108        trader_id,
109        account_id,
110        instrument_types = None,
111        environment = None,
112        region = None,
113        api_key = None,
114        api_secret = None,
115        api_passphrase = None,
116        base_url_http = None,
117        base_url_ws_private = None,
118        base_url_ws_business = None,
119        proxy_url = None,
120        http_timeout_secs = None,
121        max_retries = None,
122        retry_delay_initial_ms = None,
123        retry_delay_max_ms = None,
124        margin_mode = None,
125        load_spreads = false,
126    ))]
127    #[expect(clippy::too_many_arguments)]
128    fn py_new(
129        trader_id: TraderId,
130        account_id: AccountId,
131        instrument_types: Option<Vec<OKXInstrumentType>>,
132        environment: Option<OKXEnvironment>,
133        region: Option<OKXRegion>,
134        api_key: Option<String>,
135        api_secret: Option<String>,
136        api_passphrase: Option<String>,
137        base_url_http: Option<String>,
138        base_url_ws_private: Option<String>,
139        base_url_ws_business: Option<String>,
140        proxy_url: Option<String>,
141        http_timeout_secs: Option<u64>,
142        max_retries: Option<u32>,
143        retry_delay_initial_ms: Option<u64>,
144        retry_delay_max_ms: Option<u64>,
145        margin_mode: Option<OKXMarginMode>,
146        load_spreads: bool,
147    ) -> Self {
148        let defaults = Self::default();
149        Self {
150            trader_id,
151            account_id,
152            api_key,
153            api_secret,
154            api_passphrase,
155            instrument_types: instrument_types.unwrap_or(defaults.instrument_types),
156            contract_types: None,
157            instrument_families: None,
158            base_url_http,
159            base_url_ws_private,
160            base_url_ws_business,
161            proxy_url,
162            environment: environment.unwrap_or(defaults.environment),
163            region: region.unwrap_or(defaults.region),
164            http_timeout_secs: http_timeout_secs.unwrap_or(defaults.http_timeout_secs),
165            use_fills_channel: defaults.use_fills_channel,
166            use_mm_mass_cancel: defaults.use_mm_mass_cancel,
167            max_retries: max_retries.unwrap_or(defaults.max_retries),
168            retry_delay_initial_ms: retry_delay_initial_ms
169                .unwrap_or(defaults.retry_delay_initial_ms),
170            retry_delay_max_ms: retry_delay_max_ms.unwrap_or(defaults.retry_delay_max_ms),
171            margin_mode,
172            load_spreads,
173            use_spot_margin: defaults.use_spot_margin,
174            transport_backend: defaults.transport_backend,
175        }
176    }
177
178    fn __repr__(&self) -> String {
179        format!("{self:?}")
180    }
181}
182
183#[cfg(test)]
184mod tests {
185    use rstest::rstest;
186
187    use super::*;
188
189    #[rstest]
190    fn test_data_config_py_new_load_spreads() {
191        let config = OKXDataClientConfig::py_new(
192            None, None, None, None, None, None, None, None, None, None, None, None, None, None,
193            None, None, true,
194        );
195
196        assert!(config.load_spreads);
197    }
198
199    #[rstest]
200    fn test_exec_config_py_new_load_spreads() {
201        let config = OKXExecClientConfig::py_new(
202            TraderId::from("TRADER-001"),
203            AccountId::from("OKX-001"),
204            None,
205            None,
206            None,
207            None,
208            None,
209            None,
210            None,
211            None,
212            None,
213            None,
214            None,
215            None,
216            None,
217            None,
218            None,
219            true,
220        );
221
222        assert!(config.load_spreads);
223    }
224}