# How to calculate bond yield in QuantLib - Python

I want to calculate yield of bond having market price and coupons. I try to replicate C++ from (https://mhittesdorf.wordpress.com/2013/03/03/introducing-quantlib-internal-rate-of-return/) in Python but without success. How to use "bisection" solver in quantlib-python?

solver = ql.Bisection()
solver_max = 0.5
solver_min = 0.1
solver_maxEvaluations = 1000
solution = solver.solve(?, solver_maxEvaluations, solver_min, solver_max)


NotImplementedError: Wrong number or type of arguments for overloaded function 'Bisection_solve'.
Possible C/C++ prototypes are:
Bisection::solve(PyObject *,Real,Real,Real)
Bisection::solve(PyObject *,Real,Real,Real,Real)

What is the "PyObject*" in this case?

• Hi Kirill Dolmatov, welcome to Quant.SE! Without looking the QuantLib why of doing things probably makes sense. Why don't you try to fix that. As it stands the question is: are there other ways? Which is pretty vague and can be answered with: Yes – Bob Jansen Apr 12 '16 at 16:57
• Maybe more of a programming question but I think the API of QuantLib is on-topic here. – Bob Jansen Apr 13 '16 at 14:03
• PYobject is just a wrapper for quantlib in Python. – HelloWorld Apr 13 '16 at 16:18
• Have you tried getting rid of the question mark? Your error message is pretty obvious. – HelloWorld Apr 13 '16 at 16:20
• @StudentT , I put the question mark because I don't know what I should to put. I try to put "ql.FixedRateBond" but then get "RuntimeError: failed to call Python function". It's pretty obvious that if I put question mark I get "SyntaxError: invalid syntax". Have you any idea that I should to put? – Kirill Dolmatov Apr 14 '16 at 7:16

In the call to Bisection.solve, the question mark must be the Python function whose zero you want to find. In your case, it should be something reproducing the logic of IRRSolver::operator() in Mick Hittesdorf's code, i.e., something like this (which I haven't tested):

cashflows = fixedRateBond.cashflows()
npv = fixedRateBond.NPV()
def price_error_given_yield(rate):
interestRate = InterestRate(rate, ActualActual(ActualActual.Bond),
Compounded, Annual)
return CashFlows.npv(cashflows, interestRate, False) - npv

irr = solver.solve(price_error_given_yield, accuracy, guess, min, max)


The idea is that you write a function that takes a yield and tells you how much the corresponding price differs from the target price; the solver takes the function and returns its zero, that is, the value of the input yield for which the result (i.e. the difference from the target price) is zero.

This said, Mick's approach is useful for educational purposes but it duplicates functionality that is already available from the bond object. All you need is to call

fixedRateBond.bondYield(targetPrice, ActualActual(ActualActual.Bond),
Compounded, Annual)


Note, though, that the targetPrice above should be the clean price, so in your case what's returned by fixedRateBond.cleanPrice() rather than fixedRateBond.NPV().

• Do you have an example of how to define fixedRateBond to get access to bondYield and cleanPrice methods? When I try to do this myself, it gives an error null price engine because it requires setting an engine, which also requires definition... however, I am more interested in replicating the excel YIELD function here support.office.com/en-us/article/… which doesn't require defining such engine nor the yield term structure... – tsando Sep 14 '17 at 14:17
• You need to use the overload of bondYield that takes the clean price as an input (that is, bond.bondYield(price, day_count, compounding, frequency)). If you use the other overload (bond.bondYield(day_count, compounding, frequency)) the bond tries to calculate the price and thus needs an engine. – Luigi Ballabio Sep 14 '17 at 15:11