nautilus_analysis/python/statistics/
long_ratio.rs1use std::collections::BTreeMap;
17
18#[allow(unused_imports)] use nautilus_core::UnixNanos;
20use nautilus_model::enums::OrderSide;
21use pyo3::prelude::*;
22
23use crate::{statistic::PortfolioStatistic, statistics::long_ratio::LongRatio};
24
25#[pymethods]
26#[pyo3_stub_gen::derive::gen_stub_pymethods]
27impl LongRatio {
28 #[new]
29 #[pyo3(signature = (precision=None))]
30 fn py_new(precision: Option<usize>) -> Self {
31 Self::new(precision)
32 }
33
34 fn __repr__(&self) -> String {
35 self.to_string()
36 }
37
38 #[getter]
39 #[pyo3(name = "name")]
40 fn py_name(&self) -> String {
41 self.name()
42 }
43
44 #[pyo3(name = "calculate_from_positions")]
45 #[expect(clippy::needless_pass_by_value)]
46 fn py_calculate_from_positions(
47 &mut self,
48 py: Python,
49 positions: Vec<Py<PyAny>>,
50 ) -> PyResult<Option<f64>> {
51 if positions.is_empty() {
52 return Ok(None);
53 }
54
55 let mut longs = 0;
58
59 for position in &positions {
60 let entry = position.getattr(py, "entry")?;
61 let entry_value: u8 = entry.extract(py)?;
62 if entry_value == OrderSide::Buy as u8 {
63 longs += 1;
64 }
65 }
66
67 let value = f64::from(longs) / positions.len() as f64;
68 let scale = 10f64.powi(self.precision as i32);
69 Ok(Some((value * scale).round() / scale))
70 }
71
72 #[pyo3(name = "calculate_from_realized_pnls")]
73 fn py_calculate_from_realized_pnls(&mut self, _realized_pnls: Vec<f64>) -> Option<f64> {
74 None
75 }
76
77 #[pyo3(name = "calculate_from_returns")]
78 #[allow(unused_variables)] fn py_calculate_from_returns(&mut self, _returns: BTreeMap<u64, f64>) -> Option<f64> {
80 None
81 }
82}