0
$\begingroup$

I'd like to valuate a custom Libor3M - Fix swap with QuantLib in Python. With custom I mean, custom starting/end/payment dates for every coupon, a fixed coupon in the float leg (starting_date < evaluation_date, i.e. a swap that already started) and custom amortization amount for every coupon.

I asked a similar question recently (Valuating Custom Amortization Schedule Libor IRS with QuantLib), but the provided code did not worked for my purpose as I need to build these swaps one coupon at a time to avoid dates mismatches between loaded info to QuantLib and my portfolio schedules.

$\endgroup$

2 Answers 2

1
$\begingroup$

Unless you have some really exotic bespoke dates, I'm pretty sure QuantLib will be able to match what you need. The purpose of market conventions is precisely to allow different entities with different systems to arrive at exacly the same cashflows.

Having said that, QuantLib is very flexible so you can actually define each coupon as you wish.

Here is an example of defining a fixed leg with individual coupons:

data = [
    # nominal, rate, startDate, endDate
    (100, 0.015, '15-06-2020', '15-12-2020'),
    (100, 0.015, '15-12-2020', '15-05-2021'),
    (50, 0.025, '15-05-2021', '15-11-2021'),
    (50, 0.012, '15-11-2021', '15-06-2022'),
]

fixedLeg = ql.Leg()
for nominal, rate, startDate, endDate in data:
    startDate = ql.Date(startDate, '%d-%m-%Y')
    endDate = ql.Date(endDate, '%d-%m-%Y')
    fixedCoupon = ql.FixedRateCoupon(
        endDate, nominal, rate, ql.Thirty360(), startDate, endDate)
    fixedLeg.append(fixedCoupon)

calendar = ql.TARGET()
start = ql.Date(15,6,2020)
maturity = calendar.advance(start, ql.Period('2y'))

floatSchedule = ql.MakeSchedule(start, maturity, ql.Period('6M'))
floatLeg = ql.IborLeg([100, 100, 50, 50], floatSchedule, ql.Euribor6M(), ql.Actual360())

swap = ql.Swap(fixedLeg, floatLeg)

for cf in map(ql.as_coupon, swap.leg(0)):
    print(cf.date().ISO(), cf.rate(), cf.amount())

2020-12-15 0.015 0.7500000000000062
2021-05-15 0.015 0.6250000000000089
2021-11-15 0.025 0.6249999999999978
2022-06-15 0.012 0.34999999999999476

Alternatively, you could create a schedule with a list of custom dates:

calendar = ql.TARGET()
start = ql.Date(15,6,2020)
maturity = calendar.advance(start, ql.Period('2y'))

fixedSchedule = ql.Schedule([
    ql.Date(15,6,2020),
    ql.Date(15,12,2020),
    ql.Date(15,5,2021),
    ql.Date(15,11,2021),
    ql.Date(15,6,2022)
])
fixedLeg = ql.FixedRateLeg(fixedSchedule, ql.Thirty360(), [100, 100, 50, 50], [0.015, 0.015, 0.025, 0.012])

floatSchedule = ql.MakeSchedule(start, maturity, ql.Period('6M'))
floatLeg = ql.IborLeg([100, 100, 50, 50], floatSchedule, ql.Euribor6M(), ql.Actual360())

swap = ql.Swap(fixedLeg, floatLeg)

for cf in map(ql.as_coupon, swap.leg(0)):
    print(cf.date().ISO(), cf.rate(), cf.amount())
$\endgroup$
0
$\begingroup$

I think the best structure is

Import QuantLib as ql

ql.NonStandardSwap()

It's highly customizable in that you can set different different notionals (and therefore amortizing plans), different fixed rates, different gearings, different spreads at each date for both legs. And of course different schedules and conventions for both legs.

It can be priced by registering a DiscountSwapEngine just like every swap. I'll give you the link to the Github examples for Quantlib Python where it's specifically shown how to use the class.

$\endgroup$

Your Answer

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

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