QuantLib
QuantLib copied to clipboard
Volatility surface with different strike levels for different tenors
See https://stackoverflow.com/questions/64851608/quantlib-vol-surface-different-strike-levels-for-different-tenors.
It's not an obvious extension of BlackVarianceSurface because our 2-d interpolations require a fixed grid. It might require a different class that does its own interpolation.
For equity/fx related problems you might consider to use AndreasenHugeVolatilityInterpl, which can deal with irregular strike and maturity grids and resolves arbitrage conditions. The corresponding Python script for the problem above looks like
import QuantLib as ql
if __name__ == "__main__":
referenceDate = ql.Date(30, 9, 2013)
ql.Settings.instance().evaluationDate = referenceDate
dc = ql.Actual365Fixed()
spot = ql.SimpleQuote(1650.0)
rTS = ql.YieldTermStructureHandle(ql.FlatForward(referenceDate, 0.03, dc))
qTS = ql.YieldTermStructureHandle(ql.FlatForward(referenceDate, 0.05, dc))
strikes = [1645.0, 1650.0, 1655.0, 1650.0, 1660.0, 1670.0]
expirations = [ql.Date(20, 12, 2013)] * 3 + [ql.Date(17, 1, 2014)] * 3
vols = [0.15640, 0.15343, 0.15128, 0.15433, 0.15240, 0.14888]
calibrationSet = ql.CalibrationSet([
(
ql.VanillaOption(
ql.PlainVanillaPayoff(ql.Option.Call, strike),
ql.EuropeanExercise(expiry)
),
ql.SimpleQuote(vol)
) for strike, expiry, vol in zip(strikes, expirations, vols)
])
volInterp = ql.AndreasenHugeVolatilityAdapter(
ql.AndreasenHugeVolatilityInterpl(
calibrationSet,
ql.QuoteHandle(spot),
rTS, qTS
)
)
print(volInterp.blackVol(0.5, 1650, True))
The class AndreasenHugeLocalVolAdapter provides a local volatility adapter for this interpolation method.
I don't mind having a look at it... Will take a bit of time. What's the preferred path? Replace a 2d matrix by a vector of vectors, and interpolate first in one dimension then in the other? (at the cost of a little memory).
That's what I was thinking, but Klaus' class seems to provide the functionality already.
Parametric methods come with caveats typically and I see them as a different class to simple interpolation. They are usually a little slower, can have edge cases (far strikes, low or high expiries), sometimes there can be numerical inaccuracies in recovering the input prices. It's true though that they are arbitrage free out of the box, at least this one is... I'm curious to test a bit if I get time next week.
Hi, I did a quick test of the vol surface - comparing Andearsen & Huge vs simple Black vol interpolation (without extrapolation). I used the default bilinear interpolation as well as cubic splines. Attached are 4 plots:
- LinearVolSurface - linear interp for a range of strikes/expiries
- SplinesVolSurface - splines interp for a range of strikes/expiries
- WeirdCase1 - zooming into very short expiries but with a wide range of strikes and vols
- WeirdCase2 - zooming into very short expiries but with a narrow range of strikes and vols
What we can see in 1 and 2 is roughly what we can expect. There are differences around 1-2 bp for mid range expiries which increase for short expiries. The diffs are ok except perhaps they are a little oscillating, which can be a problem if you use first-order diffs (like local vol-style, or perhaps digital products). But overall it's reasonable. Short expiries are a little more problematic, and if I zoom into them by creating daily vol pillars, some problems emerge. Of course nether 3 nor 4 are realistic, as 3 has an unreasonable range of strikes/vols for the short of expiries I'm using. Case 4 has a narrow range of expiries, strikes and vols but there are just a lot of pillars very close to each other and for some reason it performs the worst of all. While it's unrealistic to have this sort of setup, it's perfectly normal and expected of a vol surface to price one-day expiries well. Also of note that Case 4 took a long time to calibrate.
Conclusion: I did not analyse it too deeply except to say that yes, as expected, there are some weird things happening, tolerable when the vol surface is not pushed but sometimes weird at the extremes.
Ok, thanks a lot for the analysis. If you want to go ahead, please do.