Skip to main content

nautilus_architect_ax/
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//! Configuration structures for the AX Exchange adapter.
17
18use nautilus_model::identifiers::{AccountId, TraderId};
19
20/// Configuration for the AX Exchange live data client.
21#[derive(Clone, Debug)]
22pub struct AxDataClientConfig {
23    /// Optional API key for authenticated REST/WebSocket requests.
24    pub api_key: Option<String>,
25    /// Optional API secret for authenticated REST/WebSocket requests.
26    pub api_secret: Option<String>,
27    /// Use sandbox environment (default: false).
28    pub is_sandbox: bool,
29    /// Optional override for the REST base URL.
30    pub base_url_http: Option<String>,
31    /// Optional override for the public WebSocket URL.
32    pub base_url_ws_public: Option<String>,
33    /// Optional override for the private WebSocket URL.
34    pub base_url_ws_private: Option<String>,
35    /// Optional HTTP proxy URL.
36    pub http_proxy_url: Option<String>,
37    /// Optional WebSocket proxy URL.
38    pub ws_proxy_url: Option<String>,
39    /// Optional REST timeout in seconds.
40    pub http_timeout_secs: Option<u64>,
41    /// Optional maximum retry attempts for REST requests.
42    pub max_retries: Option<u32>,
43    /// Optional initial retry backoff in milliseconds.
44    pub retry_delay_initial_ms: Option<u64>,
45    /// Optional maximum retry backoff in milliseconds.
46    pub retry_delay_max_ms: Option<u64>,
47    /// Optional heartbeat interval (seconds) for WebSocket clients.
48    pub heartbeat_interval_secs: Option<u64>,
49    /// Optional receive window in milliseconds for signed requests.
50    pub recv_window_ms: Option<u64>,
51    /// Optional interval (minutes) for instrument refresh from REST.
52    pub update_instruments_interval_mins: Option<u64>,
53}
54
55impl Default for AxDataClientConfig {
56    fn default() -> Self {
57        Self {
58            api_key: None,
59            api_secret: None,
60            is_sandbox: false,
61            base_url_http: None,
62            base_url_ws_public: None,
63            base_url_ws_private: None,
64            http_proxy_url: None,
65            ws_proxy_url: None,
66            http_timeout_secs: Some(60),
67            max_retries: Some(3),
68            retry_delay_initial_ms: Some(1_000),
69            retry_delay_max_ms: Some(10_000),
70            heartbeat_interval_secs: Some(20),
71            recv_window_ms: Some(5_000),
72            update_instruments_interval_mins: Some(60),
73        }
74    }
75}
76
77impl AxDataClientConfig {
78    /// Creates a configuration with default values.
79    #[must_use]
80    pub fn new() -> Self {
81        Self::default()
82    }
83
84    /// Returns `true` if both API key and secret are available.
85    #[must_use]
86    pub fn has_api_credentials(&self) -> bool {
87        let has_key = self.api_key.is_some() || std::env::var("AX_API_KEY").is_ok();
88        let has_secret = self.api_secret.is_some() || std::env::var("AX_API_SECRET").is_ok();
89        has_key && has_secret
90    }
91
92    /// Returns the REST base URL, considering overrides and environment.
93    #[must_use]
94    pub fn http_base_url(&self) -> String {
95        self.base_url_http.clone().unwrap_or_else(|| {
96            if self.is_sandbox {
97                "https://gateway.sandbox.architect.exchange/api".to_string()
98            } else {
99                "https://gateway.architect.exchange/api".to_string()
100            }
101        })
102    }
103
104    /// Returns the public WebSocket URL, considering overrides and environment.
105    #[must_use]
106    pub fn ws_public_url(&self) -> String {
107        self.base_url_ws_public.clone().unwrap_or_else(|| {
108            if self.is_sandbox {
109                "wss://gateway.sandbox.architect.exchange/md/ws".to_string()
110            } else {
111                "wss://gateway.architect.exchange/md/ws".to_string()
112            }
113        })
114    }
115
116    /// Returns the private WebSocket URL, considering overrides and environment.
117    #[must_use]
118    pub fn ws_private_url(&self) -> String {
119        self.base_url_ws_private.clone().unwrap_or_else(|| {
120            if self.is_sandbox {
121                "wss://gateway.sandbox.architect.exchange/orders/ws".to_string()
122            } else {
123                "wss://gateway.architect.exchange/orders/ws".to_string()
124            }
125        })
126    }
127}
128
129/// Configuration for the AX Exchange live execution client.
130#[derive(Clone, Debug)]
131pub struct AxExecClientConfig {
132    /// The trader ID for the client.
133    pub trader_id: TraderId,
134    /// The account ID for the client.
135    pub account_id: AccountId,
136    /// API key for authenticated requests.
137    pub api_key: Option<String>,
138    /// API secret for authenticated requests.
139    pub api_secret: Option<String>,
140    /// Use sandbox environment (default: true).
141    pub is_sandbox: bool,
142    /// Optional override for the REST base URL.
143    pub base_url_http: Option<String>,
144    /// Optional override for the orders REST base URL.
145    pub base_url_orders: Option<String>,
146    /// Optional override for the private WebSocket URL.
147    pub base_url_ws_private: Option<String>,
148    /// Optional HTTP proxy URL.
149    pub http_proxy_url: Option<String>,
150    /// Optional WebSocket proxy URL.
151    pub ws_proxy_url: Option<String>,
152    /// Optional REST timeout in seconds.
153    pub http_timeout_secs: Option<u64>,
154    /// Optional maximum retry attempts for REST requests.
155    pub max_retries: Option<u32>,
156    /// Optional initial retry backoff in milliseconds.
157    pub retry_delay_initial_ms: Option<u64>,
158    /// Optional maximum retry backoff in milliseconds.
159    pub retry_delay_max_ms: Option<u64>,
160    /// Optional heartbeat interval (seconds) for WebSocket clients.
161    pub heartbeat_interval_secs: Option<u64>,
162    /// Optional receive window in milliseconds for signed requests.
163    pub recv_window_ms: Option<u64>,
164}
165
166impl Default for AxExecClientConfig {
167    fn default() -> Self {
168        Self {
169            trader_id: TraderId::from("TRADER-001"),
170            account_id: AccountId::from("AX-001"),
171            api_key: None,
172            api_secret: None,
173            is_sandbox: true,
174            base_url_http: None,
175            base_url_orders: None,
176            base_url_ws_private: None,
177            http_proxy_url: None,
178            ws_proxy_url: None,
179            http_timeout_secs: Some(60),
180            max_retries: Some(3),
181            retry_delay_initial_ms: Some(1_000),
182            retry_delay_max_ms: Some(10_000),
183            heartbeat_interval_secs: Some(30),
184            recv_window_ms: Some(5_000),
185        }
186    }
187}
188
189impl AxExecClientConfig {
190    /// Creates a configuration with default values.
191    #[must_use]
192    pub fn new() -> Self {
193        Self::default()
194    }
195
196    /// Returns `true` if both API key and secret are available.
197    #[must_use]
198    pub fn has_api_credentials(&self) -> bool {
199        let has_key = self.api_key.is_some() || std::env::var("AX_API_KEY").is_ok();
200        let has_secret = self.api_secret.is_some() || std::env::var("AX_API_SECRET").is_ok();
201        has_key && has_secret
202    }
203
204    /// Returns the REST base URL, considering overrides and environment.
205    #[must_use]
206    pub fn http_base_url(&self) -> String {
207        self.base_url_http.clone().unwrap_or_else(|| {
208            if self.is_sandbox {
209                "https://gateway.sandbox.architect.exchange/api".to_string()
210            } else {
211                "https://gateway.architect.exchange/api".to_string()
212            }
213        })
214    }
215
216    /// Returns the orders REST base URL, considering overrides and environment.
217    #[must_use]
218    pub fn orders_base_url(&self) -> String {
219        self.base_url_orders.clone().unwrap_or_else(|| {
220            if self.is_sandbox {
221                "https://gateway.sandbox.architect.exchange/orders".to_string()
222            } else {
223                "https://gateway.architect.exchange/orders".to_string()
224            }
225        })
226    }
227
228    /// Returns the private WebSocket URL, considering overrides and environment.
229    #[must_use]
230    pub fn ws_private_url(&self) -> String {
231        self.base_url_ws_private.clone().unwrap_or_else(|| {
232            if self.is_sandbox {
233                "wss://gateway.sandbox.architect.exchange/orders/ws".to_string()
234            } else {
235                "wss://gateway.architect.exchange/orders/ws".to_string()
236            }
237        })
238    }
239}