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}