use crate::errors::QlResult;
use crate::fail;
use crate::time::date::Date;
use crate::types::{Real, Time, Volatility};
use super::VolatilityTermStructure;
pub trait LocalVolTermStructure: VolatilityTermStructure {
fn local_vol_impl(&self, t: Time, strike: Real) -> QlResult<Volatility>;
fn local_vol_date(
&self,
date: Date,
underlying_level: Real,
extrapolate: bool,
) -> QlResult<Volatility> {
self.check_range_date(date, extrapolate)?;
self.check_strike(underlying_level, extrapolate)?;
let t = self.time_from_reference(date)?;
let vol = self.local_vol_impl(t, underlying_level)?;
ensure_finite_volatility(vol)?;
Ok(vol)
}
fn local_vol(
&self,
t: Time,
underlying_level: Real,
extrapolate: bool,
) -> QlResult<Volatility> {
self.check_range_time(t, extrapolate)?;
self.check_strike(underlying_level, extrapolate)?;
let vol = self.local_vol_impl(t, underlying_level)?;
ensure_finite_volatility(vol)?;
Ok(vol)
}
}
fn ensure_finite_volatility(vol: Volatility) -> QlResult<()> {
if !vol.is_finite() {
fail!("volatility ({vol}) must be finite");
}
Ok(())
}