1use nautilus_model::identifiers::{AccountId, TraderId};
19use nautilus_network::websocket::TransportBackend;
20
21use crate::common::{
22 credential::credential_env_vars,
23 enums::{OKXContractType, OKXEnvironment, OKXInstrumentType, OKXMarginMode, OKXVipLevel},
24 urls::{
25 get_http_base_url, get_ws_base_url_business, get_ws_base_url_private,
26 get_ws_base_url_public,
27 },
28};
29
30#[derive(Clone, Debug, bon::Builder)]
32#[cfg_attr(
33 feature = "python",
34 pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.okx", from_py_object)
35)]
36#[cfg_attr(
37 feature = "python",
38 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.okx")
39)]
40pub struct OKXDataClientConfig {
41 pub api_key: Option<String>,
43 pub api_secret: Option<String>,
45 pub api_passphrase: Option<String>,
47 #[builder(default = vec![OKXInstrumentType::Spot])]
49 pub instrument_types: Vec<OKXInstrumentType>,
50 pub contract_types: Option<Vec<OKXContractType>>,
52 pub instrument_families: Option<Vec<String>>,
55 pub base_url_http: Option<String>,
57 pub base_url_ws_public: Option<String>,
59 pub base_url_ws_business: Option<String>,
61 pub proxy_url: Option<String>,
63 #[builder(default)]
65 pub environment: OKXEnvironment,
66 #[builder(default = 60)]
68 pub http_timeout_secs: u64,
69 #[builder(default = 3)]
71 pub max_retries: u32,
72 #[builder(default = 1_000)]
74 pub retry_delay_initial_ms: u64,
75 #[builder(default = 10_000)]
77 pub retry_delay_max_ms: u64,
78 #[builder(default = 60)]
80 pub update_instruments_interval_mins: u64,
81 pub vip_level: Option<OKXVipLevel>,
83 #[builder(default)]
85 pub transport_backend: TransportBackend,
86}
87
88impl Default for OKXDataClientConfig {
89 fn default() -> Self {
90 Self::builder().build()
91 }
92}
93
94impl OKXDataClientConfig {
95 #[must_use]
97 pub fn new() -> Self {
98 Self::default()
99 }
100
101 #[must_use]
103 pub fn has_api_credentials(&self) -> bool {
104 let (key_var, secret_var, passphrase_var) = credential_env_vars();
105 let has_key = self.api_key.is_some() || std::env::var(key_var).is_ok();
106 let has_secret = self.api_secret.is_some() || std::env::var(secret_var).is_ok();
107 let has_passphrase = self.api_passphrase.is_some() || std::env::var(passphrase_var).is_ok();
108 has_key && has_secret && has_passphrase
109 }
110
111 #[must_use]
113 pub fn http_base_url(&self) -> String {
114 self.base_url_http
115 .clone()
116 .unwrap_or_else(|| get_http_base_url().to_string())
117 }
118
119 #[must_use]
121 pub fn ws_public_url(&self) -> String {
122 self.base_url_ws_public
123 .clone()
124 .unwrap_or_else(|| get_ws_base_url_public(self.environment).to_string())
125 }
126
127 #[must_use]
129 pub fn ws_business_url(&self) -> String {
130 self.base_url_ws_business
131 .clone()
132 .unwrap_or_else(|| get_ws_base_url_business(self.environment).to_string())
133 }
134
135 #[must_use]
140 pub fn requires_business_ws(&self) -> bool {
141 true
142 }
143}
144
145#[derive(Clone, Debug, bon::Builder)]
147#[cfg_attr(
148 feature = "python",
149 pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.okx", from_py_object)
150)]
151#[cfg_attr(
152 feature = "python",
153 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.okx")
154)]
155pub struct OKXExecClientConfig {
156 #[builder(default = TraderId::from("TRADER-001"))]
158 pub trader_id: TraderId,
159 #[builder(default = AccountId::from("OKX-001"))]
161 pub account_id: AccountId,
162 pub api_key: Option<String>,
164 pub api_secret: Option<String>,
166 pub api_passphrase: Option<String>,
168 #[builder(default = vec![OKXInstrumentType::Spot])]
170 pub instrument_types: Vec<OKXInstrumentType>,
171 pub contract_types: Option<Vec<OKXContractType>>,
173 pub instrument_families: Option<Vec<String>>,
176 pub base_url_http: Option<String>,
178 pub base_url_ws_private: Option<String>,
180 pub base_url_ws_business: Option<String>,
182 pub proxy_url: Option<String>,
184 #[builder(default)]
186 pub environment: OKXEnvironment,
187 #[builder(default = 60)]
189 pub http_timeout_secs: u64,
190 #[builder(default)]
192 pub use_fills_channel: bool,
193 #[builder(default)]
195 pub use_mm_mass_cancel: bool,
196 #[builder(default = 3)]
198 pub max_retries: u32,
199 #[builder(default = 1_000)]
201 pub retry_delay_initial_ms: u64,
202 #[builder(default = 10_000)]
204 pub retry_delay_max_ms: u64,
205 pub margin_mode: Option<OKXMarginMode>,
207 #[builder(default)]
209 pub use_spot_margin: bool,
210 #[builder(default)]
212 pub transport_backend: TransportBackend,
213}
214
215impl Default for OKXExecClientConfig {
216 fn default() -> Self {
217 Self::builder().build()
218 }
219}
220
221impl OKXExecClientConfig {
222 #[must_use]
224 pub fn new() -> Self {
225 Self::default()
226 }
227
228 #[must_use]
230 pub fn has_api_credentials(&self) -> bool {
231 let (key_var, secret_var, passphrase_var) = credential_env_vars();
232 let has_key = self.api_key.is_some() || std::env::var(key_var).is_ok();
233 let has_secret = self.api_secret.is_some() || std::env::var(secret_var).is_ok();
234 let has_passphrase = self.api_passphrase.is_some() || std::env::var(passphrase_var).is_ok();
235 has_key && has_secret && has_passphrase
236 }
237
238 #[must_use]
240 pub fn http_base_url(&self) -> String {
241 self.base_url_http
242 .clone()
243 .unwrap_or_else(|| get_http_base_url().to_string())
244 }
245
246 #[must_use]
248 pub fn ws_private_url(&self) -> String {
249 self.base_url_ws_private
250 .clone()
251 .unwrap_or_else(|| get_ws_base_url_private(self.environment).to_string())
252 }
253
254 #[must_use]
256 pub fn ws_business_url(&self) -> String {
257 self.base_url_ws_business
258 .clone()
259 .unwrap_or_else(|| get_ws_base_url_business(self.environment).to_string())
260 }
261}