In [1]:

```
from scipy import stats
import pandas as pd
import numpy as np
import plotly.express as px
from plotly.subplots import make_subplots
import plotly.graph_objects as go
import plotly.io as pio
import statsmodels.api as sm
import pathlib
import sys
utils_path = pathlib.Path().absolute().parent.parent
sys.path.append(utils_path.__str__())
import utils.layout as lay
from utils.functions import PCA
```

In [2]:

```
pio.templates.default = 'simple_white+blog_mra'
```

If we consider a portfolio represented as a series of cash flows at specified maturities (1 month, 2 months, ... , 60 months), we can obtain the P&L of the portfolio is approximated as the weighted sum of changes in the interest rate risk factors with weights given by the present value of a basis point at the maturity corresponding to the interest rate.

\begin{equation} \Delta {P_{t}} = - \sum_{i=1}^{n} PV01_{i}\Delta R_{i,n}= - p' \Delta R_{t} \end{equation}where $\Delta R_{t} = (\Delta R_{1,t}, \ldots, \Delta R_{n,t})$ is the vector of changes in the interest rate risk factors at fixed maturities at time $t$ and $ p = (PV01_{1}, \ldots , PV01_{n})$ is the vector of constant PV01 sensitivities, which are held fixed at his current value in order to compute interest rate risk measures on the *current portfolio*.

By performing PCA on the covariance matrix of changes in interest rates we get the principal component approximation for each interest rate change:

\begin{equation} \Delta {R_{it}} \approx w_{i,1}P_{1t} + ... + w_{ik}P_{kt} \end{equation}The $j$th principal component risk factor sensitivity can then be obtained as

\begin{equation} w_{j} = - \sum_{i=1}^{n} PV01_{i}w_{ij} \end{equation}In this case, PCA allows us to reduce the dimentionality of the model from n=60 to k=3. Moreover, the risk factors have an intuitive representation:

- the first component captures an approximately parallel shift in the entire yield curve
- the second component captures a change in slope
- the third component captures a change in curvature of the yield curve.

In [3]:

```
df = pd.read_excel(r"data\Example II.2.1.xls", sheet_name="PV01").iloc[:, :4]
spot = pd.read_excel(r"data\Example II.2.1.xls", sheet_name="Spot").set_index("Date")
spot_cols = [str(i) + "y" for i in spot.columns]
spot.columns = spot_cols
diff_bps = spot.diff()[1:] *100
```

$$ PV01_{T,s}^{\$} \approx \$ N \cdot 10^{-4} \cdot T_{i} \cdot (1 + R_{T,s}^{\$})^{-(T_{i}+1)} $$

In [4]:

```
df["PV01"] = df["CashFlow"]*100*df["Maturity"]*(1+df["SpotRate"])**(-(df["Maturity"]+1))
```

$$\begin{array}{lrrr}
\hline
& SpotRate & CashFlow & PV01 \\
Maturity & & & \\
\hline
1 & 0.05 & 3.00 & 273.39 \\
2 & 0.04 & 2.00 & 352.15 \\
3 & 0.04 & 1.00 & 253.42 \\
4 & 0.04 & 0.50 & 161.58 \\
5 & 0.04 & 1.00 & 385.86 \\
6 & 0.04 & 1.25 & 552.74 \\
7 & 0.04 & 2.00 & 985.54 \\
8 & 0.05 & 0.50 & 269.08 \\
9 & 0.05 & 0.10 & 57.88 \\
10 & 0.05 & 0.20 & 123.04 \\
11 & 0.05 & 0.80 & 518.17 \\
12 & 0.05 & 1.00 & 676.63 \\
13 & 0.04 & 0.25 & 175.58 \\
14 & 0.04 & 0.10 & 72.50 \\
15 & 0.04 & -0.50 & -372.50 \\
16 & 0.04 & -0.50 & -381.26 \\
17 & 0.04 & -1.00 & -777.79 \\
18 & 0.04 & -0.75 & -593.25 \\
19 & 0.04 & -0.50 & -401.17 \\
20 & 0.04 & -0.25 & -203.00 \\
\hline
\end{array}$$

In [5]:

```
filt_cols = ["1y", "2y", "3y", "4y", "5y", "7y", "10y", "15y", "20y"]
fig = px.line(spot[filt_cols])
fig.update_layout(title_text="UK governement interest rates, monthly, 1995-2007" ,
legend_title = "", xaxis_title = "", yaxis_title = "%")
fig.show()
```