use crate::types::{IndicatorInfoOrInteger, IndicatorError};
pub(crate) fn min_process(
options: &[f64],
recent_only: Option<(usize, usize)>,
alpha: &[f64],
indicator_info: IndicatorInfoOrInteger,
min_data: fn(&[f64]) -> usize,
) -> usize {
if let Some((acc, _)) = recent_only {
let integers = match indicator_info {
IndicatorInfoOrInteger::Info(info_ref) => {
let inputs = info_ref.inputs;
let mut ints = 3;
for &input in inputs.iter() {
if input == "volume" {
ints = 8;
break;
}
}
ints
}
IndicatorInfoOrInteger::Integer(val) => val,
};
if acc > 0 {
let mut data_len = 0;
for (i, &al) in alpha.iter().enumerate() {
if i == 0 {
data_len += min_data_accuracy(options, acc, al, Some(min_data), integers);
} else {
data_len += min_data_accuracy(options, acc, al, None, integers);
}
}
return data_len;
}
}
min_data(options)
}
pub(crate) fn min_data_accuracy(
options: &[f64],
decimal_places: usize,
alpha: f64,
min_data: Option<fn(&[f64]) -> usize>,
integer_digits: usize,
) -> usize {
let tolerance = 0.5 * 10_f64.powi(-(decimal_places as i32 + integer_digits as i32));
let additional = (tolerance.ln() / (1.0 - alpha).ln()).ceil() as usize;
if let Some(f) = min_data {
f(options) + additional
} else {
additional
}
}
pub(crate) fn validate_inputs(inputs: &[&[f64]], min_data_length: usize) -> Result<(), IndicatorError> {
let first_len = inputs[0].len();
if first_len < min_data_length {
return Err(IndicatorError::NotEnoughData);
}
for input in inputs.iter().skip(1) {
if input.len() != first_len {
return Err(IndicatorError::InvalidInputs);
}
}
Ok(())
}
pub(crate) fn validate_options(options: &[f64]) -> Result<(), IndicatorError> {
for &option in options.iter() {
if option < 1.0 {
return Err(IndicatorError::InvalidOptions);
}
}
Ok(())
}