Skip to main content

nautilus_indicators/python/volatility/
fuzzy.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
16use nautilus_core::python::to_pyvalue_err;
17use nautilus_model::data::Bar;
18use pyo3::prelude::*;
19
20use crate::{
21    indicator::Indicator,
22    python::float_precision,
23    volatility::fuzzy::{
24        CandleBodySize, CandleDirection, CandleSize, CandleWickSize, FuzzyCandle, FuzzyCandlesticks,
25    },
26};
27
28#[pymethods]
29#[pyo3_stub_gen::derive::gen_stub_pymethods]
30impl CandleBodySize {
31    const fn __hash__(&self) -> isize {
32        *self as isize
33    }
34}
35
36#[pymethods]
37#[pyo3_stub_gen::derive::gen_stub_pymethods]
38impl CandleDirection {
39    const fn __hash__(&self) -> isize {
40        *self as isize
41    }
42}
43
44#[pymethods]
45#[pyo3_stub_gen::derive::gen_stub_pymethods]
46impl CandleSize {
47    const fn __hash__(&self) -> isize {
48        *self as isize
49    }
50}
51
52#[pymethods]
53#[pyo3_stub_gen::derive::gen_stub_pymethods]
54impl CandleWickSize {
55    const fn __hash__(&self) -> isize {
56        *self as isize
57    }
58}
59
60#[pymethods]
61#[pyo3_stub_gen::derive::gen_stub_pymethods]
62impl FuzzyCandle {
63    #[new]
64    #[must_use]
65    pub const fn py_new(
66        direction: CandleDirection,
67        size: CandleSize,
68        body_size: CandleBodySize,
69        upper_wick_size: CandleWickSize,
70        lower_wick_size: CandleWickSize,
71    ) -> Self {
72        Self::new(direction, size, body_size, upper_wick_size, lower_wick_size)
73    }
74
75    fn __repr__(&self) -> String {
76        format!(
77            "FuzzyCandle({},{},{},{},{})",
78            self.direction, self.size, self.body_size, self.upper_wick_size, self.lower_wick_size
79        )
80    }
81
82    #[getter]
83    #[pyo3(name = "direction")]
84    const fn py_direction(&self) -> CandleDirection {
85        self.direction
86    }
87
88    #[getter]
89    #[pyo3(name = "size")]
90    const fn py_size(&self) -> CandleSize {
91        self.size
92    }
93
94    #[getter]
95    #[pyo3(name = "body_size")]
96    const fn py_body_size(&self) -> CandleBodySize {
97        self.body_size
98    }
99
100    #[getter]
101    #[pyo3(name = "upper_wick_size")]
102    const fn py_upper_wick_size(&self) -> CandleWickSize {
103        self.upper_wick_size
104    }
105
106    #[getter]
107    #[pyo3(name = "lower_wick_size")]
108    const fn py_lower_wick_size(&self) -> CandleWickSize {
109        self.lower_wick_size
110    }
111}
112
113#[pymethods]
114#[pyo3_stub_gen::derive::gen_stub_pymethods]
115impl FuzzyCandlesticks {
116    /// Creates a new `FuzzyCandlesticks` instance.
117    ///
118    /// A zero period is accepted.
119    #[new]
120    pub fn py_new(
121        period: usize,
122        threshold1: f64,
123        threshold2: f64,
124        threshold3: f64,
125        threshold4: f64,
126    ) -> PyResult<Self> {
127        Self::new_checked(period, threshold1, threshold2, threshold3, threshold4)
128            .map_err(to_pyvalue_err)
129    }
130
131    fn __repr__(&self) -> String {
132        format!(
133            "FuzzyCandlesticks({},{},{},{},{})",
134            self.period, self.threshold1, self.threshold2, self.threshold3, self.threshold4
135        )
136    }
137
138    #[getter]
139    #[pyo3(name = "name")]
140    fn py_name(&self) -> String {
141        self.name()
142    }
143
144    #[getter]
145    #[pyo3(name = "period")]
146    const fn py_period(&self) -> usize {
147        self.period
148    }
149
150    #[getter]
151    #[pyo3(name = "threshold1")]
152    const fn py_threshold1(&self) -> f64 {
153        self.threshold1
154    }
155
156    #[getter]
157    #[pyo3(name = "threshold2")]
158    const fn py_threshold2(&self) -> f64 {
159        self.threshold2
160    }
161
162    #[getter]
163    #[pyo3(name = "threshold3")]
164    const fn py_threshold3(&self) -> f64 {
165        self.threshold3
166    }
167
168    #[getter]
169    #[pyo3(name = "threshold4")]
170    const fn py_threshold4(&self) -> f64 {
171        self.threshold4
172    }
173
174    #[getter]
175    #[pyo3(name = "has_inputs")]
176    fn py_has_inputs(&self) -> bool {
177        self.has_inputs()
178    }
179
180    #[getter]
181    #[pyo3(name = "value")]
182    const fn py_value(&self) -> FuzzyCandle {
183        self.value
184    }
185
186    #[getter]
187    #[pyo3(name = "vector")]
188    fn py_vector(&self) -> Vec<i32> {
189        self.vector.clone()
190    }
191
192    #[getter]
193    #[pyo3(name = "initialized")]
194    const fn py_initialized(&self) -> bool {
195        self.initialized
196    }
197
198    #[pyo3(name = "update_raw")]
199    fn py_update_raw(&mut self, open: f64, high: f64, low: f64, close: f64) {
200        self.update_raw(open, high, low, close);
201    }
202
203    #[pyo3(name = "handle_bar")]
204    fn py_handle_bar(&mut self, bar: &Bar) -> PyResult<()> {
205        float_precision::check_bar(bar)?;
206        self.handle_bar(bar);
207        Ok(())
208    }
209
210    #[pyo3(name = "reset")]
211    fn py_reset(&mut self) {
212        self.reset();
213    }
214}