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
use crate::core::Method;
use crate::core::{ValueType, OHLCV};
use std::ops::Add;

/// Implements some methods for sequence manipulations.
pub trait Sequence<T>: AsRef<[T]> {
	/// Validates the sequence.
	fn validate(&self) -> bool;

	/// Calls [`Method`](crate::core::Method) over the slice and returns `Vec` of result values.
	#[inline]
	fn call<M>(&self, method: &mut M) -> Vec<M::Output>
	where
		M: Method<Input = T>,
	{
		self.as_ref().iter().map(|x| method.next(x)).collect()
	}

	/// Applies [`Method`](crate::core::Method) on the slice in-place.
	#[inline]
	fn apply<M>(&mut self, method: &mut M)
	where
		M: Method<Input = T, Output = T>,
		Self: AsMut<[T]>,
	{
		self.as_mut().iter_mut().for_each(|x| *x = method.next(x));
	}

	/// Returns a reference to the first value in the sequence or `None` if it's empty.
	#[inline]
	fn get_initial_value(&self) -> Option<&T> {
		self.as_ref().first()
	}

	/// Returns a reference to the first value in the sequence or `None` if it's empty.
	#[inline]
	fn get_initial_value_mut(&mut self) -> Option<&mut T>
	where
		Self: AsMut<[T]>,
	{
		self.as_mut().first_mut()
	}

	/// Converts timeframe of the series
	///
	/// See also [`CollapseTimeframe`](crate::methods::CollapseTimeframe) method.
	fn collapse_timeframe(&self, size: usize, continuous: bool) -> Vec<T>
	where
		T: OHLCV + Clone + Add<Output = T>,
	{
		#[inline]
		fn reduce<T: OHLCV + Clone + Add<Output = T>>(window: &[T]) -> T {
			window.iter().cloned().reduce(Add::add).unwrap()
		}

		self.as_ref()
			.windows(size)
			.step_by(if continuous { 1 } else { size })
			.map(reduce)
			.collect()
	}
}

impl<Q: AsRef<[ValueType]>> Sequence<ValueType> for Q {
	#[inline]
	fn validate(&self) -> bool {
		self.as_ref().iter().copied().all(ValueType::is_finite)
	}
}

impl<T: OHLCV, Q: AsRef<[T]>> Sequence<T> for Q {
	#[inline]
	fn validate(&self) -> bool {
		self.as_ref().iter().all(OHLCV::validate)
	}
}