use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{BasisPoints32, Cents, Height, Indexes, StoredF32, Version};
use vecdb::{Database, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode};
use crate::{
indexes,
internal::{BpsType, LazyPerBlock, PerBlock},
};
#[derive(Traversable)]
pub struct RatioPerBlock<B: BpsType = BasisPoints32, M: StorageMode = Rw> {
pub bps: PerBlock<B, M>,
pub ratio: LazyPerBlock<StoredF32, B>,
}
const VERSION: Version = Version::TWO;
impl<B: BpsType> RatioPerBlock<B> {
pub(crate) fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
Self::forced_import_raw(db, &format!("{name}_ratio"), version, indexes)
}
pub(crate) fn forced_import_raw(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v = version + VERSION;
let bps = PerBlock::forced_import(db, &format!("{name}_bps"), v, indexes)?;
let ratio = LazyPerBlock::from_computed::<B::ToRatio>(
name,
v,
bps.height.read_only_boxed_clone(),
&bps,
);
Ok(Self { bps, ratio })
}
}
impl RatioPerBlock<BasisPoints32> {
pub(crate) fn compute_ratio(
&mut self,
starting_indexes: &Indexes,
close_price: &impl ReadableVec<Height, Cents>,
series_price: &impl ReadableVec<Height, Cents>,
exit: &Exit,
) -> Result<()> {
self.bps.height.compute_transform2(
starting_indexes.height,
close_price,
series_price,
|(i, close, price, ..)| {
if price == Cents::ZERO {
(i, BasisPoints32::from(1.0))
} else {
(i, BasisPoints32::from(f64::from(close) / f64::from(price)))
}
},
exit,
)?;
Ok(())
}
}