use num_traits::{Float, FromPrimitive, One, Zero};
use crate::smooth::{factory::DefaultSmoothFactory, SmoothError};
pub enum SmoothType {
SMA,
EMA,
RMA,
MEDIAN
}
pub trait SmoothApply<T> where
T: Float + FromPrimitive + Zero + Clone + One + 'static,
{
fn apply(&self, data: &Vec<T>, window_size: usize, precision: Option<f64>) -> Result<Vec<T>, SmoothError>;
fn apply_inplase(&self, data: &mut Vec<T>, window_size: usize, precision: Option<f64>) -> Result<(), SmoothError>;
}
pub trait SmoothFactory<T>
where
T: Float + FromPrimitive + Clone + Zero + One + 'static,
{
fn create(&self, smooth_type: SmoothType) -> Box<dyn SmoothApply<T>>;
}
pub fn smooth_factory<T>() -> Box<dyn SmoothFactory<T>>
where
T: Float + FromPrimitive + Clone + Zero + One + 'static,
{
Box::new(DefaultSmoothFactory)
}
pub fn sma<T: Float + FromPrimitive + Clone + Zero + One + 'static>(
data: &Vec<T>,
window_size: usize
) -> Result<Vec<T>, SmoothError> {
let smooth = smooth_factory::<T>().create(SmoothType::SMA);
smooth.apply(data, window_size, None)
}
pub fn sma_inplase<T: Float + FromPrimitive + Clone + Zero + One + 'static>(
data: &mut Vec<T>,
window_size: usize
) -> Result<(), SmoothError> {
let smooth = smooth_factory::<T>().create(SmoothType::SMA);
smooth.apply_inplase(data, window_size, None)
}
pub fn ema<T: Float + FromPrimitive + Clone + Zero + One + 'static>(
data: &Vec<T>,
window_size: usize
) -> Result<Vec<T>, SmoothError> {
let smooth = smooth_factory::<T>().create(SmoothType::EMA);
smooth.apply(data, window_size, None)
}
pub fn rma<T: Float + FromPrimitive + Clone + Zero + One + 'static>(
data: &Vec<T>,
window_size: usize
) -> Result<Vec<T>, SmoothError> {
let smooth = smooth_factory::<T>().create(SmoothType::RMA);
smooth.apply(data, window_size, None)
}
pub fn median<T: Float + FromPrimitive + Clone + Zero + One + 'static>(
data: &Vec<T>,
window_size: usize,
precision: f64
) -> Result<Vec<T>, SmoothError> {
let smooth = smooth_factory::<T>().create(SmoothType::MEDIAN);
smooth.apply(data, window_size, Some(precision))
}