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