I was able to build a discount curve for the Treasury market. However, I'm looking to use this to find the key rate risks of an individual bond (and eventually a portfolio of bonds).
The key rate risk I'm looking for is if I have a 30Y bond and we shift the 1y rate that was used to discount the bond, while holding the other rates constant, how much does the price of the bond change by? Repeating this for the tenors (eg. 2Y, 5Y, 7Y, etc) and summing the result should get you to the overall duration of the bond, but provides a better view of how the risk exposure breaks down.
http://www.investinganswers.com/financial-dictionary/bonds/key-rate-duration-6725
Is anyone aware of any documentation that demonstrates how to do this? Thank you.
Given that you have already built the bond and the discount curve, and you have linked them in some way similar to:
discount_handle = RelinkableYieldTermStructureHandle(discount_curve)
bond.setPricingEngine(DiscountingBondEngine(discount_handle))
you can first add a spread over the existing discount curve and then use the modified curve to price the bond. Something like:
nodes = [ 1, 2, 5, 7, 10 ] # the durations
dates = [ today + Period(n, Years) for n in nodes ]
spreads = [ SimpleQuote(0.0) for n in nodes ] # null spreads to begin
new_curve = SpreadedLinearZeroInterpolatedTermStructure(
YieldTermStructureHandle(discount_curve),
[ QuoteHandle(q) for q in spreads ],
dates)
will give you a new curve with initial spreads all at 0 (and a horrible class name) that you can use instead of the original discount curve:
discount_handle.linkTo(new_curve)
After the above, the bond should still return the same price (since the spreads are all null).
When you want to calculate a particular key-rate duration, you can move the corresponding quote: for instance, if you want to bump the 5-years quote (the third in the list above), execute
spreads[2].setValue(0.001) # 10 bps
the curve will update accordingly, and the bond price should change.
A note: the above will interpolate between spreads, so if you move the 5-years points by 10 bps and you leave the 2-years point unchanged, then a rate around 3 years would move by about 3 bps. To mitigate this (in case that's not what you want), you can add more points to the curve and restrict the range that varies. For instance, if you add a point at 5 years minus one month and another at 5 years plus 1 month, then moving the 5-years point will only affect the two months around it.