1use nautilus_core::{python::to_pyvalue_err, string::secret::SecretString};
19use nautilus_model::identifiers::AccountId;
20use nautilus_network::websocket::TransportBackend;
21use pyo3::{PyResult, pymethods};
22
23use crate::{
24 common::{
25 enums::{BybitEnvironment, BybitMarginMode, BybitProductType},
26 parse::parse_smp_type,
27 },
28 config::{BybitDataClientConfig, BybitExecutionClientConfig},
29};
30
31#[pymethods]
32#[pyo3_stub_gen::derive::gen_stub_pymethods]
33impl BybitDataClientConfig {
34 #[new]
36 #[pyo3(signature = (
37 product_types = None,
38 environment = None,
39 api_key = None,
40 api_secret = None,
41 base_url_http = None,
42 base_url_ws_public = None,
43 base_url_ws_private = None,
44 proxy_url = None,
45 http_timeout_secs = None,
46 max_retries = None,
47 retry_delay_initial_ms = None,
48 retry_delay_max_ms = None,
49 heartbeat_interval_secs = None,
50 recv_window_ms = None,
51 update_instruments_interval_mins = None,
52 instrument_status_poll_secs = None,
53 transport_backend = None,
54 ))]
55 #[expect(clippy::too_many_arguments)]
56 fn py_new(
57 product_types: Option<Vec<BybitProductType>>,
58 environment: Option<BybitEnvironment>,
59 api_key: Option<String>,
60 api_secret: Option<String>,
61 base_url_http: Option<String>,
62 base_url_ws_public: Option<String>,
63 base_url_ws_private: Option<String>,
64 proxy_url: Option<String>,
65 http_timeout_secs: Option<u64>,
66 max_retries: Option<u32>,
67 retry_delay_initial_ms: Option<u64>,
68 retry_delay_max_ms: Option<u64>,
69 heartbeat_interval_secs: Option<u64>,
70 recv_window_ms: Option<u64>,
71 update_instruments_interval_mins: Option<u64>,
72 instrument_status_poll_secs: Option<u64>,
73 transport_backend: Option<TransportBackend>,
74 ) -> Self {
75 let defaults = Self::default();
76 Self {
77 api_key: api_key.map(SecretString::from),
78 api_secret: api_secret.map(SecretString::from),
79 product_types: product_types.unwrap_or(defaults.product_types),
80 environment: environment.unwrap_or(defaults.environment),
81 base_url_http,
82 base_url_ws_public,
83 base_url_ws_private,
84 proxy_url: proxy_url.map(SecretString::from),
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 heartbeat_interval_secs: heartbeat_interval_secs
91 .unwrap_or(defaults.heartbeat_interval_secs),
92 recv_window_ms: recv_window_ms.unwrap_or(defaults.recv_window_ms),
93 update_instruments_interval_mins: update_instruments_interval_mins
94 .or(defaults.update_instruments_interval_mins),
95 instrument_poll_interval_secs: instrument_status_poll_secs
96 .or(defaults.instrument_poll_interval_secs),
97 transport_backend: transport_backend.unwrap_or(defaults.transport_backend),
98 }
99 }
100
101 #[getter]
102 const fn instrument_status_poll_secs(&self) -> Option<u64> {
103 self.instrument_poll_interval_secs
104 }
105
106 #[getter]
107 const fn has_proxy_url(&self) -> bool {
108 self.proxy_url.is_some()
109 }
110
111 fn __repr__(&self) -> String {
112 stringify!(BybitDataClientConfig).to_string()
113 }
114}
115
116#[pymethods]
117#[pyo3_stub_gen::derive::gen_stub_pymethods]
118impl BybitExecutionClientConfig {
119 #[new]
121 #[pyo3(signature = (
122 product_types = None,
123 environment = None,
124 api_key = None,
125 api_secret = None,
126 base_url_http = None,
127 base_url_ws_private = None,
128 base_url_ws_trade = None,
129 proxy_url = None,
130 http_timeout_secs = None,
131 max_retries = None,
132 retry_delay_initial_ms = None,
133 retry_delay_max_ms = None,
134 heartbeat_interval_secs = None,
135 auth_timeout_secs = None,
136 recv_window_ms = None,
137 account_id = None,
138 use_spot_position_reports = None,
139 auto_repay_spot_borrows = None,
140 margin_mode = None,
141 smp_type = None,
142 transport_backend = None,
143 ))]
144 #[expect(clippy::too_many_arguments)]
145 fn py_new(
146 product_types: Option<Vec<BybitProductType>>,
147 environment: Option<BybitEnvironment>,
148 api_key: Option<String>,
149 api_secret: Option<String>,
150 base_url_http: Option<String>,
151 base_url_ws_private: Option<String>,
152 base_url_ws_trade: Option<String>,
153 proxy_url: Option<String>,
154 http_timeout_secs: Option<u64>,
155 max_retries: Option<u32>,
156 retry_delay_initial_ms: Option<u64>,
157 retry_delay_max_ms: Option<u64>,
158 heartbeat_interval_secs: Option<u64>,
159 auth_timeout_secs: Option<u64>,
160 recv_window_ms: Option<u64>,
161 account_id: Option<AccountId>,
162 use_spot_position_reports: Option<bool>,
163 auto_repay_spot_borrows: Option<bool>,
164 margin_mode: Option<BybitMarginMode>,
165 smp_type: Option<String>,
166 transport_backend: Option<TransportBackend>,
167 ) -> PyResult<Self> {
168 let smp_type = smp_type
169 .map(|value| parse_smp_type(&value))
170 .transpose()
171 .map_err(to_pyvalue_err)?;
172
173 let defaults = Self::default();
174 Ok(Self {
175 api_key: api_key.map(SecretString::from),
176 api_secret: api_secret.map(SecretString::from),
177 product_types: product_types.unwrap_or(defaults.product_types),
178 environment: environment.unwrap_or(defaults.environment),
179 base_url_http,
180 base_url_ws_private,
181 base_url_ws_trade,
182 proxy_url: proxy_url.map(SecretString::from),
183 http_timeout_secs: http_timeout_secs.unwrap_or(defaults.http_timeout_secs),
184 max_retries: max_retries.unwrap_or(defaults.max_retries),
185 retry_delay_initial_ms: retry_delay_initial_ms
186 .unwrap_or(defaults.retry_delay_initial_ms),
187 retry_delay_max_ms: retry_delay_max_ms.unwrap_or(defaults.retry_delay_max_ms),
188 heartbeat_interval_secs: heartbeat_interval_secs
189 .unwrap_or(defaults.heartbeat_interval_secs),
190 auth_timeout_secs,
191 recv_window_ms: recv_window_ms.unwrap_or(defaults.recv_window_ms),
192 account_id,
193 use_spot_position_reports: use_spot_position_reports
194 .unwrap_or(defaults.use_spot_position_reports),
195 auto_repay_spot_borrows: auto_repay_spot_borrows
196 .unwrap_or(defaults.auto_repay_spot_borrows),
197 futures_leverages: None,
198 position_mode: None,
199 margin_mode,
200 smp_type,
201 transport_backend: transport_backend.unwrap_or(defaults.transport_backend),
202 })
203 }
204
205 #[getter]
206 #[pyo3(name = "smp_type")]
207 fn py_smp_type(&self) -> Option<String> {
208 self.smp_type.map(|smp_type| smp_type.as_ref().to_string())
209 }
210
211 #[getter]
212 const fn has_proxy_url(&self) -> bool {
213 self.proxy_url.is_some()
214 }
215
216 fn __repr__(&self) -> String {
217 stringify!(BybitExecutionClientConfig).to_string()
218 }
219}