Scaling a Floating IRS Leg with QuantLib Gearing
Summary
The document explains how to model an interest rate swap whose floating payments are a fraction of an index rate, using QuantLib for Python. Its example targets a floating leg equal to a specified proportion of a LIBOR index, a structure the question notes can be used by US municipal entities to adjust floating payments in relation to a tax rate.
The accepted answer gives two construction approaches: build fixed and floating legs separately and pass a gearing to the Ibor leg, or use the NonstandardSwap class with arrays for notionals, rates, spreads, and gearings that match the payment periods. Gearing scales the index fixing or forward rate; the response also mentions changing notional as a less direct alternative. The second answer identifies this feature as gearing. The examples use a particular index and schedule, so users must adapt conventions and array sizes to their transaction. The exchange explains construction mechanics, not pricing validation or legal and tax treatment.
Key ideas
- QuantLib floating-rate coupons use gearing to multiply the index rate by a chosen factor.
- A swap can be assembled from separate fixed and floating legs with an Ibor leg gearing.
- The NonstandardSwap class can also represent the scaled floating leg using period-aligned parameter arrays.
- Changing notional is mentioned as an alternative, but gearing directly adjusts the coupon rate.
- The example's index, schedule, and conventions may need adaptation for a specific swap.
Tags
Full text
# Building a percent of floating rate IRS in QuantLib
# Building a percent of floating rate IRS in QuantLib
Just starting to learn Quantlib for Python.
I am trying to figure out how you create an interest rate swap where the floating leg is a percent of the floating index. For example, the floating leg would be 70% of 1M USD LIBOR.
Any help is greatly appreciated.
Note: For those who are curious, the % of LIBOR swaps are a common structure for municipal entities in the United States. These entities can issue tax-exempt debt and the floating leg is adjusted so the % = (1 - marginal tax rate).
## Answer by David Duarte (score 5, accepted)
https://quant.stackexchange.com/a/58903
There are two ways to create the swap you want: (1) creating individual legs (`ql.FixedRateLeg` and `IborLeg`) where you can provide a gearing to the `ql.IborLeg` and build a swap (`ql.Swap`) with those or (2) Use the `ql.NonstandardSwap` class
First I'll define the general boilerplate code to use in the examples:
```
import QuantLib as ql
import pandas as pd
yts = ql.YieldTermStructureHandle(ql.FlatForward(2, ql.TARGET(), 0.05, ql.Actual360()))
engine = ql.DiscountingSwapEngine(yts)
index = ql.USDLibor(ql.Period('6M'), yts)
schedule = ql.MakeSchedule(ql.Date(15,6,2021), ql.Date(15,6,2023), ql.Period('6M'))
nominal = [10e6]
```
### 1. Creating individual legs
Before defining a gearing, we can build a simple swap and examine it's floating leg:
```
fixedLeg = ql.FixedRateLeg(schedule, index.dayCounter(), nominal, [0.05])
floatingLeg = ql.IborLeg(nominal, schedule, index)
swap = ql.Swap(fixedLeg, floatingLeg)
swap.setPricingEngine(engine)
print(f"Floating leg NPV: {swap.legNPV(1):,.2f}\n")
pd.DataFrame([{
'fixingDate': cf.fixingDate().ISO(),
'accrualStart': cf.accrualStartDate().ISO(),
'accrualEnd': cf.accrualEndDate().ISO(),
"paymentDate": cf.date().ISO(),
'gearing': cf.gearing(),
'forward': cf.indexFixing(),
'rate': cf.rate(),
"amount": cf.amount()
} for cf in map(ql.as_floating_rate_coupon, swap.leg(1))])
```
Notice by default the gearing will be 1 so the leg rate with be the same as the fixing/forwards.
Next, we use the "gearings" parameter of the `ql.IborLeg` constructor:
```
floatingLeg = ql.IborLeg(nominal, schedule, index, gearings=[0.7])
swap = ql.Swap(fixedLeg, floatingLeg)
swap.setPricingEngine(engine)
print(f"Floating leg NPV: {swap.legNPV(1):,.2f}\n")
pd.DataFrame([{
'fixingDate': cf.fixingDate().ISO(),
'accrualStart': cf.accrualStartDate().ISO(),
'accrualEnd': cf.accrualEndDate().ISO(),
"paymentDate": cf.date().ISO(),
'gearing': cf.gearing(),
'forward': cf.indexFixing(),
'rate': cf.rate(),
"amount": cf.amount()
} for cf in map(ql.as_floating_rate_coupon, swap.leg(1))])
```
Notice here, we have ajusted the leg rate to be the fixing/forwards times the gearing.
Another, a bit more sloppy, way to do it would be to multiply the notional by the gearing on the iborLeg instead of using the gearing parameter.
### 2. NonstandardSwap
The exact same thing can be done with the `ql.NonstandardSwap` class, although you have to be more careful with the constructor as it expects arrays of the notional, rate, spreads, gearings, etc, with the same size as the respective payment schedule.
```
swapType = ql.VanillaSwap.Payer
numDates = (len(schedule)-1)
gearing = [0.7] * numDates
spread = [0.0] * numDates
fixedRateArray = [0.05] * numDates
nominalArray = nominal * numDates
nsSwap = ql.NonstandardSwap(
swapType, nominalArray, nominalArray,
schedule, fixedRateArray, index.dayCounter(),
schedule, index, gearing, spread, index.dayCounter())
nsSwap.setPricingEngine(engine)
print(f"Floating leg NPV: {nsSwap.legNPV(1):,.2f}\n")
pd.DataFrame([{
'fixingDate': cf.fixingDate().ISO(),
'accrualStart': cf.accrualStartDate().ISO(),
'accrualEnd': cf.accrualEndDate().ISO(),
"paymentDate": cf.date().ISO(),
'gearing': cf.gearing(),
'forward': cf.indexFixing(),
'rate': cf.rate(),
"amount": cf.amount()
} for cf in map(ql.as_floating_rate_coupon, swap.leg(1))])
```
## Answer by Dimitri Vulis (score 4)
https://quant.stackexchange.com/a/58900
This feature is called "gearing".
If you look in https://github.com/lballabio/QuantLib/blob/master/ql/cashflows/floatingratecoupon.hpp , you see
```
Real gearing = 1.0,
```
Related question: https://stackoverflow.com/questions/40283195/Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.