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.