In this post we look at valuing callable bonds using QuantLib Python
In this post, I will walk you through on how to value callable bonds in QuantLib Python. The approach to construct a callable bond is lot similar to creating a fixed rate bond in QuantLib. The one additional input that we need to provide here is the details on the callable schedule. If you follow the fixed rate bond example already, this should be fairly straight forward.
As always, we will start with some initializations and imports.
import QuantLib as ql import numpy as np import matplotlib.pyplot as plt %matplotlib inline calc_date = ql.Date(16,8,2016) ql.Settings.instance().evaluationDate = calc_date
For simplicity, I am going to assume that the interest rate term structure is a flat yield curve at 3.5%.
day_count = ql.ActualActual(ql.ActualActual.Bond) rate = 0.035 ts = ql.FlatForward(calc_date, rate, day_count, ql.Compounded, ql.Semiannual) ts_handle = ql.YieldTermStructureHandle(ts)
The call and put schedules for the callable bond is created as shown below. I create a container for holding all the call and put dates using the
CallabilitySchedule class. You can add each call using
Callability class and noting as
Callability.Put for either a call or put.
callability_schedule = ql.CallabilitySchedule() call_price = 100.0 call_date = ql.Date(15,ql.September,2016); null_calendar = ql.NullCalendar(); for i in range(0,24): callability_price = ql.CallabilityPrice( call_price, ql.CallabilityPrice.Clean) callability_schedule.append( ql.Callability(callability_price, ql.Callability.Call, call_date)) call_date = null_calendar.advance(call_date, 3, ql.Months);
What follows next is very similar to the
Schedule that we created in the vanilla fixed rate bond valuation.
issue_date = ql.Date(16,ql.September,2014) maturity_date = ql.Date(15,ql.September,2022) calendar = ql.UnitedStates(ql.UnitedStates.GovernmentBond) tenor = ql.Period(ql.Quarterly) accrual_convention = ql.Unadjusted schedule = ql.Schedule(issue_date, maturity_date, tenor, calendar, accrual_convention, accrual_convention, ql.DateGeneration.Backward, False)
The callable bond is instantiated using the
CallableFixedRateBond class, which accepts the bond inputs and the call / put schedule.
settlement_days = 3 face_amount = 100 accrual_daycount = ql.ActualActual(ql.ActualActual.Bond) coupon = 0.025 bond = ql.CallableFixedRateBond( settlement_days, face_amount, schedule, [coupon], accrual_daycount, ql.Following, face_amount, issue_date, callability_schedule)
In order to value the bond, we need an interest rate model to model the fact that the bond will get called or not in the future depending on where the future interest rates are at. The
TreeCallableFixedRateBondEngine can be used to value the callable bond. Below, the
value_bond function prices the callable bond based on the Hull-White model parameter for mean reversion and volatility.
def value_bond(a, s, grid_points, bond): model = ql.HullWhite(ts_handle, a, s) engine = ql.TreeCallableFixedRateBondEngine(model, grid_points) bond.setPricingEngine(engine) return bond
The callable bond value for a 3% mean reversion and 12% volatility is shown below.
value_bond(0.03, 0.12, 40, bond) print "Bond price: ",bond.cleanPrice()
Bond price: 68.3769646975
The price sensitivity of callable bonds to that of volatility parameter is shown below. As volatility increases, there is a higher chance of it being callable. Hence the value of the bond decreases.
sigmas = np.arange(0.001, 0.15, 0.001) prices = [value_bond(0.03, s, 40, bond).cleanPrice() for s in sigmas]
[<matplotlib.lines.Line2D at 0x7fa0abbdbd90>]
The static cashflows can be accessed using the
for c in bond.cashflows(): print c.date(), " ", c.amount()
December 15th, 2,014 0.618131868132 March 16th, 2,015 0.625 June 15th, 2,015 0.625 September 15th, 2,015 0.625 December 15th, 2,015 0.625 March 15th, 2,016 0.625 June 15th, 2,016 0.625 September 15th, 2,016 0.625 December 15th, 2,016 0.625 March 15th, 2,017 0.625 June 15th, 2,017 0.625 September 15th, 2,017 0.625 December 15th, 2,017 0.625 March 15th, 2,018 0.625 June 15th, 2,018 0.625 September 17th, 2,018 0.625 December 17th, 2,018 0.625 March 15th, 2,019 0.625 June 17th, 2,019 0.625 September 16th, 2,019 0.625 December 16th, 2,019 0.625 March 16th, 2,020 0.625 June 15th, 2,020 0.625 September 15th, 2,020 0.625 December 15th, 2,020 0.625 March 15th, 2,021 0.625 June 15th, 2,021 0.625 September 15th, 2,021 0.625 December 15th, 2,021 0.625 March 15th, 2,022 0.625 June 15th, 2,022 0.625 September 15th, 2,022 0.625 September 15th, 2,022 100.0
Here we explored a minimal example on pricing a callable bond.