1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//! Multi-tenor volatility surface construction.
//!
//! A volatility surface maps (expiry, strike) → implied vol across multiple
//! tenors. This module provides several surface representations:
//!
//! - [`SsviSurface`] — Global SSVI parameterization (Gatheral-Jacquier)
//! - [`EssviSurface`] — Extended SSVI with calendar-spread no-arb guarantees
//! - [`PiecewiseSurface`] — Per-tenor [`SmileSection`]s with cross-tenor
//! variance interpolation
//! - [`SurfaceBuilder`] — Ergonomic builder API for surface construction
pub
pub use ;
pub use ;
pub use ;
pub use PiecewiseSurface;
pub use ;
use crateerror;
use crateSmileSection;
use crate;
/// A full volatility surface: (expiry, strike) → vol.
///
/// All implementations must be `Send + Sync` for safe concurrent pricing
/// across multiple threads. Surfaces are immutable after construction.
///
/// # Design
/// - No global state — evaluation date is implicit in the tenors
/// - Immutable after construction — no observer pattern
/// - Ragged strike grids — each tenor can have different strikes
/// - Local vol is computed via [`DupireLocalVol`](crate::local_vol::DupireLocalVol)
/// by composing it around any `VolSurface`, not as a trait method here.
/// This avoids forcing every surface type to embed Dupire numerics.
///
/// # Examples
///
/// ```
/// use volsurf::surface::{SsviSurface, VolSurface};
///
/// let surface = SsviSurface::new(
/// -0.3, 0.5, 0.5,
/// vec![0.25, 0.5, 1.0],
/// vec![100.0, 100.0, 100.0],
/// vec![0.04, 0.08, 0.16],
/// )?;
///
/// let vol = surface.black_vol(0.5, 100.0)?;
/// assert!(vol.0 > 0.0);
///
/// let var = surface.black_variance(0.5, 100.0)?;
/// assert!((var.0 - vol.0 * vol.0 * 0.5).abs() < 1e-12);
///
/// let smile = surface.smile_at(0.5)?;
/// assert!(smile.vol(100.0)?.0 > 0.0);
/// # Ok::<(), volsurf::VolSurfError>(())
/// ```