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