Skip to main content

nautilus_architect_ax/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
16use nautilus_core::string::secret::SecretString;
17use nautilus_model::identifiers::AccountId;
18use nautilus_network::websocket::TransportBackend;
19use pyo3::pymethods;
20
21use crate::{
22    common::enums::AxEnvironment,
23    config::{AxDataClientConfig, AxExecutionClientConfig},
24};
25
26#[pymethods]
27#[pyo3_stub_gen::derive::gen_stub_pymethods]
28impl AxDataClientConfig {
29    /// Configuration for the AX Exchange live data client.
30    #[new]
31    #[expect(clippy::too_many_arguments)]
32    #[pyo3(signature = (api_key=None, api_secret=None, environment=None, base_url_http=None, base_url_ws_public=None, base_url_ws_private=None, proxy_url=None, http_timeout_secs=None, max_retries=None, retry_delay_initial_ms=None, retry_delay_max_ms=None, heartbeat_interval_secs=None, recv_window_ms=None, update_instruments_interval_mins=None, funding_rate_poll_interval_mins=None, transport_backend=None, book_snapshot_timeout_secs=None))]
33    fn py_new(
34        api_key: Option<String>,
35        api_secret: Option<String>,
36        environment: Option<AxEnvironment>,
37        base_url_http: Option<String>,
38        base_url_ws_public: Option<String>,
39        base_url_ws_private: Option<String>,
40        proxy_url: Option<String>,
41        http_timeout_secs: Option<u64>,
42        max_retries: Option<u32>,
43        retry_delay_initial_ms: Option<u64>,
44        retry_delay_max_ms: Option<u64>,
45        heartbeat_interval_secs: Option<u64>,
46        recv_window_ms: Option<u64>,
47        update_instruments_interval_mins: Option<u64>,
48        funding_rate_poll_interval_mins: Option<u64>,
49        transport_backend: Option<TransportBackend>,
50        book_snapshot_timeout_secs: Option<u64>,
51    ) -> Self {
52        let default = Self::default();
53        Self {
54            api_key: api_key.map(SecretString::from),
55            api_secret: api_secret.map(SecretString::from),
56            environment: environment.unwrap_or(default.environment),
57            base_url_http,
58            base_url_ws_public,
59            base_url_ws_private,
60            proxy_url: proxy_url.map(SecretString::from),
61            http_timeout_secs: http_timeout_secs.unwrap_or(default.http_timeout_secs),
62            max_retries: max_retries.unwrap_or(default.max_retries),
63            retry_delay_initial_ms: retry_delay_initial_ms
64                .unwrap_or(default.retry_delay_initial_ms),
65            retry_delay_max_ms: retry_delay_max_ms.unwrap_or(default.retry_delay_max_ms),
66            heartbeat_interval_secs: heartbeat_interval_secs
67                .unwrap_or(default.heartbeat_interval_secs),
68            recv_window_ms: recv_window_ms.unwrap_or(default.recv_window_ms),
69            update_instruments_interval_mins: update_instruments_interval_mins
70                .unwrap_or(default.update_instruments_interval_mins),
71            funding_rate_poll_interval_mins: funding_rate_poll_interval_mins
72                .unwrap_or(default.funding_rate_poll_interval_mins),
73            book_snapshot_timeout_secs: book_snapshot_timeout_secs
74                .unwrap_or(default.book_snapshot_timeout_secs),
75            transport_backend: transport_backend.unwrap_or(default.transport_backend),
76        }
77    }
78
79    #[getter]
80    const fn has_proxy_url(&self) -> bool {
81        self.proxy_url.is_some()
82    }
83
84    fn __repr__(&self) -> String {
85        stringify!(AxDataClientConfig).to_string()
86    }
87
88    fn __str__(&self) -> String {
89        stringify!(AxDataClientConfig).to_string()
90    }
91}
92
93#[pymethods]
94#[pyo3_stub_gen::derive::gen_stub_pymethods]
95impl AxExecutionClientConfig {
96    /// Configuration for the AX Exchange live execution client.
97    #[new]
98    #[expect(clippy::too_many_arguments)]
99    #[pyo3(signature = (account_id=None, api_key=None, api_secret=None, environment=None, base_url_http=None, base_url_orders=None, base_url_ws_private=None, proxy_url=None, http_timeout_secs=None, max_retries=None, retry_delay_initial_ms=None, retry_delay_max_ms=None, heartbeat_interval_secs=None, recv_window_ms=None, cancel_on_disconnect=None, transport_backend=None))]
100    fn py_new(
101        account_id: Option<AccountId>,
102        api_key: Option<String>,
103        api_secret: Option<String>,
104        environment: Option<AxEnvironment>,
105        base_url_http: Option<String>,
106        base_url_orders: Option<String>,
107        base_url_ws_private: Option<String>,
108        proxy_url: Option<String>,
109        http_timeout_secs: Option<u64>,
110        max_retries: Option<u32>,
111        retry_delay_initial_ms: Option<u64>,
112        retry_delay_max_ms: Option<u64>,
113        heartbeat_interval_secs: Option<u64>,
114        recv_window_ms: Option<u64>,
115        cancel_on_disconnect: Option<bool>,
116        transport_backend: Option<TransportBackend>,
117    ) -> Self {
118        let default = Self::default();
119        Self {
120            account_id: account_id.unwrap_or(default.account_id),
121            api_key: api_key.map(SecretString::from),
122            api_secret: api_secret.map(SecretString::from),
123            environment: environment.unwrap_or(default.environment),
124            base_url_http,
125            base_url_orders,
126            base_url_ws_private,
127            proxy_url: proxy_url.map(SecretString::from),
128            http_timeout_secs: http_timeout_secs.unwrap_or(default.http_timeout_secs),
129            max_retries: max_retries.unwrap_or(default.max_retries),
130            retry_delay_initial_ms: retry_delay_initial_ms
131                .unwrap_or(default.retry_delay_initial_ms),
132            retry_delay_max_ms: retry_delay_max_ms.unwrap_or(default.retry_delay_max_ms),
133            heartbeat_interval_secs: heartbeat_interval_secs
134                .unwrap_or(default.heartbeat_interval_secs),
135            recv_window_ms: recv_window_ms.unwrap_or(default.recv_window_ms),
136            cancel_on_disconnect: cancel_on_disconnect.unwrap_or(default.cancel_on_disconnect),
137            transport_backend: transport_backend.unwrap_or(default.transport_backend),
138        }
139    }
140
141    #[getter]
142    const fn has_proxy_url(&self) -> bool {
143        self.proxy_url.is_some()
144    }
145
146    fn __repr__(&self) -> String {
147        stringify!(AxExecutionClientConfig).to_string()
148    }
149
150    fn __str__(&self) -> String {
151        stringify!(AxExecutionClientConfig).to_string()
152    }
153}
154
155#[cfg(test)]
156mod tests {
157    use rstest::rstest;
158
159    use super::*;
160
161    #[rstest]
162    #[case::default(None, 10)]
163    #[case::override_value(Some(42), 42)]
164    fn test_data_config_py_new_book_snapshot_timeout(
165        #[case] book_snapshot_timeout_secs: Option<u64>,
166        #[case] expected: u64,
167    ) {
168        let config = AxDataClientConfig::py_new(
169            None,
170            None,
171            None,
172            None,
173            None,
174            None,
175            None,
176            None,
177            None,
178            None,
179            None,
180            None,
181            None,
182            None,
183            Some(7),
184            None,
185            book_snapshot_timeout_secs,
186        );
187
188        assert_eq!(config.funding_rate_poll_interval_mins, 7);
189        assert_eq!(config.book_snapshot_timeout_secs, expected);
190    }
191}