Building FX Volatility Surfaces from Delta Quotes in QuantLib Python
Summary
The note concerns constructing an FX volatility surface when market quotes are expressed by moneyness or delta rather than by fixed absolute strikes. It describes limitations encountered with Python bindings for QuantLib and an Open Source Risk Engine volatility surface, including difficulty extending a C++ term-structure class through its Python wrapper.
The accepted suggestion is to convert between delta quotes and strikes using delta-quote and Black delta-calculator tools, then use a Black variance surface. This offers a route to build the desired surface without implementing a new term-structure subclass. The response points to a related example but provides no implementation details or comparison of accuracy. A separate answer confirms that subclassing the Python wrappers does not work, so users needing custom C++ behavior may need another approach.
Key ideas
- FX volatility quotes expressed in delta need to be translated into strikes for a strike-based surface.
- Delta quote and Black delta-calculator utilities can support that conversion before surface construction.
- Subclassing the QuantLib Python wrappers does not provide a working way to extend the C++ term-structure classes.
- The suggested workaround is conceptual and does not specify implementation details or validate surface accuracy.
Tags
Full text
# Extending/Subclassing QuantLib Classes in Python?
# Extending/Subclassing QuantLib Classes in Python?
I'm using quantlib via the quantlib-python or open-source-risk-engine both on pypi. The question relates whether it's possible to extend QuantLib term structure base classes in python rather than C++. My guess is you can't, but wanted to double check.
Background:
I've hit a limitation whereby the available BlackVarianceSurface is unable to take different strikes for different tenors when building a surface - my FX market instruments are quotes in moneyness, not absolutely strikes.
I've found ORE's extension - FxBlackVannaVolgaVolatilitySurface, which is very close to what I want, but only handles market quotes at a single delta (eg only 25-delta by default).
So, in order to add more market deltas, I was hoping to extend the parent class - BlackVolatilityTermStructure. However, the python bindings only seem to expose its parent BlackVolTermStructure - the idea being to write a new FX Surface implementation, following the C++ for FxBlackVannaVolgaVolatilitySurface as a rough guide, but to do it in python.
I'm not sure extending BlackVolTermStructure in python is the right thing to do? My test class extending BlackVolTermStructure instantiates OK, but when I try to create a BlackVolTermStructureHandle from the instance it fails (see below). It looks to me like QuantLib is expecting a shared pointer to the class which I'm assuming I can't provide to a python-implemented child class (error below)?
My questions are:
- Is it possible to create your own extended volatility term structures using only python, or am I should I write it in C++ and build python bindings to my C++ extension?
- Given it's a small extension is there a way to bundle this as a separate library I build in C++ rather than forking and changing QuantLib itself? Any guides on this?
- On the off-chance if anyone has managed to use FxBlackVannaVolgaVolatilitySurface from ORE in python with (for example) 10 and 25 market deltas on the same surface that would remove the need for me to extend!
- Perhaps there's a better approach to avoid extending that I'm missing, given what I'm trying to build is quite typical for FX Option pricing - any advice gladly received. I'm not against implementing my extension in C++, but would prefer to avoid this complication if possible.
```
self = <ORE.ORE.BlackVolTermStructureHandle; >, args = (<lib.opcalc.volatility.vol_surface.CustomVolatilitySurface; >,)
def __init__(self, *args):
> _ORE.BlackVolTermStructureHandle_swiginit(self, _ORE.new_BlackVolTermStructureHandle(*args))
E TypeError: Wrong number or type of arguments for overloaded function 'new_BlackVolTermStructureHandle'.
E Possible C/C++ prototypes are:
E Handle< BlackVolTermStructure >::Handle(ext::shared_ptr< BlackVolTermStructure > const &)
E Handle< BlackVolTermStructure >::Handle()
venv-osre/lib/python3.11/site-packages/ORE/ORE.py:8657: TypeError
```
## Answer by user35980 (score 4, accepted)
https://quant.stackexchange.com/a/77183
I think you can use a combination of the `ql.DeltaVolQuote` and `ql.BlackDeltaCalculator` classes with the `.strikeFromDelta` attribute to switch between strikes and delta quotes, then use `ql.BlackVarianceSurface`, to achieve your goal. Take a look at this answer where something similar is being done.
## Answer by Luigi Ballabio (score 2)
https://quant.stackexchange.com/a/77210
Just to confirm: subclassing the Python wrappers doesn't work.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.