Skip to content

feat(swaption): expose discrete option/swap grid on vol structures#610

Merged
benbenbang merged 3 commits into
mainfrom
fable/603
Jul 26, 2026
Merged

feat(swaption): expose discrete option/swap grid on vol structures#610
benbenbang merged 3 commits into
mainfrom
fable/603

Conversation

@benbenbang

@benbenbang benbenbang commented Jul 26, 2026

Copy link
Copy Markdown
Owner
  • feat(swaption): expose discrete option/swap grid on vol structures
  • feat(crates): implement dense ATM-calibrated arm for SABR vol cube
  • test(crates): add dense ATM-calibration oracle for SABR vol cube

close #603

Add a `discrete_grid` method to `SwaptionVolatilityStructure` so a
consumer can read the underlying option/swap node set. This stands in
for QuantLib's `dynamic_pointer_cast<SwaptionVolatilityDiscrete>`, which
the SABR cube's dense ATM-calibration fill relies on to widen its node
set.

**Trait default:**
* Introduce the `SwaptionVolatilityGrid` type holding index-aligned
  option times/dates and swap lengths/tenors.
* Provide a default `discrete_grid` that returns `Err`, since only a
  grid-backed structure can answer; this surfaces an error exactly where
  the C++ cast would null-deref.

**Matrix implementation:**
* Override `discrete_grid` in `SwaptionVolatilityMatrix` to delegate to
  the embedded discrete structure.

**Tests:**
* Verify the default returns `Err` for a non-grid structure and that the
  matrix delegates its grid to the embedded discrete.
This change ports the `isAtmCalibrated` dense arm of the SABR volatility
cube (previously deferred to #603), wiring the ATM-anchored cube widening
and re-fit into `perform_calculations`.

**Dense calibration arm:**
* Added a `dense_parameters` cube, populated during `perform_calculations`
  when `is_atm_calibrated` by building sparse smiles, widening the market
  vol cube with ATM-anchored points, and re-fitting SABR over the widened
  grid.
* Implemented `fill_volatility_cube` to merge the ATM structure's grid
  (read via `discrete_grid`, the downcast-equivalent for C++'s
  `dynamic_pointer_cast<SwaptionVolatilityDiscrete>`) with the cube's axes
  and set ATM vol plus interpolated per-strike spreads on new nodes.
* Implemented `create_sparse_smiles` and `smile_section_from_cube` to build
  per-node `SabrSmileSection`s from the parameter cube.
* Implemented `spread_vol_interpolation` to bracket the ATM node between the
  four surrounding sparse nodes and bilinearly blend corner spreads.
* Added `dense_parameter_values` accessor for the calibrated dense params.
* Added sorted-union axis helpers (`union_sorted_times`,
  `union_sorted_dates`, `union_sorted_tenors`) and `sorted_contains` /
  `lower_bound` for the C++ binary-search equivalents.

**Tests:**
* Replaced the #603 deferral test with a check that a non-grid ATM surface
  errors at `discrete_grid`, where the C++ cast would null-deref.

A non-grid ATM handle now errors instead of silently deferring, and the
`smileSectionImpl` query still defers to #604.
Adds a test that verifies the SABR swaption volatility cube recovers the
matrix ATM vol over a grid strictly denser than the cube's own. The ATM
surface is a real SwaptionVolatilityMatrix on {1Y,2Y,3Y} x {2Y,5Y,10Y}
while the cube covers {1Y,3Y} x {2Y,10Y}, so fillVolatilityCube must
genuinely insert the 2Y-option and 5Y-swap nodes.

**Testing improvements:**
* Added SABR-consistent matrix helpers so each ATM vol matches the DENSE_PARAMS SABR ATM vol at the node forward.
* Seeded cube smiles so the market smile is an exact SABR smile at every cube node, then asserted sparse node params match DENSE_PARAMS.
* Asserted dense parameter values reconstruct the matrix ATM vol within tolerance across the widened grid.

Closes #603

close #603
@benbenbang
benbenbang enabled auto-merge (rebase) July 26, 2026 14:14
@github-actions github-actions Bot added the enhancement New feature or request label Jul 26, 2026
@benbenbang
benbenbang merged commit 57fec9e into main Jul 26, 2026
3 of 6 checks passed
@benbenbang
benbenbang deleted the fable/603 branch July 26, 2026 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[QL-10.x][EPIC-10] SABR cube T3c: dense ATM-calibration fill (#596)

1 participant