use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::PartsPerMillion32;
use vecdb::Exit;
use super::RsiChain;
use crate::blocks;
pub(super) fn compute(
chain: &mut RsiChain,
indexer: &Indexer,
blocks: &blocks::Vecs,
rma_days: usize,
stoch_sma_days: usize,
exit: &Exit,
) -> Result<()> {
let starting_height = indexer.safe_lengths().height;
let ws_rma = blocks.lookback.start_vec(rma_days);
let ws_sma = blocks.lookback.start_vec(stoch_sma_days);
chain.average_gain.height.compute_rolling_rma(
starting_height,
ws_rma,
&chain.gains.height,
exit,
)?;
chain.average_loss.height.compute_rolling_rma(
starting_height,
ws_rma,
&chain.losses.height,
exit,
)?;
chain.rsi.ppm.height.compute_transform2(
starting_height,
&chain.average_gain.height,
&chain.average_loss.height,
|(h, g, l, ..)| {
let sum = *g + *l;
let rsi = if sum == 0.0 { 0.5 } else { *g / sum };
(h, PartsPerMillion32::from(rsi as f64))
},
exit,
)?;
chain.rsi_min.ppm.height.compute_rolling_min_from_starts(
starting_height,
ws_rma,
&chain.rsi.ppm.height,
exit,
)?;
chain.rsi_max.ppm.height.compute_rolling_max_from_starts(
starting_height,
ws_rma,
&chain.rsi.ppm.height,
exit,
)?;
chain.stoch_rsi.ppm.height.compute_transform3(
starting_height,
&chain.rsi.ppm.height,
&chain.rsi_min.ppm.height,
&chain.rsi_max.ppm.height,
|(h, r, mn, mx, ..)| {
let range = f64::from(*mx) - f64::from(*mn);
let stoch = if range == 0.0 {
PartsPerMillion32::ZERO
} else {
PartsPerMillion32::from((f64::from(*r) - f64::from(*mn)) / range)
};
(h, stoch)
},
exit,
)?;
chain.stoch_rsi_k.ppm.height.compute_rolling_average(
starting_height,
ws_sma,
&chain.stoch_rsi.ppm.height,
exit,
)?;
chain.stoch_rsi_d.ppm.height.compute_rolling_average(
starting_height,
ws_sma,
&chain.stoch_rsi_k.ppm.height,
exit,
)?;
Ok(())
}