pub mod arbitrage;
pub mod sabr;
pub mod spline;
pub mod svi;
pub use arbitrage::{ArbitrageReport, ButterflyViolation};
pub use sabr::SabrSmile;
pub use spline::SplineSmile;
pub use svi::SviSmile;
use crate::error;
use crate::implied::black::black_price;
use crate::types::{OptionType, Variance, Vol};
use crate::validate::validate_positive;
pub trait SmileSection: Send + Sync + std::fmt::Debug {
fn vol(&self, strike: f64) -> error::Result<Vol>;
fn variance(&self, strike: f64) -> error::Result<Variance> {
let v = self.vol(strike)?;
Ok(Variance(v.0 * v.0 * self.expiry()))
}
fn density(&self, strike: f64) -> error::Result<f64> {
validate_positive(strike, "strike")?;
let h = strike * 1e-4;
let k_lo = strike - h;
let k_hi = strike + h;
let v_lo = self.vol(k_lo)?;
let v_mid = self.vol(strike)?;
let v_hi = self.vol(k_hi)?;
let c_lo = black_price(
self.forward(),
k_lo,
v_lo.0,
self.expiry(),
OptionType::Call,
)?;
let c_mid = black_price(
self.forward(),
strike,
v_mid.0,
self.expiry(),
OptionType::Call,
)?;
let c_hi = black_price(
self.forward(),
k_hi,
v_hi.0,
self.expiry(),
OptionType::Call,
)?;
Ok((c_lo - 2.0 * c_mid + c_hi) / (h * h))
}
fn forward(&self) -> f64;
fn expiry(&self) -> f64;
fn is_arbitrage_free(&self) -> error::Result<ArbitrageReport>;
}