nautilus_indicators/python/momentum/
stochastics.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 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_model::data::Bar;
17use pyo3::prelude::*;
18
19use crate::{
20    average::MovingAverageType,
21    indicator::Indicator,
22    momentum::stochastics::{Stochastics, StochasticsDMethod},
23};
24
25#[pymethods]
26impl Stochastics {
27    /// Creates a new Stochastics indicator.
28    ///
29    /// Parameters
30    /// ----------
31    /// period_k : int
32    ///     The lookback period for %K calculation (highest high / lowest low).
33    /// period_d : int
34    ///     The smoothing period for %D calculation.
35    /// slowing : int, optional
36    ///     The slowing period for %K smoothing. Default is 1 (no slowing).
37    ///     Use >1 for MA smoothed %K.
38    /// ma_type : MovingAverageType, optional
39    ///     The MA type for slowing and MA-based %D. Default is Exponential.
40    /// d_method : StochasticsDMethod, optional
41    ///     The %D calculation method. Default is Ratio (Nautilus original).
42    ///     Use MovingAverage for MA smoothed %D.
43    #[new]
44    #[pyo3(signature = (period_k, period_d, slowing=None, ma_type=None, d_method=None))]
45    #[must_use]
46    pub fn py_new(
47        period_k: usize,
48        period_d: usize,
49        slowing: Option<usize>,
50        ma_type: Option<MovingAverageType>,
51        d_method: Option<StochasticsDMethod>,
52    ) -> Self {
53        Self::new_with_params(
54            period_k,
55            period_d,
56            slowing.unwrap_or(1),
57            ma_type.unwrap_or(MovingAverageType::Exponential),
58            d_method.unwrap_or(StochasticsDMethod::Ratio),
59        )
60    }
61
62    fn __repr__(&self) -> String {
63        format!(
64            "Stochastics({},{},{},{:?},{:?})",
65            self.period_k, self.period_d, self.slowing, self.ma_type, self.d_method
66        )
67    }
68
69    #[getter]
70    #[pyo3(name = "name")]
71    fn py_name(&self) -> String {
72        self.name()
73    }
74
75    #[getter]
76    #[pyo3(name = "period_k")]
77    const fn py_period_k(&self) -> usize {
78        self.period_k
79    }
80
81    #[getter]
82    #[pyo3(name = "period_d")]
83    const fn py_period_d(&self) -> usize {
84        self.period_d
85    }
86
87    #[getter]
88    #[pyo3(name = "slowing")]
89    const fn py_slowing(&self) -> usize {
90        self.slowing
91    }
92
93    #[getter]
94    #[pyo3(name = "ma_type")]
95    const fn py_ma_type(&self) -> MovingAverageType {
96        self.ma_type
97    }
98
99    #[getter]
100    #[pyo3(name = "d_method")]
101    const fn py_d_method(&self) -> StochasticsDMethod {
102        self.d_method
103    }
104
105    #[getter]
106    #[pyo3(name = "has_inputs")]
107    fn py_has_inputs(&self) -> bool {
108        self.has_inputs()
109    }
110
111    #[getter]
112    #[pyo3(name = "value_k")]
113    const fn py_value_k(&self) -> f64 {
114        self.value_k
115    }
116
117    #[getter]
118    #[pyo3(name = "value_d")]
119    const fn py_value_d(&self) -> f64 {
120        self.value_d
121    }
122
123    #[getter]
124    #[pyo3(name = "initialized")]
125    const fn py_initialized(&self) -> bool {
126        self.initialized
127    }
128
129    #[pyo3(name = "update_raw")]
130    fn py_update_raw(&mut self, high: f64, low: f64, close: f64) {
131        self.update_raw(high, low, close);
132    }
133
134    #[pyo3(name = "handle_bar")]
135    fn py_handle_bar(&mut self, bar: &Bar) {
136        self.handle_bar(bar);
137    }
138
139    #[pyo3(name = "reset")]
140    fn py_reset(&mut self) {
141        self.reset();
142    }
143}