use std::sync::Arc;
use std::f64::NAN;
use data::volsurface::RcVolSurface;
use data::volsurface::FlatVolSurface;
use data::voldecorators::TimeScaledBumpVol;
use data::voldecorators::ParallelBumpVol;
use data::bump::Bumper;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum BumpVol {
FlatAdditive { size: f64 },
TimeScaled { size: f64, floor: f64 },
Replace { vol: f64 }
}
impl BumpVol {
pub fn new_flat_additive(size: f64) -> BumpVol {
BumpVol::FlatAdditive { size: size }
}
pub fn new_time_scaled(size: f64, floor: f64) -> BumpVol {
BumpVol::TimeScaled { size: size, floor: floor }
}
pub fn new_replace(vol: f64) -> BumpVol {
BumpVol::Replace { vol }
}
pub fn bumpsize(&self) -> f64 {
match self {
&BumpVol::FlatAdditive { size } => size,
&BumpVol::TimeScaled { size, floor: _ } => size,
&BumpVol::Replace { vol: _ } => NAN
}
}
pub fn opposite(&self) -> BumpVol {
let bumpsize = self.bumpsize();
let down_bump = (1.0 - bumpsize) / (1.0 + bumpsize) - 1.0;
match self {
&BumpVol::FlatAdditive { size: _ }
=> BumpVol::FlatAdditive { size : down_bump },
&BumpVol::TimeScaled { size: _, floor }
=> BumpVol::TimeScaled { size : down_bump, floor: floor },
&BumpVol::Replace { vol: _ }
=> BumpVol::Replace { vol: NAN }
}
}
}
impl Bumper<RcVolSurface> for BumpVol {
fn apply(&self, surface: RcVolSurface) -> RcVolSurface {
match self {
&BumpVol::FlatAdditive { size }
=> RcVolSurface::new(Arc::new(ParallelBumpVol::new(surface.clone(), size))),
&BumpVol::TimeScaled { size, floor }
=> RcVolSurface::new(Arc::new(TimeScaledBumpVol::new(surface.clone(), size, floor))),
&BumpVol::Replace { vol }
=> RcVolSurface::new(Arc::new(FlatVolSurface::new(vol,
surface.calendar().clone(), surface.base_date())))
}
}
}