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),

    engine = ql.AnalyticEuropeanEngine(process)

    result = option.NPV()
    return result

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.

  • $\begingroup$ Hi @N4v. I have a similar issue. Can you please let us know whether this issue was opened ( as suggested by Luigi Ballabio) and resolved? Appreciate your reply. $\endgroup$ – ahr1729 Jun 5 at 5:19

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:

2.230000 % Actual/360 continuous compounding
  • 1
    $\begingroup$ @N4v, I could not comment your question. What do you mean by 'index curve'? $\endgroup$ – Cornholio Jun 12 '19 at 9:03
  • $\begingroup$ by index curve I mean the yield curve, or the risk-neutral rate at which the stock grows. The reason I asked is that some valuation software allows one to have separate yield and discount curves, i.e. let the yield curve be the swap curve, and let the discount curve be based on OIS rates. $\endgroup$ – N4v Jun 12 '19 at 13:49
  • 1
    $\begingroup$ I am not that familiar with this topic, but I have not seen something like this before (in QuantLib or in general). In case of the BlackScholesMertonProcess your riskFreeCurve is used for discounting and is the drift of the underlying (under the risk-neutral measure). I do not think that you can add another curve, because the "real" drift of the underlying is not needed for option pricing. $\endgroup$ – Cornholio Jun 19 '19 at 10:29
  • $\begingroup$ ok thanks for your insight. $\endgroup$ – N4v Jun 19 '19 at 13:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.