use crate::traits::FloatExt;
#[derive(Clone, Debug)]
pub enum MtPayoff<T: FloatExt> {
Call { asset: usize, strike: T },
Put { asset: usize, strike: T },
DigitalPut2D { strikes: [T; 2] },
BasketCall { weights: Vec<T>, strike: T },
WorstOfPut { strike: T },
}
impl<T: FloatExt> MtPayoff<T> {
pub fn evaluate(&self, st: &[T]) -> T {
match self {
Self::Call { asset, strike } => (st[*asset] - *strike).max(T::zero()),
Self::Put { asset, strike } => (*strike - st[*asset]).max(T::zero()),
Self::DigitalPut2D { strikes } => {
if st[0] <= strikes[0] && st[1] <= strikes[1] {
T::one()
} else {
T::zero()
}
}
Self::BasketCall { weights, strike } => {
let basket = weights
.iter()
.zip(st)
.map(|(&w, &s)| w * s)
.fold(T::zero(), |a, b| a + b);
(basket - *strike).max(T::zero())
}
Self::WorstOfPut { strike } => {
let worst = st.iter().copied().fold(T::infinity(), |a, b| a.min(b));
(*strike - worst).max(T::zero())
}
}
}
}