Skip to main content

nautilus_betfair/python/
mod.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 the Betfair adapter.
17
18pub mod config;
19pub mod factories;
20
21use nautilus_common::factories::{ClientConfig, DataClientFactory, ExecutionClientFactory};
22use nautilus_core::python::{to_pyruntime_err, to_pyvalue_err};
23use nautilus_system::get_global_pyo3_registry;
24use pyo3::prelude::*;
25
26use crate::{
27    common::consts::{BETFAIR, BETFAIR_CLIENT_ID, BETFAIR_VENUE},
28    config::{BetfairDataClientConfig, BetfairExecutionClientConfig},
29    factories::{BetfairDataClientFactory, BetfairExecutionClientFactory},
30};
31
32#[expect(clippy::needless_pass_by_value)]
33fn extract_betfair_data_factory(
34    py: Python<'_>,
35    factory: Py<PyAny>,
36) -> PyResult<Box<dyn DataClientFactory>> {
37    match factory.extract::<BetfairDataClientFactory>(py) {
38        Ok(factory) => Ok(Box::new(factory)),
39        Err(e) => Err(to_pyvalue_err(format!(
40            "Failed to extract BetfairDataClientFactory: {e}"
41        ))),
42    }
43}
44
45#[expect(clippy::needless_pass_by_value)]
46fn extract_betfair_exec_factory(
47    py: Python<'_>,
48    factory: Py<PyAny>,
49) -> PyResult<Box<dyn ExecutionClientFactory>> {
50    match factory.extract::<BetfairExecutionClientFactory>(py) {
51        Ok(factory) => Ok(Box::new(factory)),
52        Err(e) => Err(to_pyvalue_err(format!(
53            "Failed to extract BetfairExecutionClientFactory: {e}"
54        ))),
55    }
56}
57
58#[expect(clippy::needless_pass_by_value)]
59fn extract_betfair_data_config(
60    py: Python<'_>,
61    config: Py<PyAny>,
62) -> PyResult<Box<dyn ClientConfig>> {
63    match config.extract::<BetfairDataClientConfig>(py) {
64        Ok(config) => Ok(Box::new(config)),
65        Err(e) => Err(to_pyvalue_err(format!(
66            "Failed to extract BetfairDataClientConfig: {e}"
67        ))),
68    }
69}
70
71#[expect(clippy::needless_pass_by_value)]
72fn extract_betfair_exec_config(
73    py: Python<'_>,
74    config: Py<PyAny>,
75) -> PyResult<Box<dyn ClientConfig>> {
76    match config.extract::<BetfairExecutionClientConfig>(py) {
77        Ok(config) => Ok(Box::new(config)),
78        Err(e) => Err(to_pyvalue_err(format!(
79            "Failed to extract BetfairExecutionClientConfig: {e}"
80        ))),
81    }
82}
83
84/// Betfair adapter Python module.
85///
86/// Exposed through `nautilus_trader.adapters.betfair`.
87///
88/// # Errors
89///
90/// Returns an error if module initialization fails.
91#[pymodule]
92pub fn betfair(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
93    m.add(stringify!(BETFAIR), BETFAIR)?;
94    m.add(stringify!(BETFAIR_CLIENT_ID), *BETFAIR_CLIENT_ID)?;
95    m.add(stringify!(BETFAIR_VENUE), *BETFAIR_VENUE)?;
96    m.add_class::<BetfairDataClientConfig>()?;
97    m.add_class::<BetfairDataClientFactory>()?;
98    m.add_class::<BetfairExecutionClientConfig>()?;
99    m.add_class::<BetfairExecutionClientFactory>()?;
100
101    let registry = get_global_pyo3_registry();
102
103    if let Err(e) =
104        registry.register_factory_extractor(BETFAIR.to_string(), extract_betfair_data_factory)
105    {
106        return Err(to_pyruntime_err(format!(
107            "Failed to register Betfair data factory extractor: {e}"
108        )));
109    }
110
111    if let Err(e) =
112        registry.register_exec_factory_extractor(BETFAIR.to_string(), extract_betfair_exec_factory)
113    {
114        return Err(to_pyruntime_err(format!(
115            "Failed to register Betfair exec factory extractor: {e}"
116        )));
117    }
118
119    if let Err(e) = registry.register_config_extractor(
120        "BetfairDataClientConfig".to_string(),
121        extract_betfair_data_config,
122    ) {
123        return Err(to_pyruntime_err(format!(
124            "Failed to register Betfair data config extractor: {e}"
125        )));
126    }
127
128    if let Err(e) = registry.register_config_extractor(
129        "BetfairExecutionClientConfig".to_string(),
130        extract_betfair_exec_config,
131    ) {
132        return Err(to_pyruntime_err(format!(
133            "Failed to register Betfair exec config extractor: {e}"
134        )));
135    }
136
137    Ok(())
138}