Skip to content
All library documents

Why Bloomberg Cap Volatility Quotes May Not Fit a SABR Smile

Article Quant Q&A · Author: Hasek

Summary

The document investigates why a SABR calibration using Bloomberg cap volatility figures produces a poor match across strikes. The question provides an example with caplet-related strikes and volatilities, estimates a forward from interest-rate curve inputs, and describes fitting a lognormal SABR model with a Python library. The resulting model smile differs noticeably from the supplied volatility values.

The answer explains that the displayed Bloomberg swaption manager cap volatility is not itself a SABR-fitted market quote. It is described as a flat volatility that reproduces the deal premium when used for caplet pricing, while the caplets are derived from Bloomberg’s volatility cube and swaption volatilities. This means the displayed values should not be assumed to be direct smile inputs for a simple SABR fit. The response points to Bloomberg’s documentation for the more detailed stripping process, but does not provide a complete calibration recipe or independently validate the numerical example.

Key ideas

  • Bloomberg’s displayed cap volatility may represent a flat premium-equivalent volatility rather than a quoted strike-by-strike SABR volatility.
  • The response attributes caplet inputs to a volatility cube and swaption volatilities.
  • A direct SABR fit to displayed cap volatilities can therefore fail to reproduce the reported values.
  • The answer gives only a high-level explanation and refers readers to separate documentation for the stripping procedure.

Tags

Full text
# Can't fit Bloomberg volatility smile with pysabr. What am I doing wrong?


# Can't fit Bloomberg volatility smile with pysabr. What am I doing wrong?












I want to make sure that I can properly use SABR model on 1-period interest rate options, i.e. caplets, therefore I attempted to get lognormal volatilities for 4%, 6%, ATM, 8%, 10% strikes for 3Mx6M caps on RUB MOSKP3 index with IRS ICVS179 RUB as both discounting and projecting curve and fit SABR model to corresponding volatility smile. I use pysabr library for SABR model implementation in python.

The Bloomberg data is as follows:

```
capStrikes = [0.04, 0.06, 0.0745136, 0.08, 0.10]
capVols = [23.52/100.00, 16.24/100.00, 18.35/100.00, 20.17/100.00, 26.19/100.00]
IRS curve = [1WK 0.0713, 1MO 0.0722, 2MO 0.0732, 3MO 0.0747, 6MO 0.0753, 1YR 0.0789]
```

I think this is all that I need to more or less fit the model to Bloomberg quotes. This is an example of the interface that I'm trying to use:

```
from pysabr import Hagan2002LognormalSABR
# Forward = 2.5%, Shift = 3%, ATM Normal Vol = 40bps
# Beta = 0.5, Rho = -20%, Volvol = 0.30
sabr = Hagan2002LognormalSABR(f=0.025, shift=0.03, t=1., v_atm_n=0.0040,
                              beta=0.5, rho=-0.2, volvol=0.30)
k = 0.025
sabr.lognormal_vol(k) * 100
# returns 7.27
sabr.normal_vol(k) *1e4
# returns 40
```

However I can't properly fit the smile. Please see my code below:

```
import pysabr
from pysabr import Hagan2002LognormalSABR as LNsabr
import numpy as np

testStrikes = np.array([0.04, 0.06, 0.0745136, 0.08, 0.10])
testVols = np.array([23.52/100.00, 16.24/100.00, 18.35/100.00, 20.17/100.00, 26.19/100.00])
forward_3m_6m = (1/0.25) * (-1 + (1+0.0753*0.5) / (1+0.0747*0.25))

calibration = LNsabr(f = forward_3m_6m, shift = 0, t = 0.5, beta = 0.5).fit(testStrikes, testVols)
smile = []
for strike in testStrikes:
    smile.append(LNsabr(f = forward_3m_6m, shift = 0, t = 0.5, v_atm_n = 136.75/10000.00, beta = 0.5, rho = calibration[1], volvol = calibration[2]).lognormal_vol(strike) * 100.00)
print(smile)
```

The SABR implied lognormal results are pretty far away from the initial volatilities.

```
[21.331968636265458, 19.365310362267866, 18.36618998284387, 18.04637126862935, 17.06699480954601]
```

What am I doing wrong? Why my results are so far from the quotes? I will be very grateful if someone would show me a proper way to fit the Bloomberg smile using pysabr.

EDIT: I'm looking for either a fix to my code which will do a better SABR fit or a qualitative explanation why the obtained fit is that bad. Alternatively one can show me an example of fitting a pysabr to any other Bloomberg SWPM cap/floor smile given 4-5 strikes and their volatilities.

## Answer by AKdemy (score 1)

https://quant.stackexchange.com/a/67963

Bloomberg swpm doesn't fit caps vol. It's quite complicated what is done by BBG and they offer a lengthy white paper, on HELP VCUB - "Documents" called the "Bloomberg Volatility Cube". Cap stripping is explained from P.9 onwards. In general, the cap vol shown in swpm is NOT a SABR fitted vol. The caplets are from VCUB (and actually swaption vols). Here are some (very basic) ideas of how Bloomberg does it. The main tab of SWPM shows the cap vol itself, which is simply the flat vol which, when used as optlet vol in cap pricing, gives the deal the same premium. It is neither a market quote, nor directly SABR fitted.

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.