use num::Float;
use crate::{
View,
pure_functions::Echo,
};
#[derive(Debug, Clone)]
pub struct LnReturn<T, V> {
view: V,
last_val: T,
current_val: T,
}
impl<T: Float> Default for LnReturn<T, Echo<T>> {
fn default() -> Self {
Self::new(Echo::new())
}
}
impl<T, V> LnReturn<T, V>
where
T: Float,
V: View<T>,
{
pub fn new(view: V) -> Self {
Self {
view,
last_val: T::zero(),
current_val: T::zero(),
}
}
}
impl<T, V> View<T> for LnReturn<T, V>
where
T: Float,
V: View<T>,
{
fn update(&mut self, val: T) {
debug_assert!(val.is_finite(), "value must be finite");
self.view.update(val);
let Some(val) = self.view.last() else { return };
debug_assert!(val.is_finite(), "value must be finite");
self.last_val = self.current_val;
self.current_val = val;
}
fn last(&self) -> Option<T> {
if self.last_val == T::zero() {
return None;
}
let out = (self.current_val / self.last_val).ln();
debug_assert!(out.is_finite(), "value must be finite");
Some(out)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ln_return() {
let mut ln_return = LnReturn::new(Echo::new());
ln_return.update(100.0);
assert!(ln_return.last().is_none());
ln_return.update(110.0);
assert_eq!(ln_return.last().unwrap(), 0.09531017980432493);
}
}