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,
28    config::{BetfairDataConfig, BetfairExecConfig},
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::<BetfairDataConfig>(py) {
64        Ok(config) => Ok(Box::new(config)),
65        Err(e) => Err(to_pyvalue_err(format!(
66            "Failed to extract BetfairDataConfig: {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::<BetfairExecConfig>(py) {
77        Ok(config) => Ok(Box::new(config)),
78        Err(e) => Err(to_pyvalue_err(format!(
79            "Failed to extract BetfairExecConfig: {e}"
80        ))),
81    }
82}
83
84/// Betfair adapter Python module.
85///
86/// Loaded as `nautilus_pyo3.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_class::<BetfairDataConfig>()?;
94    m.add_class::<BetfairExecConfig>()?;
95    m.add_class::<BetfairDataClientFactory>()?;
96    m.add_class::<BetfairExecutionClientFactory>()?;
97
98    let registry = get_global_pyo3_registry();
99
100    if let Err(e) =
101        registry.register_factory_extractor(BETFAIR.to_string(), extract_betfair_data_factory)
102    {
103        return Err(to_pyruntime_err(format!(
104            "Failed to register Betfair data factory extractor: {e}"
105        )));
106    }
107
108    if let Err(e) =
109        registry.register_exec_factory_extractor(BETFAIR.to_string(), extract_betfair_exec_factory)
110    {
111        return Err(to_pyruntime_err(format!(
112            "Failed to register Betfair exec factory extractor: {e}"
113        )));
114    }
115
116    if let Err(e) = registry
117        .register_config_extractor("BetfairDataConfig".to_string(), extract_betfair_data_config)
118    {
119        return Err(to_pyruntime_err(format!(
120            "Failed to register Betfair data config extractor: {e}"
121        )));
122    }
123
124    if let Err(e) = registry
125        .register_config_extractor("BetfairExecConfig".to_string(), extract_betfair_exec_config)
126    {
127        return Err(to_pyruntime_err(format!(
128            "Failed to register Betfair exec config extractor: {e}"
129        )));
130    }
131
132    Ok(())
133}