use volsurf::surface::{SurfaceBuilder, VolSurface};
use volsurf::{Strike, Tenor};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let strikes = vec![80.0, 90.0, 95.0, 100.0, 105.0, 110.0, 120.0];
let vols_3m = vec![0.30, 0.26, 0.24, 0.22, 0.23, 0.25, 0.29];
let vols_6m = vec![0.28, 0.25, 0.23, 0.21, 0.22, 0.24, 0.27];
let vols_1y = vec![0.26, 0.23, 0.22, 0.20, 0.21, 0.23, 0.26];
let surface = SurfaceBuilder::new()
.spot(100.0)
.rate(0.05) .add_tenor(0.25, &strikes, &vols_3m) .add_tenor(0.50, &strikes, &vols_6m) .add_tenor(1.00, &strikes, &vols_1y) .build()?;
println!("Surface built: 3 tenors x 7 strikes\n");
println!("--- Vol grid (expiry x strike) ---\n");
let query_tenors = [0.10, 0.25, 0.50, 0.75, 1.00, 1.50];
let query_strikes = [80.0, 90.0, 100.0, 110.0, 120.0];
print!("{:>8}", "T\\K");
for &k in &query_strikes {
print!("{k:>10.0}");
}
println!();
println!("{}", "-".repeat(58));
for &t in &query_tenors {
print!("{t:>8.2}");
for &k in &query_strikes {
let vol = surface.black_vol(Tenor(t), Strike(k))?;
print!("{:>10.2}%", vol.0 * 100.0);
}
println!();
}
println!("\n--- Vol/Variance consistency check ---\n");
let t = 0.5;
let k = 100.0;
let vol = surface.black_vol(Tenor(t), Strike(k))?;
let var = surface.black_variance(Tenor(t), Strike(k))?;
println!("At T={t}, K={k}:");
println!(" vol = {:.6}", vol.0);
println!(" variance = {:.6}", var.0);
println!(" vol^2*T = {:.6}", vol.0 * vol.0 * t);
println!(" match = {}", (vol.0 * vol.0 * t - var.0).abs() < 1e-12);
println!("\n--- Smile section at T=0.75 (interpolated) ---\n");
let smile = surface.smile_at(Tenor(0.75))?;
println!("Forward: {:.2}", smile.forward());
println!("Expiry: {:.2}", smile.expiry());
for &k in &query_strikes {
let v = smile.vol(Strike(k))?;
let d = smile.density(Strike(k))?;
println!(" K={k:>6.0} vol={:.4} density={:.6}", v.0, d);
}
println!("\n--- Arbitrage diagnostics ---\n");
let diag = surface.diagnostics()?;
println!("Butterfly violations per tenor:");
for (i, report) in diag.smile_reports.iter().enumerate() {
println!(
" Tenor {}: {} violations",
i + 1,
report.butterfly_violations.len()
);
}
println!("Calendar violations: {}", diag.calendar_violations.len());
println!("Surface is arbitrage-free: {}", diag.is_free());
Ok(())
}