Skip to main content

nautilus_backtest/python/
result.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 [`BacktestResult`] type.
17
18use std::collections::HashMap;
19
20use nautilus_core::UUID4;
21
22use crate::result::BacktestResult;
23
24#[pyo3_stub_gen::derive::gen_stub_pymethods]
25#[pyo3::pymethods]
26impl BacktestResult {
27    #[getter]
28    #[pyo3(name = "trader_id")]
29    fn py_trader_id(&self) -> &str {
30        &self.trader_id
31    }
32
33    #[getter]
34    #[pyo3(name = "machine_id")]
35    fn py_machine_id(&self) -> &str {
36        &self.machine_id
37    }
38
39    #[getter]
40    #[pyo3(name = "instance_id")]
41    const fn py_instance_id(&self) -> UUID4 {
42        self.instance_id
43    }
44
45    #[getter]
46    #[pyo3(name = "run_config_id")]
47    fn py_run_config_id(&self) -> Option<&str> {
48        self.run_config_id.as_deref()
49    }
50
51    #[getter]
52    #[pyo3(name = "elapsed_time_secs")]
53    const fn py_elapsed_time_secs(&self) -> f64 {
54        self.elapsed_time_secs
55    }
56
57    #[getter]
58    #[pyo3(name = "iterations")]
59    const fn py_iterations(&self) -> usize {
60        self.iterations
61    }
62
63    #[getter]
64    #[pyo3(name = "total_events")]
65    const fn py_total_events(&self) -> usize {
66        self.total_events
67    }
68
69    #[getter]
70    #[pyo3(name = "total_orders")]
71    const fn py_total_orders(&self) -> usize {
72        self.total_orders
73    }
74
75    #[getter]
76    #[pyo3(name = "total_positions")]
77    const fn py_total_positions(&self) -> usize {
78        self.total_positions
79    }
80
81    #[getter]
82    #[pyo3(name = "stats_pnls")]
83    fn py_stats_pnls(&self) -> HashMap<String, HashMap<String, f64>> {
84        self.stats_pnls
85            .iter()
86            .map(|(k, v)| {
87                (
88                    k.clone(),
89                    v.iter().map(|(k2, v2)| (k2.clone(), *v2)).collect(),
90                )
91            })
92            .collect()
93    }
94
95    #[getter]
96    #[pyo3(name = "stats_returns")]
97    fn py_stats_returns(&self) -> HashMap<String, f64> {
98        self.stats_returns
99            .iter()
100            .map(|(k, v)| (k.clone(), *v))
101            .collect()
102    }
103
104    #[getter]
105    #[pyo3(name = "stats_general")]
106    fn py_stats_general(&self) -> HashMap<String, f64> {
107        self.stats_general
108            .iter()
109            .map(|(k, v)| (k.clone(), *v))
110            .collect()
111    }
112
113    fn __repr__(&self) -> String {
114        format!(
115            "BacktestResult(trader_id='{}', elapsed={:.2}s, iterations={}, orders={}, positions={})",
116            self.trader_id,
117            self.elapsed_time_secs,
118            self.iterations,
119            self.total_orders,
120            self.total_positions,
121        )
122    }
123}