use crate::utils::{make_vec, check_begin_idx4, check_begin_idx2};
use serde::Deserialize;
use talib_sys::{TA_ADOSC_Lookback, TA_AD_Lookback, TA_OBV_Lookback, TA_AD, TA_ADOSC, TA_OBV};
use talib_sys::{TA_Integer, TA_RetCode};
use derive_builder::Builder;
pub fn ta_ad(
high_ptr: *const f64,
low_ptr: *const f64,
close_ptr: *const f64,
volume_ptr: *const f64,
len: usize,
) -> Result<Vec<f64>, TA_RetCode> {
let mut out_begin: TA_Integer = 0;
let mut out_size: TA_Integer = 0;
let begin_idx = check_begin_idx4(len, high_ptr, low_ptr, close_ptr, volume_ptr) as i32;
let end_idx = len as i32 - begin_idx - 1;
let lookback = begin_idx + unsafe { TA_AD_Lookback() };
let (mut out, ptr) = make_vec(len, lookback);
let ret_code = unsafe {
TA_AD(
0,
end_idx,
high_ptr.offset(begin_idx as isize),
low_ptr.offset(begin_idx as isize),
close_ptr.offset(begin_idx as isize),
volume_ptr.offset(begin_idx as isize),
&mut out_begin,
&mut out_size,
ptr,
)
};
let out_size_begin = (begin_idx + out_begin + out_size) as usize;
match ret_code {
TA_RetCode::TA_SUCCESS => {
if out_size != 0 {
unsafe {
out.set_len(out_size_begin);
}
} else {
unsafe {
out.set_len(len);
}
}
Ok(out)
}
_ => Err(ret_code),
}
}
#[derive(Builder, Deserialize)]
pub struct ADOSCKwargs {
#[builder(default = "3")]
pub fastperiod: i32,
#[builder(default = "10")]
pub slowperiod: i32,
}
pub fn ta_adosc(
high_ptr: *const f64,
low_ptr: *const f64,
close_ptr: *const f64,
volume_ptr: *const f64,
len: usize,
kwargs: &ADOSCKwargs,
) -> Result<Vec<f64>, TA_RetCode> {
let mut out_begin: TA_Integer = 0;
let mut out_size: TA_Integer = 0;
let begin_idx = check_begin_idx4(len, high_ptr, low_ptr, close_ptr, volume_ptr) as i32;
let end_idx = len as i32 - begin_idx - 1;
let lookback = begin_idx + unsafe { TA_ADOSC_Lookback(kwargs.fastperiod, kwargs.slowperiod) };
let (mut out, ptr) = make_vec(len, lookback);
let ret_code = unsafe {
TA_ADOSC(
0,
end_idx,
high_ptr.offset(begin_idx as isize),
low_ptr.offset(begin_idx as isize),
close_ptr.offset(begin_idx as isize),
volume_ptr.offset(begin_idx as isize),
kwargs.fastperiod,
kwargs.slowperiod,
&mut out_begin,
&mut out_size,
ptr,
)
};
let out_size_begin = (begin_idx + out_begin + out_size) as usize;
match ret_code {
TA_RetCode::TA_SUCCESS => {
if out_size != 0 {
unsafe {
out.set_len(out_size_begin);
}
} else {
unsafe {
out.set_len(len);
}
}
Ok(out)
}
_ => Err(ret_code),
}
}
pub fn ta_obv(
real_ptr: *const f64,
volume_ptr: *const f64,
len: usize,
) -> Result<Vec<f64>, TA_RetCode> {
let mut out_begin: TA_Integer = 0;
let mut out_size: TA_Integer = 0;
let begin_idx = check_begin_idx2(len, real_ptr, volume_ptr) as i32;
let end_idx = len as i32 - begin_idx - 1;
let lookback = begin_idx + unsafe { TA_OBV_Lookback() };
let (mut out, ptr) = make_vec(len, lookback);
let ret_code = unsafe {
TA_OBV(
0,
end_idx,
real_ptr.offset(begin_idx as isize),
volume_ptr.offset(begin_idx as isize),
&mut out_begin,
&mut out_size,
ptr,
)
};
let out_size_begin = (begin_idx + out_begin + out_size) as usize;
match ret_code {
TA_RetCode::TA_SUCCESS => {
if out_size != 0 {
unsafe {
out.set_len(out_size_begin);
}
} else {
unsafe {
out.set_len(len);
}
}
Ok(out)
}
_ => Err(ret_code),
}
}