1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
use super::{Error, Sequence};
use std::fmt;

/// Trait for creating methods for timeseries
///
/// # Regular methods usage
///
/// ### Iterate over vector's values
///
/// ```
/// use yata::methods::SMA;
/// use yata::prelude::*;
///
/// let s: Vec<_> = vec![1.,2.,3.,4.,5.,6.,7.,8.,9.,10.];
/// let mut ma = SMA::new(2, s[0]).unwrap();
///
/// s.iter().enumerate().for_each(|(index, &value)| {
/// 	assert_eq!(ma.next(value), (value + s[index.saturating_sub(1)])/2.);
/// });
/// ```
///
/// ### Get a whole new vector over the input vector
///
/// ```
/// use yata::methods::SMA;
/// use yata::prelude::*;
///
/// let s: Vec<_> = vec![1.,2.,3.,4.,5.,6.,7.,8.,9.,10.];
/// let mut ma = SMA::new(2, s[0]).unwrap();
///
/// let result = ma.over(s.iter().copied());
/// assert_eq!(result.as_slice(), &[1., 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5]);
/// ```
///
/// ### Change vector values using method
///
/// ```
/// use yata::core::Sequence;
/// use yata::methods::SMA;
/// use yata::prelude::*;
///
/// let mut s: Sequence<_> = Sequence::from(vec![1.,2.,3.,4.,5.,6.,7.,8.,9.,10.]);
/// let mut ma = SMA::new(2, s[0]).unwrap();
///
/// s.apply(&mut ma);
/// assert_eq!(s.as_slice(), &[1., 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5]);
/// ```
///
/// # Be advised
/// 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.
pub trait Method: fmt::Debug {
	/// Method parameters
	type Params;
	/// Input value type
	type Input: Copy;
	/// Output value type
	type Output: Copy; // = Self::Input;

	/// Static method for creating an instance of the method with given `parameters` and initial `value` (simply first input value)
	fn new(parameters: Self::Params, initial_value: Self::Input) -> Result<Self, Error>
	where
		Self: Sized;

	/// Generates next output value based on the given input `value`
	fn next(&mut self, value: Self::Input) -> Self::Output;

	/// Returns a name of the method
	fn name(&self) -> &str {
		let parts = std::any::type_name::<Self>().split("::");
		parts.last().unwrap_or_default()
	}

	/// Returns memory size of the method `(size, align)`
	fn memsize(&self) -> (usize, usize)
	where
		Self: Sized,
	{
		(std::mem::size_of::<Self>(), std::mem::align_of::<Self>())
	}

	/// Creates an `iterator` which produces values by the `Method` over given input data `Iterator`
	fn iter_data<I>(&mut self, input: I) -> MethodOverIterator<Self, I>
	where
		I: Iterator<Item = Self::Input>,
		Self: Sized,
	{
		MethodOverIterator::new(self, input)
	}

	/// Iterates the `Method` over the given `Iterator` and returns timeserie of output values
	///
	/// # Guarantees
	///
	/// The length of an output `Sequence` is always equal to the length of input one
	/// ```
	/// use yata::methods::SMA;
	/// use yata::prelude::*;
	///
	/// let s: Vec<_> = vec![1.,2.,3.,4.,5.,6.,7.,8.,9.,10.];
	/// let mut ma = SMA::new(5, s[0]).unwrap();
	///
	/// let result = ma.over(s.iter().copied());
	/// assert_eq!(result.len(), s.len());
	/// ```
	///
	/// ```
	/// use yata::methods::SMA;
	/// use yata::prelude::*;
	///
	/// let s: Vec<_> = vec![1.,2.,3.,4.,5.,6.,7.,8.,9.,10.];
	/// let mut ma = SMA::new(100, s[0]).unwrap();
	///
	/// let result = ma.over(s.iter().copied());
	/// assert_eq!(result.len(), s.len());
	/// ```
	#[inline]
	fn over<I>(&mut self, sequence: I) -> Sequence<Self::Output>
	where
		I: Iterator<Item = Self::Input>,
		Self: Sized,
	{
		sequence.map(|x| self.next(x)).collect()
	}
}

#[derive(Debug)]
pub struct MethodOverIterator<'a, T: Method, I: Iterator<Item = T::Input>> {
	method: &'a mut T,
	over: I,
}

impl<'a, T: Method, I: Iterator<Item = T::Input>> MethodOverIterator<'a, T, I> {
	pub fn new(method: &'a mut T, over: I) -> Self {
		Self { method, over }
	}
}

impl<'a, T: Method, I: Iterator<Item = T::Input>> Iterator for MethodOverIterator<'a, T, I> {
	type Item = T::Output;

	fn next(&mut self) -> Option<Self::Item> {
		let input = self.over.next()?;
		let output = self.method.next(input);
		Some(output)
	}
}