Applying Amortization to Instruments#
Standard Amortization#
The FixedLeg
and FloatLeg
classes both
have amortization
as an input argument which defines the reduction (or addition) of
a notional amount each period.
In [1]: curve = Curve({dt(2000, 1, 1): 1.0, dt(2010, 1, 1): 0.65})
In [2]: fxl = FixedLeg(
...: effective=dt(2000, 1, 1),
...: termination="1y",
...: frequency="Q",
...: notional=10e6,
...: amortization=1e6, # <- 1mm reduction per period
...: )
...:
In [3]: fxl.cashflows(curve)[["Type", "Acc Start", "Notional"]]
Out[3]:
Type Acc Start Notional
0 FixedPeriod 2000-01-01 10000000.00
1 FixedPeriod 2000-04-01 9000000.00
2 FixedPeriod 2000-07-01 8000000.00
3 FixedPeriod 2000-10-01 7000000.00
In [4]: fll = FloatLeg(
...: effective=dt(2000, 1, 1),
...: termination="1y",
...: frequency="M",
...: notional=10e6,
...: amortization=0.5e6, # 0.5mm reduction per period
...: )
...:
In [5]: fll.cashflows(curve)[["Type", "Acc Start", "Notional"]]
Out[5]:
Type Acc Start Notional
0 FloatPeriod 2000-01-01 10000000.00
1 FloatPeriod 2000-02-01 9500000.00
2 FloatPeriod 2000-03-01 9000000.00
3 FloatPeriod 2000-04-01 8500000.00
4 FloatPeriod 2000-05-01 8000000.00
5 FloatPeriod 2000-06-01 7500000.00
6 FloatPeriod 2000-07-01 7000000.00
7 FloatPeriod 2000-08-01 6500000.00
8 FloatPeriod 2000-09-01 6000000.00
9 FloatPeriod 2000-10-01 5500000.00
10 FloatPeriod 2000-11-01 5000000.00
11 FloatPeriod 2000-12-01 4500000.00
Amortization is expressed in a specific notional amount reduction per period so,
when applied to an IRS
, each leg with different
frequencies should be input directly. Observe the directions.
In [6]: irs = IRS(
...: effective=dt(2000, 1, 1),
...: termination="1Y",
...: frequency="Q",
...: leg2_frequency="S",
...: notional=1e6,
...: amortization=2e5, # <- Reduces notional on 1st July to 600,000
...: leg2_amortization=-4e5, # <- Aligns the notional on 1st July
...: )
...:
In [7]: irs.cashflows(curve)[["Type", "Acc Start", "Notional"]]
Out[7]:
Type Acc Start Notional
leg1 0 FixedPeriod 2000-01-01 1000000.00
1 FixedPeriod 2000-04-01 800000.00
2 FixedPeriod 2000-07-01 600000.00
3 FixedPeriod 2000-10-01 400000.00
leg2 0 FloatPeriod 2000-01-01 -1000000.00
1 FloatPeriod 2000-07-01 -600000.00
Legs with Notional Exchange#
If a Leg has a final notional exchange then any amortised amount would
typically be expected to be paid out at the same time as the notional reduction.
This is visible on FixedLeg
and FloatLeg
classes when there is a final_exchange
. The final cashflow will be reduced by the
amount of interim exchanges that have already occurred.
In [8]: fxl = FixedLeg(
...: effective=dt(2000, 1, 1),
...: termination="1y",
...: frequency="Q",
...: notional=10e6,
...: final_exchange=True,
...: amortization=1e6, # <- 1mm reduction and notional exchange per period
...: )
...:
In [9]: fxl.cashflows(curve)[["Type", "Period", "Acc Start", "Notional"]]
Out[9]:
Type Period Acc Start Notional
0 FixedPeriod Regular 2000-01-01 10000000.00
1 Cashflow Amortization NaT 1000000.00
2 FixedPeriod Regular 2000-04-01 9000000.00
3 Cashflow Amortization NaT 1000000.00
4 FixedPeriod Regular 2000-07-01 8000000.00
5 Cashflow Amortization NaT 1000000.00
6 FixedPeriod Regular 2000-10-01 7000000.00
7 Cashflow Exchange NaT 7000000.00
In [10]: fll = FloatLeg(
....: effective=dt(2000, 1, 1),
....: termination="1y",
....: frequency="Q",
....: notional=10e6,
....: final_exchange=True,
....: amortization=1e6, # <- 1mm reduction and notional exchange per period
....: )
....:
In [11]: fll.cashflows(curve)[["Type", "Period", "Acc Start", "Notional"]]
Out[11]:
Type Period Acc Start Notional
0 FloatPeriod Regular 2000-01-01 10000000.00
1 Cashflow Amortization NaT 1000000.00
2 FloatPeriod Regular 2000-04-01 9000000.00
3 Cashflow Amortization NaT 1000000.00
4 FloatPeriod Regular 2000-07-01 8000000.00
5 Cashflow Amortization NaT 1000000.00
6 FloatPeriod Regular 2000-10-01 7000000.00
7 Cashflow Exchange NaT 7000000.00
An Instrument that can potentially use notional exchanges is a Non-MTM XCS
.
In [12]: xcs = XCS(
....: effective=dt(2000, 1, 1),
....: termination="1y",
....: spec="eurusd_xcs",
....: notional=5e6,
....: amortization=1e6, # <- 1mm reduction and notional exchange per period
....: leg2_mtm=False,
....: )
....:
In [13]: xcs.cashflows(curve, fx=FXRates({"eurusd": 2.0}, base="usd"))[["Type", "Period", "Acc Start", "Payment", "Ccy", "Notional"]]
Out[13]:
Type Period Acc Start Payment Ccy Notional
leg1 0 Cashflow Exchange NaT 2000-01-03 EUR -5000000.00
1 FloatPeriod Regular 2000-01-03 2000-04-05 EUR 5000000.00
2 Cashflow Amortization NaT 2000-04-03 EUR 1000000.00
3 FloatPeriod Regular 2000-04-03 2000-07-06 EUR 4000000.00
4 Cashflow Amortization NaT 2000-07-03 EUR 1000000.00
5 FloatPeriod Regular 2000-07-03 2000-10-04 EUR 3000000.00
6 Cashflow Amortization NaT 2000-10-02 EUR 1000000.00
7 FloatPeriod Regular 2000-10-02 2001-01-04 EUR 2000000.00
8 Cashflow Exchange NaT 2001-01-02 EUR 2000000.00
leg2 0 Cashflow Exchange NaT 2000-01-03 USD 10000000.00
1 FloatPeriod Regular 2000-01-03 2000-04-05 USD -10000000.00
2 Cashflow Amortization NaT 2000-04-03 USD -2000000.00
3 FloatPeriod Regular 2000-04-03 2000-07-06 USD -8000000.00
4 Cashflow Amortization NaT 2000-07-03 USD -2000000.00
5 FloatPeriod Regular 2000-07-03 2000-10-04 USD -6000000.00
6 Cashflow Amortization NaT 2000-10-02 USD -2000000.00
7 FloatPeriod Regular 2000-10-02 2001-01-04 USD -4000000.00
8 Cashflow Exchange NaT 2001-01-02 USD -4000000.00
Indexed Legs#
We can also apply amortization
to IndexLegs. Cashflows paid at future dates
will also be indexed by the index.
In [14]: icurve = IndexCurve({dt(2000, 1, 1): 1.0, dt(2010, 1, 1): 0.75}, index_base=100.0)
In [15]: il = IndexFixedLeg(
....: effective=dt(2000, 1, 1),
....: termination="1y",
....: frequency="M",
....: notional=10e6,
....: index_base=100.0,
....: amortization=0.5e6, # 0.5mm reduction per period
....: )
....:
In [16]: il.cashflows(icurve, curve)[["Type", "Acc Start", "Notional"]]
Out[16]:
Type Acc Start Notional
0 IndexFixedPeriod 2000-01-01 10000000.00
1 IndexFixedPeriod 2000-02-01 9500000.00
2 IndexFixedPeriod 2000-03-01 9000000.00
3 IndexFixedPeriod 2000-04-01 8500000.00
4 IndexFixedPeriod 2000-05-01 8000000.00
5 IndexFixedPeriod 2000-06-01 7500000.00
6 IndexFixedPeriod 2000-07-01 7000000.00
7 IndexFixedPeriod 2000-08-01 6500000.00
8 IndexFixedPeriod 2000-09-01 6000000.00
9 IndexFixedPeriod 2000-10-01 5500000.00
10 IndexFixedPeriod 2000-11-01 5000000.00
11 IndexFixedPeriod 2000-12-01 4500000.00
In [17]: il = IndexFixedLeg(
....: effective=dt(2000, 1, 1),
....: termination="1y",
....: frequency="Q",
....: notional=10e6,
....: index_base=100.0,
....: final_exchange=True,
....: amortization=1e6, # 1mm reduction per period
....: )
....:
In [18]: il.cashflows(icurve, curve)[["Type", "Period", "Acc Start", "Payment", "Ccy", "Notional", "Index Ratio", "Index Val"]]
Out[18]:
Type Period Acc Start Payment Ccy Notional Index Ratio Index Val
0 IndexFixedPeriod Regular 2000-01-01 2000-04-03 GBP 10000000.00 1.01 100.83
1 IndexCashflow Amortization NaT 2000-04-03 GBP 1000000.00 1.01 100.85
2 IndexFixedPeriod Regular 2000-04-01 2000-07-03 GBP 9000000.00 1.02 101.66
3 IndexCashflow Amortization NaT 2000-07-03 GBP 1000000.00 1.02 101.68
4 IndexFixedPeriod Regular 2000-07-01 2000-10-03 GBP 8000000.00 1.03 102.50
5 IndexCashflow Amortization NaT 2000-10-03 GBP 1000000.00 1.03 102.52
6 IndexFixedPeriod Regular 2000-10-01 2001-01-03 GBP 7000000.00 1.03 103.34
7 IndexCashflow Exchange NaT 2001-01-01 GBP 7000000.00 1.03 103.34
Unsupported#
Instruments that currently do not support amortization are MTM-XCS and Bonds.
In [19]: try:
....: XCS(
....: effective=dt(2000, 1, 1),
....: termination="1y",
....: spec="eurusd_xcs",
....: notional=5e6,
....: amortization=1e6,
....: )
....: except Exception as e:
....: print(e)
....:
`amortization` cannot be supplied to a `FixedLegExchangeMtm` type.
In [20]: try:
....: FixedRateBond(
....: effective=dt(2000, 1, 1),
....: termination="1y",
....: spec="us_gb",
....: notional=5e6,
....: amortization=1e6,
....: fixed_rate=2.0,
....: )
....: except Exception as e:
....: print(e)
....:
`amortization` for FixedRateBond must be zero.
In [21]: try:
....: IndexFixedRateBond(
....: effective=dt(2000, 1, 1),
....: termination="1y",
....: spec="us_gb",
....: notional=5e6,
....: amortization=1e6,
....: fixed_rate=2.0,
....: index_base=100.0,
....: )
....: except Exception as e:
....: print(e)
....:
`amortization` for IndexFixedRateBond must be zero.