yata/core/method.rs
1use super::{Error, Sequence};
2use crate::helpers::{WithHistory, WithLastValue};
3use std::fmt;
4
5type BoxedFnMethod<'a, M> = Box<dyn FnMut(&'a <M as Method>::Input) -> <M as Method>::Output>;
6
7/// Trait for creating methods for timeseries
8///
9/// # Regular methods usage
10///
11/// ### Iterate over vector's values
12///
13/// ```
14/// use yata::methods::SMA;
15/// use yata::prelude::*;
16///
17/// let s: Vec<_> = vec![1.,2.,3.,4.,5.,6.,7.,8.,9.,10.];
18/// let mut ma = SMA::new(2, &s[0]).unwrap();
19///
20/// s.iter().enumerate().for_each(|(index, value)| {
21/// assert_eq!(ma.next(value), (*value + s[index.saturating_sub(1)])/2.);
22/// });
23/// ```
24///
25/// ### Get a whole new vector over the input vector
26///
27/// You can call method `over` any `Sequence`:
28/// ```
29/// use yata::methods::SMA;
30/// use yata::prelude::*;
31///
32/// let s: Vec<_> = vec![1.,2.,3.,4.,5.,6.,7.,8.,9.,10.];
33/// let mut ma = SMA::new(2, &s[0]).unwrap();
34///
35/// let result = ma.over(s);
36/// assert_eq!(result.as_slice(), &[1., 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5]);
37/// ```
38///
39/// Or you can provide `Method` to `Sequence`:
40/// ```
41/// use yata::methods::SMA;
42/// use yata::prelude::*;
43///
44/// let s: Vec<_> = vec![1.,2.,3.,4.,5.,6.,7.,8.,9.,10.];
45/// let mut ma = SMA::new(2, &s[0]).unwrap();
46///
47/// let result = s.call(&mut ma);
48/// assert_eq!(result.as_slice(), &[1., 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5]);
49/// ```
50///
51/// Or you can even change `Sequence` values in-place:
52/// ```
53/// use yata::methods::SMA;
54/// use yata::prelude::*;
55///
56/// let mut s: Vec<_> = vec![1.,2.,3.,4.,5.,6.,7.,8.,9.,10.];
57/// let mut ma = SMA::new(2, &s[0]).unwrap();
58///
59/// s.apply(&mut ma);
60/// assert_eq!(s.as_slice(), &[1., 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5]);
61/// ```
62///
63/// # Be advised
64/// There is no `reset` method on the trait. If you need reset a state of the `Method` instance, you should just create a new one.
65pub trait Method {
66 /// Method parameters
67 type Params;
68 /// Input value type
69 type Input: ?Sized;
70 /// Output value type
71 type Output;
72
73 /// Static method for creating an instance of the method with given `parameters` and initial `value` (simply first input value)
74 fn new(parameters: Self::Params, initial_value: &Self::Input) -> Result<Self, Error>
75 where
76 Self: Sized;
77
78 /// Generates next output value based on the given input `value`
79 fn next(&mut self, value: &Self::Input) -> Self::Output;
80
81 /// Creates an instance of the method with given `parameters` and initial `value`, wrapped by historical data holder
82 fn with_history(
83 parameters: Self::Params,
84 initial_value: &Self::Input,
85 ) -> Result<WithHistory<Self, Self::Output>, Error>
86 where
87 Self: Sized,
88 Self::Output: fmt::Debug + Clone,
89 {
90 WithHistory::new(parameters, initial_value)
91 }
92
93 /// Creates an instance of the method with given `parameters` and initial `value`, wrapped by last produced value holder
94 fn with_last_value(
95 parameters: Self::Params,
96 initial_value: &Self::Input,
97 ) -> Result<WithLastValue<Self, Self::Output>, Error>
98 where
99 Self: Sized,
100 Self::Output: fmt::Debug + Clone,
101 {
102 WithLastValue::new(parameters, initial_value)
103 }
104
105 /// Returns a name of the method
106 fn name(&self) -> &str {
107 let parts = std::any::type_name::<Self>().split("::");
108 parts.last().unwrap_or_default()
109 }
110
111 /// Returns memory size of the method `(size, align)`
112 #[deprecated]
113 fn memsize(&self) -> (usize, usize)
114 where
115 Self: Sized,
116 {
117 (std::mem::size_of::<Self>(), std::mem::align_of::<Self>())
118 }
119
120 /// Iterates the `Method` over the given `inputs` slice and returns `Vec` of output values.
121 ///
122 /// # Guarantees
123 ///
124 /// The length of an output `Vec` is always equal to the length of an `inputs` slice.
125 /// ```
126 /// use yata::methods::SMA;
127 /// use yata::prelude::*;
128 ///
129 /// let s: Vec<_> = vec![1.,2.,3.,4.,5.,6.,7.,8.,9.,10.];
130 /// let mut ma = SMA::new(5, &s[0]).unwrap();
131 ///
132 /// let result = ma.over(&s);
133 /// assert_eq!(result.len(), s.len());
134 /// ```
135 ///
136 /// ```
137 /// use yata::methods::SMA;
138 /// use yata::prelude::*;
139 ///
140 /// let s: Vec<_> = vec![1.,2.,3.,4.,5.,6.,7.,8.,9.,10.];
141 /// let mut ma = SMA::new(100, &s[0]).unwrap();
142 ///
143 /// let result = ma.over(&s);
144 /// assert_eq!(result.len(), s.len());
145 /// ```
146 #[inline]
147 fn over<S>(&mut self, inputs: S) -> Vec<Self::Output>
148 where
149 S: Sequence<Self::Input>,
150 Self::Input: Sized,
151 Self: Sized,
152 {
153 inputs.call(self)
154 }
155
156 /// Applies method to the sequence in-place.
157 fn apply<T, S>(&mut self, sequence: &mut S)
158 where
159 S: Sequence<T> + AsMut<[T]> + ?Sized,
160 Self: Method<Input = T, Output = T> + Sized,
161 {
162 sequence.apply(self);
163 }
164
165 /// Creates new `Method` instance and iterates it over the given `inputs` slice and returns `Vec` of output values.
166 ///
167 /// # Guarantees
168 ///
169 /// The length of an output `Vec` is always equal to the length of an `inputs` slice.
170 fn new_over<S>(parameters: Self::Params, inputs: S) -> Result<Vec<Self::Output>, Error>
171 where
172 S: Sequence<Self::Input>,
173 Self::Input: Sized,
174 Self: Sized,
175 {
176 match inputs.get_initial_value() {
177 Some(v) => {
178 let mut method = Self::new(parameters, v)?;
179 Ok(inputs.call(&mut method))
180 }
181 None => Ok(Vec::new()),
182 }
183 }
184
185 /// Creates new `Method` instance and applies it to the `sequence`.
186 fn new_apply<T, S>(parameters: Self::Params, sequence: &mut S) -> Result<(), Error>
187 where
188 S: Sequence<T> + AsMut<[T]>,
189 Self: Method<Input = T, Output = T> + Sized,
190 {
191 let initial_value = {
192 // Why do we need to get immutable reference to get initial value?
193 // If try to remove it, then compile error occured.
194 // Looks like some Rust type system bug?
195 let seq = &*sequence;
196
197 match seq.get_initial_value() {
198 Some(v) => v,
199 None => return Ok(()),
200 }
201 };
202
203 let mut m = Self::new(parameters, initial_value)?;
204 sequence.apply(&mut m);
205 Ok(())
206 }
207
208 /// Creates a function from the `Method` instance
209 fn into_fn<'a>(mut self) -> BoxedFnMethod<'a, Self>
210 where
211 Self: Sized + 'static,
212 Self::Input: 'static,
213 {
214 let f = move |x| self.next(x);
215 Box::new(f)
216 }
217
218 /// Creates new function based on the method
219 fn new_fn(
220 params: Self::Params,
221 initial_value: &Self::Input,
222 ) -> Result<BoxedFnMethod<Self>, Error>
223 where
224 Self: Sized + 'static,
225 {
226 let instance = Self::new(params, initial_value)?;
227
228 Ok(instance.into_fn())
229 }
230}