QuantLib Curve Roles in European Option Pricing
Summary
The document explains how yield and discount curves relate when pricing a European call with QuantLib. In the Python example, a Black–Scholes–Merton process receives an underlying quote, a dividend curve, a risk-free curve, and a volatility term structure. The question is whether a separate discount curve can also be supplied.
The responses clarify that a yield term structure can provide both yield rates and discount factors. The Python interface described does not expose the C++ engine’s option to pass a separate discount curve, so the risk-free curve is also used for discounting in this setup. The example demonstrates retrieving both a discount factor and a zero rate from the same curve. This is a narrow account of the library interface and does not cover multi-curve pricing workarounds or the assumptions behind the chosen curves.
Key ideas
- A QuantLib yield term structure can return both discount factors and zero rates.
- The described Python Black–Scholes–Merton setup uses the risk-free curve for discounting.
- The C++ engine supports a separate discount curve, but the discussed Python bindings do not expose that functionality.
- The example uses a separate dividend curve alongside the risk-free curve and volatility term structure.
Tags
Full text
# How to use both yield curve and discount curve to value call in QuantLib
# How to use both yield curve and discount curve to value call in QuantLib
I'm new to QuantLib, and I'm trying value a simple European call. QuantLib's Black-Scholes-Merton Process makes sense to me, but I don't know how to incorporate a discount curve into it.
Please see below for my current example in Python. Right now the process takes an index curve and a dividend curve. I need the process to take an index curve, dividend curve, and a discount curve. How can I accomplish this in QuantLib?
```
def call_atm_test():
"""Returns price of a european option using black-scholes"""
today = ql.Date(22, ql.May, 2019)
ql.Settings.instance().evaluationDate = today
option = ql.EuropeanOption(ql.PlainVanillaPayoff(ql.Option.Call, 2856.27),
ql.EuropeanExercise(ql.Date(22, ql.May, 2020)))
u = ql.SimpleQuote(2856.27)
r = ql.SimpleQuote(0.0223)
d = ql.SimpleQuote(0.01879)
sigma = ql.SimpleQuote(0.15259)
riskFreeCurve = ql.FlatForward(0, ql.TARGET(), ql.QuoteHandle(r), ql.Actual360())
dividend_yield = ql.FlatForward(0, ql.TARGET(), ql.QuoteHandle(d), ql.Actual360())
volatility = ql.BlackConstantVol(0, ql.TARGET(), ql.QuoteHandle(sigma), ql.Actual360())
process = ql.BlackScholesMertonProcess(ql.QuoteHandle(u),
ql.YieldTermStructureHandle(dividend_yield),
ql.YieldTermStructureHandle(riskFreeCurve),
ql.BlackVolTermStructureHandle(volatility))
engine = ql.AnalyticEuropeanEngine(process)
option.setPricingEngine(engine)
result = option.NPV()
return result
```
## Answer by Luigi Ballabio (score 3, accepted)
https://quant.stackexchange.com/a/47091
In the C++ version of QuantLib it is possible to pass a separate discount curve to the engine, but the functionality is not exported in Python (and therefore, as @Cornholio said, the risk-free curve is also used for discounting). If you need this feature in Python, please open an issue at https://github.com/lballabio/QuantLib-SWIG/issues.
## Answer by Cornholio (score 3)
https://quant.stackexchange.com/a/46054
Basically, your `riskFreeCurve` is a yield curve and a discount curve at the same time. QuantLib just saves it as a `YieldTermStructure`. You can see that
```
print(riskFreeCurve.discount(ql.Date(22, ql.May, 2020)))
print(riskFreeCurve.zeroRate(ql.Date(22, ql.May, 2020), ql.Actual360(), ql.Continuous))
```
gives you the discount factor and the yield rate:
```
0.9775834043036867
2.230000 % Actual/360 continuous compounding
```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.