0
$\begingroup$

Situation: I would like to make a small script which prices loans (fe annuities or fixed payment) for the ALM purposes. However, I am stuck in the amount of classes existing in Quantlib and would like to understand how to do it properly.

Say I have a simple loan with calendar and fixed interest, which yields monthly principal and interest payments. All of them are trivially calculated using school maths, and making such a calendar is also very easy in pandas. I wrote additional custom class for yield curve to get discounts, so my pandas output looks like this:

pic 1

However, I want to use Quantlib functionality. As far as I understand, there is no built-in loan or mortgage class. The "Bond" class is not applicable for the case. I tried to use FixedRateLeg class for the stream of the principal repayments:

leg = FixedRateLeg(schedule, dayCount, [nominal], [rate])

but it also didn't work due to daycount issues.

So, the question is:

  1. What built-in class am I supposed to use for such a cashflow stream? I am fine with calculating the required values of payments by myself and providing zip(Schedule, Payments) , but if there is a class that calculates such payments by itself, it is also great.
  2. Given such class, how do I merge it with a yield curve to obtain discounts and npv? Assume I already have a yc = ZeroCurve(*args).
  3. Is there a way to perform such calculation with a floating interest rate (apart of merging pre-calculated schedule and payments like in 1)?
$\endgroup$
4
  • $\begingroup$ You could use the ‘Leg’ constructor which accepts an array of cash flows as argument. quantlib-python-docs.readthedocs.io/en/latest/… $\endgroup$ Commented Jul 30, 2021 at 14:35
  • $\begingroup$ So, basicaslly, I do: 1) create schedule 2) iterate over schedule creating SimpleCashFlow and append them to list 3) create Leg passing this list and curve handle 4) use CashFlows built-in functions Okay, I got it, it makes sense. Thank you. $\endgroup$
    – egor_zhev
    Commented Jul 30, 2021 at 14:48
  • $\begingroup$ That sounds doable. But I’d recommend you to wait a bit for better answers / comments; there are people in here who are more experienced with QuantLib’s cash flow features than I am. $\endgroup$ Commented Jul 30, 2021 at 17:17
  • $\begingroup$ I think you're saying that QL's fixed-coupon bond code assumes that the coupon is always 1/frequency, but in reality fixed-coupon loans, loan participation notes, and even a few bonds daycount the coupon - similar to a fixed leg of an interest rate swap. I suggest that you add a flag to Quantlib's fixed-coupon bond constructor (see github.com/lballabio/QuantLib @Luigi Ballabio, scroll down to "Contributing") that would indicate that you're setting up such a bond. Then you'd be able to use bond class for your loans. $\endgroup$ Commented Aug 1, 2021 at 15:01

1 Answer 1

3
$\begingroup$

You could build a bond and then add the first cashflow and build a leg:

start = ql.Date(30, 9, 2021)
maturity = ql.Date(30, 9, 2022)
calendar = ql.TARGET()
nominal = 100e3
freq = ql.Period('6M')
dayCount = ql.Actual360()
coupon = 0.07

bond = ql.FixedRateBond(2, calendar, nominal, start, maturity, freq, [coupon], dayCount)
principal = cf = ql.AmortizingPayment(-nominal, start)

leg = ql.Leg([principal, *bond.cashflows()])
for cf in leg:
    print(cf.date().ISO(), cf.amount())

2021-09-30 -100000.0
2022-03-30 3519.444444444453
2022-09-30 3577.7777777777687
2022-09-30 100000.0

If you need amortizations, use the ql.AmortizingFixedRateBond class (Link).

Then you could value it using the Cashflows functions:

yts = ql.YieldTermStructureHandle(ql.FlatForward(0, ql.TARGET(), 0.05, ql.Actual360()))
ql.CashFlows.npv(leg, yts, False)

1874.481604734974

$\endgroup$
1
  • $\begingroup$ Thank you very much David. It worked. $\endgroup$
    – egor_zhev
    Commented Aug 2, 2021 at 11:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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