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;
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,
71            api_secret,
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,
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        spot_account_type = None,
136        default_leverage = None,
137        use_spot_position_reports = None,
138        spot_positions_quote_currency = None,
139        margin_balance_asset = None,
140        use_ws_trade = None,
141        ws_request_timeout_secs = None,
142        transport_backend = None,
143    ))]
144    #[expect(clippy::too_many_arguments)]
145    fn py_new(
146        account_id: AccountId,
147        api_key: String,
148        api_secret: String,
149        product_type: Option<KrakenProductType>,
150        environment: Option<KrakenEnvironment>,
151        base_url: Option<String>,
152        ws_url: Option<String>,
153        proxy_url: Option<String>,
154        timeout_secs: Option<u64>,
155        heartbeat_interval_secs: Option<u64>,
156        auth_timeout_secs: Option<u64>,
157        max_requests_per_second: Option<u32>,
158        spot_account_type: Option<AccountType>,
159        default_leverage: Option<u16>,
160        use_spot_position_reports: Option<bool>,
161        spot_positions_quote_currency: Option<String>,
162        margin_balance_asset: Option<String>,
163        use_ws_trade: Option<bool>,
164        ws_request_timeout_secs: Option<u64>,
165        transport_backend: Option<TransportBackend>,
166    ) -> PyResult<Self> {
167        let defaults = Self::default();
168        let spot_account_type = spot_account_type.unwrap_or(defaults.spot_account_type);
169        if default_leverage.is_some() && spot_account_type == AccountType::Cash {
170            return Err(to_pyvalue_err(
171                "default_leverage requires spot_account_type=Margin",
172            ));
173        }
174        Ok(Self {
175            account_id,
176            api_key,
177            api_secret,
178            product_type: product_type.unwrap_or(defaults.product_type),
179            environment: environment.unwrap_or(defaults.environment),
180            base_url,
181            ws_url,
182            proxy_url,
183            timeout_secs: timeout_secs.unwrap_or(defaults.timeout_secs),
184            heartbeat_interval_secs: heartbeat_interval_secs
185                .unwrap_or(defaults.heartbeat_interval_secs),
186            auth_timeout_secs,
187            max_requests_per_second,
188            transport_backend: transport_backend.unwrap_or(defaults.transport_backend),
189            spot_account_type,
190            default_leverage,
191            use_spot_position_reports: use_spot_position_reports
192                .unwrap_or(defaults.use_spot_position_reports),
193            spot_positions_quote_currency: spot_positions_quote_currency
194                .unwrap_or(defaults.spot_positions_quote_currency),
195            margin_balance_asset,
196            use_ws_trade: use_ws_trade.unwrap_or(defaults.use_ws_trade),
197            ws_request_timeout_secs: ws_request_timeout_secs
198                .unwrap_or(defaults.ws_request_timeout_secs),
199        })
200    }
201
202    #[getter]
203    const fn has_proxy_url(&self) -> bool {
204        self.proxy_url.is_some()
205    }
206
207    /// Returns the configured WebSocket URL override.
208    #[getter]
209    fn get_ws_url(&self) -> Option<String> {
210        self.ws_url.clone()
211    }
212
213    fn __repr__(&self) -> String {
214        stringify!(KrakenExecutionClientConfig).to_string()
215    }
216}