use regit_svi::calibration::surface::{PhiFamily, SsviMaturity, calibrate as calibrate_ssvi};
use regit_svi::calibration::{calibrate_slice, quasi_explicit};
use regit_svi::density::density_report;
use regit_svi::market::quote::Quote;
use regit_svi::no_arb::butterfly::butterfly_scan;
use regit_svi::smile::conversion::{jw_to_raw, raw_to_jw};
use regit_svi::surface::interpolation::Surface;
use regit_svi::surface::ssvi::{Phi, Ssvi};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let quotes = [
Quote::new(-0.20, 0.0512, 1.0)?,
Quote::new(-0.10, 0.0432, 1.0)?,
Quote::new(0.00, 0.0400, 1.0)?,
Quote::new(0.10, 0.0420, 1.0)?,
Quote::new(0.20, 0.0480, 1.0)?,
];
let fit = calibrate_slice("es)?;
let svi = fit.slice();
println!("Calibrated raw SVI slice");
println!(
" a = {:.6} b = {:.6} rho = {:.6}",
svi.a(),
svi.b(),
svi.rho()
);
println!(" m = {:.6} sigma = {:.6}", svi.m(), svi.sigma());
println!(" RMSE = {:.3e}", fit.rmse());
println!(
" butterfly assessment = {:?}",
fit.arbitrage_assessment().status()
);
let qe = quasi_explicit::calibrate("es)?;
println!(" quasi-explicit RMSE = {:.3e}", qe.rmse());
let w = svi.total_variance(0.05);
let vol = svi.implied_vol(0.05, 1.0)?; println!("\nAt k = 0.05: w = {w:.6}, implied vol = {vol:.4}");
println!("ATM variance = {:.6}", svi.atm_total_variance());
println!("ATM skew = {:.6}", svi.atm_skew());
let jw = raw_to_jw(&svi, 1.0)?;
println!("\nJump-Wings view (t = 1y)");
println!(
" v_t = {:.6} psi_t = {:.6}",
jw.atm_variance(),
jw.atm_skew()
);
println!(" p_t = {:.6} c_t = {:.6}", jw.put_wing(), jw.call_wing());
let back = jw_to_raw(&jw)?;
println!(
" round-trip max param error: {:.2e}",
(back.a() - svi.a()).abs()
);
let report = butterfly_scan(&svi, -0.5, 0.5)?;
println!("\nButterfly scan");
println!(" violation observed = {}", report.violation_observed());
println!(
" min g(k) = {:.6} at k = {:.4}",
report.min_g(),
report.worst_k()
);
let density = density_report(&svi, -6.0, 6.0, 2000)?;
println!("\nRisk-neutral density");
println!(" integral over [-6, 6] = {:.6}", density.integral());
println!(" violation observed = {}", density.violation_observed());
let truth = Ssvi::new(-0.3, Phi::modified_power_law(0.5, 0.5)?)?;
let ks = [-0.3, -0.15, 0.0, 0.15, 0.3];
let maturities: Vec<SsviMaturity> = [(0.5, 0.02), (1.0, 0.04), (2.0, 0.07)]
.iter()
.map(|&(t, theta)| {
let quotes = ks
.iter()
.map(|&k| Quote::new(k, truth.total_variance(k, theta), 1.0))
.collect::<Result<Vec<_>, _>>()?;
SsviMaturity::new(t, theta, quotes)
})
.collect::<Result<Vec<_>, _>>()?;
let ssvi_fit = calibrate_ssvi(&maturities, PhiFamily::PowerLaw)?;
println!("\nSSVI surface calibration");
println!(" rho = {:.6}", ssvi_fit.ssvi().rho());
println!(" RMSE = {:.3e}", ssvi_fit.rmse());
println!(
" butterfly evidence = {:?}",
ssvi_fit.report().butterfly_assessment().status()
);
let surface = Surface::from_ssvi(
ssvi_fit.ssvi(),
maturities
.iter()
.map(|m| (m.maturity().get(), m.theta().get()))
.collect::<Vec<_>>(),
)?;
let w_interp = surface.total_variance(0.05, 1.5)?;
let vol_interp = surface.implied_vol(0.05, 1.5)?;
println!("\nSurface at (k = 0.05, T = 1.5y)");
println!(" w = {w_interp:.6}, implied vol = {vol_interp:.4}");
println!(
" calendar assessment = {:?}",
surface.calendar_assessment(-0.4, 0.4)?.status()
);
Ok(())
}