use crate::errors::Error;
use cpython::{exc, PyErr, PyResult, Python};
pub struct Roc {
input: Vec<f64>,
time_period: i32,
}
impl Roc {
pub fn new(input: Vec<f64>, time_period: i32) -> Result<Self, Error> {
if input.is_empty() {
return Err(Error::InvalidParams(String::from("Input Vector is Empty")));
}
if time_period < 2 {
return Err(Error::InvalidParams(String::from(
"Time Period should be greater than 2",
)));
}
Ok(Self { input, time_period })
}
pub fn rocp(&self) -> Vec<f64> {
let mut output_vector = Vec::with_capacity(self.input.len());
let start_index = self.time_period as usize;
let trailing_index = start_index - self.time_period as usize;
for idx in start_index..self.input.len() {
let tmp = self.input[trailing_index];
if tmp != 0.0 {
let result = (self.input[idx] - tmp) / tmp;
output_vector.push(result);
} else {
output_vector.push(0.0)
}
}
output_vector
}
pub fn roc(&self) -> Vec<f64> {
let mut output_vector = Vec::with_capacity(self.input.len());
let start_index = self.time_period as usize;
let trailing_index = start_index - self.time_period as usize;
for idx in start_index..self.input.len() {
let tmp = self.input[trailing_index];
if tmp != 0.0 {
let result = ((self.input[idx] / tmp) - 1.0) * 100.0;
output_vector.push(result);
} else {
output_vector.push(0.0)
}
}
output_vector
}
pub fn rocr(&self) -> Vec<f64> {
let mut output_vector = Vec::with_capacity(self.input.len());
let start_index = self.time_period as usize;
let trailing_index = start_index - self.time_period as usize;
for idx in start_index..self.input.len() {
let tmp = self.input[trailing_index];
if tmp != 0.0 {
let result = self.input[idx] / tmp;
output_vector.push(result);
} else {
output_vector.push(0.0)
}
}
output_vector
}
pub fn rocr100(&self) -> Vec<f64> {
let mut output_vector = Vec::with_capacity(self.input.len());
let start_index = self.time_period as usize;
let trailing_index = start_index - self.time_period as usize;
for idx in start_index..self.input.len() {
let tmp = self.input[trailing_index];
if tmp != 0.0 {
let result = (self.input[idx] / tmp) * 100.0;
output_vector.push(result);
} else {
output_vector.push(0.0)
}
}
output_vector
}
}
pub fn roc_py(py: Python, input: Vec<f64>, time_period: i32) -> PyResult<Vec<f64>> {
let roc_wrapped = Roc::new(input, time_period);
let roc = match roc_wrapped {
Ok(x) => x,
Err(err_typ) => match err_typ {
Error::InvalidParams(msg) => return Err(PyErr::new::<exc::ValueError, _>(py, msg)),
},
};
let out_vec = roc.roc();
Ok(out_vec)
}
pub fn rocp_py(py: Python, input: Vec<f64>, time_period: i32) -> PyResult<Vec<f64>> {
let roc_wrapped = Roc::new(input, time_period);
let roc = match roc_wrapped {
Ok(x) => x,
Err(err_typ) => match err_typ {
Error::InvalidParams(msg) => return Err(PyErr::new::<exc::ValueError, _>(py, msg)),
},
};
let out_vec = roc.rocp();
Ok(out_vec)
}
pub fn rocr_py(py: Python, input: Vec<f64>, time_period: i32) -> PyResult<Vec<f64>> {
let roc_wrapped = Roc::new(input, time_period);
let roc = match roc_wrapped {
Ok(x) => x,
Err(err_typ) => match err_typ {
Error::InvalidParams(msg) => return Err(PyErr::new::<exc::ValueError, _>(py, msg)),
},
};
let out_vec = roc.rocr();
Ok(out_vec)
}
pub fn rocr_100_py(py: Python, input: Vec<f64>, time_period: i32) -> PyResult<Vec<f64>> {
let roc_wrapped = Roc::new(input, time_period);
let roc = match roc_wrapped {
Ok(x) => x,
Err(err_typ) => match err_typ {
Error::InvalidParams(msg) => return Err(PyErr::new::<exc::ValueError, _>(py, msg)),
},
};
let out_vec = roc.rocr100();
Ok(out_vec)
}
#[cfg(test)]
mod test {
use super::super::testcon::*;
use super::*;
#[test]
fn test_roc() {
let period = Roc::new(Vec::from(VECTOR), 10).unwrap();
assert_eq!(period.roc(), VECTOR_ROC_10)
}
#[test]
fn test_rocp() {
let period = Roc::new(Vec::from(VECTOR), 10).unwrap();
assert_eq!(period.rocp(), VECTOR_ROCP_10)
}
#[test]
fn test_rocr() {
let period = Roc::new(Vec::from(VECTOR), 10).unwrap();
assert_eq!(period.rocr(), VECTOR_ROCR_10)
}
#[test]
fn test_rocr100() {
let period = Roc::new(Vec::from(VECTOR), 10).unwrap();
assert_eq!(period.rocr100(), VECTOR_ROCR_100_10)
}
}