1use nautilus_core::string::secret::SecretString;
19use nautilus_live::book::DEFAULT_BOOK_SNAPSHOT_TIMEOUT_SECS;
20use nautilus_model::identifiers::AccountId;
21use pyo3::prelude::*;
22use rust_decimal::Decimal;
23
24use crate::config::{BetfairDataClientConfig, BetfairExecutionClientConfig};
25
26fn stringify_ids(values: Option<Vec<u64>>) -> Option<Vec<String>> {
27 values.map(|values| values.into_iter().map(|value| value.to_string()).collect())
28}
29
30#[pymethods]
31#[pyo3_stub_gen::derive::gen_stub_pymethods]
32impl BetfairDataClientConfig {
33 #[new]
35 #[pyo3(signature = (
36 account_currency = None,
37 username = None,
38 password = None,
39 app_key = None,
40 proxy_url = None,
41 request_rate_per_second = 5,
42 default_min_notional = None,
43 event_type_ids = None,
44 event_type_names = None,
45 event_ids = None,
46 country_codes = None,
47 market_types = None,
48 market_ids = None,
49 min_market_start_time = None,
50 max_market_start_time = None,
51 stream_host = None,
52 stream_port = None,
53 stream_heartbeat_secs = None,
54 stream_heartbeat_timeout_secs = None,
55 stream_reconnect_delay_initial_ms = 2_000,
56 stream_reconnect_delay_max_ms = 30_000,
57 stream_use_tls = true,
58 stream_conflate_ms = None,
59 subscription_delay_secs = None,
60 subscribe_race_data = false,
61 subscribe_cricket_data = false,
62 book_snapshot_timeout_secs = None,
63 ))]
64 #[expect(clippy::too_many_arguments)]
65 fn py_new(
66 account_currency: Option<String>,
67 username: Option<String>,
68 password: Option<String>,
69 app_key: Option<String>,
70 proxy_url: Option<String>,
71 request_rate_per_second: u32,
72 default_min_notional: Option<Decimal>,
73 event_type_ids: Option<Vec<u64>>,
74 event_type_names: Option<Vec<String>>,
75 event_ids: Option<Vec<u64>>,
76 country_codes: Option<Vec<String>>,
77 market_types: Option<Vec<String>>,
78 market_ids: Option<Vec<String>>,
79 min_market_start_time: Option<String>,
80 max_market_start_time: Option<String>,
81 stream_host: Option<String>,
82 stream_port: Option<u16>,
83 stream_heartbeat_secs: Option<u64>,
84 stream_heartbeat_timeout_secs: Option<u64>,
85 stream_reconnect_delay_initial_ms: u64,
86 stream_reconnect_delay_max_ms: u64,
87 stream_use_tls: bool,
88 stream_conflate_ms: Option<u64>,
89 subscription_delay_secs: Option<u64>,
90 subscribe_race_data: bool,
91 subscribe_cricket_data: bool,
92 book_snapshot_timeout_secs: Option<u64>,
93 ) -> Self {
94 Self {
95 account_currency: account_currency.unwrap_or_else(|| "GBP".to_string()),
96 username: username.map(SecretString::from),
97 password: password.map(SecretString::from),
98 app_key: app_key.map(SecretString::from),
99 proxy_url: proxy_url.map(SecretString::from),
100 request_rate_per_second,
101 default_min_notional,
102 event_type_ids: stringify_ids(event_type_ids),
103 event_type_names,
104 event_ids: stringify_ids(event_ids),
105 country_codes,
106 market_types,
107 market_ids,
108 min_market_start_time,
109 max_market_start_time,
110 stream_host,
111 stream_port,
112 stream_heartbeat_secs,
113 stream_heartbeat_timeout_secs,
114 stream_reconnect_delay_initial_ms,
115 stream_reconnect_delay_max_ms,
116 stream_use_tls,
117 stream_conflate_ms,
118 subscription_delay_secs: subscription_delay_secs.unwrap_or(3),
119 subscribe_race_data,
120 subscribe_cricket_data,
121 book_snapshot_timeout_secs: book_snapshot_timeout_secs
122 .unwrap_or(DEFAULT_BOOK_SNAPSHOT_TIMEOUT_SECS),
123 }
124 }
125
126 #[getter]
128 fn username(&self) -> Option<&str> {
129 self.username.as_ref().map(SecretString::expose_secret)
130 }
131
132 #[getter]
133 const fn has_proxy_url(&self) -> bool {
134 self.proxy_url.is_some()
135 }
136
137 fn __repr__(&self) -> String {
138 stringify!(BetfairDataClientConfig).to_string()
139 }
140}
141
142#[pymethods]
143#[pyo3_stub_gen::derive::gen_stub_pymethods]
144impl BetfairExecutionClientConfig {
145 #[new]
147 #[pyo3(signature = (
148 account_id = None,
149 account_currency = None,
150 username = None,
151 password = None,
152 app_key = None,
153 proxy_url = None,
154 request_rate_per_second = 5,
155 order_request_rate_per_second = 20,
156 stream_host = None,
157 stream_port = None,
158 stream_heartbeat_secs = None,
159 stream_heartbeat_timeout_secs = None,
160 stream_reconnect_delay_initial_ms = 2_000,
161 stream_reconnect_delay_max_ms = 30_000,
162 stream_use_tls = true,
163 stream_market_ids_filter = None,
164 ignore_external_orders = false,
165 calculate_account_state = true,
166 request_account_state_secs = 300,
167 reconcile_market_ids_only = false,
168 reconcile_market_ids = None,
169 use_market_version = false,
170 stream_gap_recovery_lookback_mins = 10,
171 ))]
172 #[expect(clippy::too_many_arguments)]
173 fn py_new(
174 account_id: Option<AccountId>,
175 account_currency: Option<String>,
176 username: Option<String>,
177 password: Option<String>,
178 app_key: Option<String>,
179 proxy_url: Option<String>,
180 request_rate_per_second: u32,
181 order_request_rate_per_second: u32,
182 stream_host: Option<String>,
183 stream_port: Option<u16>,
184 stream_heartbeat_secs: Option<u64>,
185 stream_heartbeat_timeout_secs: Option<u64>,
186 stream_reconnect_delay_initial_ms: u64,
187 stream_reconnect_delay_max_ms: u64,
188 stream_use_tls: bool,
189 stream_market_ids_filter: Option<Vec<String>>,
190 ignore_external_orders: bool,
191 calculate_account_state: bool,
192 request_account_state_secs: u64,
193 reconcile_market_ids_only: bool,
194 reconcile_market_ids: Option<Vec<String>>,
195 use_market_version: bool,
196 stream_gap_recovery_lookback_mins: u64,
197 ) -> Self {
198 Self {
199 account_id: account_id.unwrap_or_else(|| AccountId::from("BETFAIR-001")),
200 account_currency: account_currency.unwrap_or_else(|| "GBP".to_string()),
201 username: username.map(SecretString::from),
202 password: password.map(SecretString::from),
203 app_key: app_key.map(SecretString::from),
204 proxy_url: proxy_url.map(SecretString::from),
205 request_rate_per_second,
206 order_request_rate_per_second,
207 stream_host,
208 stream_port,
209 stream_heartbeat_secs,
210 stream_heartbeat_timeout_secs,
211 stream_reconnect_delay_initial_ms,
212 stream_reconnect_delay_max_ms,
213 stream_use_tls,
214 stream_market_ids_filter,
215 ignore_external_orders,
216 calculate_account_state,
217 request_account_state_secs,
218 reconcile_market_ids_only,
219 reconcile_market_ids,
220 use_market_version,
221 stream_gap_recovery_lookback_mins,
222 }
223 }
224
225 #[getter]
227 fn username(&self) -> Option<&str> {
228 self.username.as_ref().map(SecretString::expose_secret)
229 }
230
231 #[getter]
232 const fn has_proxy_url(&self) -> bool {
233 self.proxy_url.is_some()
234 }
235
236 fn __repr__(&self) -> String {
237 stringify!(BetfairExecutionClientConfig).to_string()
238 }
239}