Skip to main content

nautilus_kraken/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 Kraken configuration.
17
18use nautilus_core::{python::to_pyvalue_err, string::secret::SecretString};
19use nautilus_model::{enums::AccountType, identifiers::AccountId};
20use nautilus_network::websocket::TransportBackend;
21use pyo3::prelude::*;
22
23use crate::{
24    common::enums::{KrakenEnvironment, KrakenProductType},
25    config::{KrakenDataClientConfig, KrakenExecutionClientConfig},
26};
27
28#[pymethods]
29#[pyo3_stub_gen::derive::gen_stub_pymethods]
30impl KrakenDataClientConfig {
31    /// Configuration for the Kraken data client.
32    #[new]
33    #[pyo3(signature = (
34        product_type = None,
35        environment = None,
36        api_key = None,
37        api_secret = None,
38        base_url = None,
39        ws_public_url = None,
40        ws_private_url = None,
41        ws_l3_url = None,
42        validate_l3_checksum = None,
43        proxy_url = None,
44        timeout_secs = None,
45        heartbeat_interval_secs = None,
46        ws_idle_timeout_ms = None,
47        max_requests_per_second = None,
48        transport_backend = None,
49    ))]
50    #[expect(clippy::too_many_arguments)]
51    fn py_new(
52        product_type: Option<KrakenProductType>,
53        environment: Option<KrakenEnvironment>,
54        api_key: Option<String>,
55        api_secret: Option<String>,
56        base_url: Option<String>,
57        ws_public_url: Option<String>,
58        ws_private_url: Option<String>,
59        ws_l3_url: Option<String>,
60        validate_l3_checksum: Option<bool>,
61        proxy_url: Option<String>,
62        timeout_secs: Option<u64>,
63        heartbeat_interval_secs: Option<u64>,
64        ws_idle_timeout_ms: Option<u64>,
65        max_requests_per_second: Option<u32>,
66        transport_backend: Option<TransportBackend>,
67    ) -> Self {
68        let defaults = Self::default();
69        Self {
70            api_key: api_key.map(SecretString::from),
71            api_secret: api_secret.map(SecretString::from),
72            product_type: product_type.unwrap_or(defaults.product_type),
73            environment: environment.unwrap_or(defaults.environment),
74            base_url,
75            ws_public_url,
76            ws_private_url,
77            ws_l3_url,
78            validate_l3_checksum: validate_l3_checksum.unwrap_or(defaults.validate_l3_checksum),
79            proxy_url: proxy_url.map(SecretString::from),
80            timeout_secs: timeout_secs.unwrap_or(defaults.timeout_secs),
81            heartbeat_interval_secs: heartbeat_interval_secs
82                .unwrap_or(defaults.heartbeat_interval_secs),
83            ws_idle_timeout_ms: ws_idle_timeout_ms.unwrap_or(defaults.ws_idle_timeout_ms),
84            max_requests_per_second,
85            transport_backend: transport_backend.unwrap_or(defaults.transport_backend),
86        }
87    }
88
89    #[getter]
90    const fn has_proxy_url(&self) -> bool {
91        self.proxy_url.is_some()
92    }
93
94    /// Returns the configured public WebSocket URL override.
95    #[getter]
96    fn get_ws_public_url(&self) -> Option<String> {
97        self.ws_public_url.clone()
98    }
99
100    /// Returns the configured private WebSocket URL override.
101    #[getter]
102    fn get_ws_private_url(&self) -> Option<String> {
103        self.ws_private_url.clone()
104    }
105
106    /// Returns the configured L3 WebSocket URL override.
107    #[getter]
108    fn get_ws_l3_url(&self) -> Option<String> {
109        self.ws_l3_url.clone()
110    }
111
112    fn __repr__(&self) -> String {
113        stringify!(KrakenDataClientConfig).to_string()
114    }
115}
116
117#[pymethods]
118#[pyo3_stub_gen::derive::gen_stub_pymethods]
119impl KrakenExecutionClientConfig {
120    /// Configuration for the Kraken execution client.
121    #[new]
122    #[pyo3(signature = (
123        account_id,
124        api_key,
125        api_secret,
126        product_type = None,
127        environment = None,
128        base_url = None,
129        ws_url = None,
130        proxy_url = None,
131        timeout_secs = None,
132        heartbeat_interval_secs = None,
133        auth_timeout_secs = None,
134        max_requests_per_second = None,
135        max_retries = None,
136        spot_account_type = None,
137        default_leverage = None,
138        use_spot_position_reports = None,
139        spot_positions_quote_currency = None,
140        margin_balance_asset = None,
141        use_ws_trade = None,
142        ws_request_timeout_secs = None,
143        transport_backend = None,
144    ))]
145    #[expect(clippy::too_many_arguments)]
146    fn py_new(
147        account_id: AccountId,
148        api_key: String,
149        api_secret: String,
150        product_type: Option<KrakenProductType>,
151        environment: Option<KrakenEnvironment>,
152        base_url: Option<String>,
153        ws_url: Option<String>,
154        proxy_url: Option<String>,
155        timeout_secs: Option<u64>,
156        heartbeat_interval_secs: Option<u64>,
157        auth_timeout_secs: Option<u64>,
158        max_requests_per_second: Option<u32>,
159        max_retries: Option<u32>,
160        spot_account_type: Option<AccountType>,
161        default_leverage: Option<u16>,
162        use_spot_position_reports: Option<bool>,
163        spot_positions_quote_currency: Option<String>,
164        margin_balance_asset: Option<String>,
165        use_ws_trade: Option<bool>,
166        ws_request_timeout_secs: Option<u64>,
167        transport_backend: Option<TransportBackend>,
168    ) -> PyResult<Self> {
169        let defaults = Self::default();
170        let spot_account_type = spot_account_type.unwrap_or(defaults.spot_account_type);
171        if default_leverage.is_some() && spot_account_type == AccountType::Cash {
172            return Err(to_pyvalue_err(
173                "default_leverage requires spot_account_type=Margin",
174            ));
175        }
176        Ok(Self {
177            account_id,
178            api_key: api_key.into(),
179            api_secret: api_secret.into(),
180            product_type: product_type.unwrap_or(defaults.product_type),
181            environment: environment.unwrap_or(defaults.environment),
182            base_url,
183            ws_url,
184            proxy_url: proxy_url.map(SecretString::from),
185            timeout_secs: timeout_secs.unwrap_or(defaults.timeout_secs),
186            heartbeat_interval_secs: heartbeat_interval_secs
187                .unwrap_or(defaults.heartbeat_interval_secs),
188            auth_timeout_secs,
189            max_requests_per_second,
190            max_retries: max_retries.unwrap_or(defaults.max_retries),
191            transport_backend: transport_backend.unwrap_or(defaults.transport_backend),
192            spot_account_type,
193            default_leverage,
194            use_spot_position_reports: use_spot_position_reports
195                .unwrap_or(defaults.use_spot_position_reports),
196            spot_positions_quote_currency: spot_positions_quote_currency
197                .unwrap_or(defaults.spot_positions_quote_currency),
198            margin_balance_asset,
199            use_ws_trade: use_ws_trade.unwrap_or(defaults.use_ws_trade),
200            ws_request_timeout_secs: ws_request_timeout_secs
201                .unwrap_or(defaults.ws_request_timeout_secs),
202        })
203    }
204
205    #[getter]
206    const fn has_proxy_url(&self) -> bool {
207        self.proxy_url.is_some()
208    }
209
210    /// Returns the configured WebSocket URL override.
211    #[getter]
212    fn get_ws_url(&self) -> Option<String> {
213        self.ws_url.clone()
214    }
215
216    fn __repr__(&self) -> String {
217        stringify!(KrakenExecutionClientConfig).to_string()
218    }
219}