4
$\begingroup$

I'm trying to figure out if it's possible to value structured products, mainly loans, in quantlib. The idea is to build a bond class with different cash flows. For example, a loan could have coupons that only pay interest, could be only-amortizing or even the coupons can increase the nominal amount.

Also, for FTP purposes, one could be interested in the yield that returns the par value of the loan. Is there a native function for that?

It's possible to do this with the current release in python or c++?

Being more precise, imagine these two examples:

First, I have a loan that is issued with a face value of 2000 and has two redemptions of 1000: enter image description here

I've been successful building the cashflows with the Bond class with a simple code:

def bond_from_table(df,notional, outlay_date, day_counter, r=0.03):
    eval_date = ql.Settings.instance().evaluationDate
    coupons = []
    redemptions = []
    redem = 0
    for i in range(df.shape[0]):
        start_date = df.at[i,'Start']
        end_date = df.at[i,'End']
        notional -= redem        
        redem = df.at[i,'Capital']
        redemptions.append(ql.Redemption(redem,end_date))    
    coupons.append(ql.FixedRateCoupon(end_date,notional,r,day_counter,start_date,end_date))    

    leg = ql.Leg(coupons)
    loan = ql.Bond(0,calendar,eval_date,leg)
    return loan

As it seems that the Bond class constructs the redemptions from the nominals that are being paid. The good thing is that using the bond class we can access all the bond functions and other things as callability and so on.

But! if I try to build something like this:

enter image description here

Where after the initial 2000 payment to the client, another 400 are paid in the next coming dates (that's why the - sign) -at the end, you receive the total lend- I would get an error saying the nominal is increasing, which is true. I guess there might be another route for this, but I think I'll be losing the functionalities of the bond class.

Any ideas? Thanks in advance,

$\endgroup$
  • 1
    $\begingroup$ FTP = Fund Transfer Pricing ? $\endgroup$ – Alex C Sep 11 at 19:21
  • $\begingroup$ Yes, for ALM purpose $\endgroup$ – Jose Pedro Melo Sep 11 at 19:42
  • 1
    $\begingroup$ It might be helpful if you listed the features of structured loans that you want to use to project the cash flows. For example, I remember an Indonesian loan where at every reset the issuer had the option: pay 3mo libor + spread in 3 months, or 6mo libor + spread and reset in 6 months. That's not what you meant, right? $\endgroup$ – Dimitri Vulis Sep 13 at 2:42
  • $\begingroup$ I see your point, i'll update the post with an example. $\endgroup$ – Jose Pedro Melo Sep 15 at 0:03
  • 1
    $\begingroup$ You assume that the redemptions (amortizations) happen on coupon days, but I've seen loans where the notional way paid on arbitrary days in the middle of coupon period. The coupon paid in the ens of the period accrues on different notional amounts before and after. I've also seen loans whose notional increased through PIK or disbursements. $\endgroup$ – Dimitri Vulis Sep 15 at 18:58
3
+50
$\begingroup$

As you've found, the Bond class assumes that you're buying a bond; that is, you're paying a notional upfront and it will be returned to you in one solution or in a series of amortizing payments. The assumption is coded here, and you might try removing it and recompiling but I don't suggest it. It might be that other parts of the code rely on that check having passed successfully.

What you might do instead is to take both sets of cash flows (coupons and redemptions), put together, sort them, and consider the resulting leg as your loan. It probably won't give you all the functionality of the bond (e.g., lazy recalculation when something changes) but you'll be able to analyze them using the methods of the CashFlows class. This will give you NPV, BPS, yield, and measures like duration, as well as some static info. Unfortunately, it won't let you access features like callability which are coded inside some specific bond class.

$\endgroup$
  • $\begingroup$ Hi Luigi, thanks for the answer. I did what you mention (remove the assumption and recompile the library) and everything seems to be working correctly, even the notional is being increased as time passes. Could you point me out an example of what could be in conflict with that? Also, what do you think about creating a class for this type of instrument in the base library, would it be worth it? $\endgroup$ – Jose Pedro Melo Sep 20 at 0:57
  • 1
    $\begingroup$ I was thinking of the normalization of the price to the current notional, but it should work, so mostly I was being prudent :) A separate instrument would make sense, though. This way we could make different assumptions explicitly. $\endgroup$ – Luigi Ballabio Sep 20 at 8:24
  • $\begingroup$ Thanks again, I'll give it a look to see how can be implemented. One last question, usually in loans one is interested in the coupon rate that returns certain NPV, instead of the usual IRR. I think one easy way of doing this calculation is iterate over the coupon rate and create an instance of the bond/loan class every time until the NPV is reached, but I feel like it's a bit dirty. I was looking at the InterestRate class and the rate attribute is private and even if I change it I don't think that would update the bond cashflows. Is there any class that allows you to do something like this? $\endgroup$ – Jose Pedro Melo Sep 20 at 14:59
  • $\begingroup$ No, there isn't. $\endgroup$ – Luigi Ballabio Sep 21 at 20:34

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.