De-mean the dataset
Notation
Let $\mathbf{Y} \in \mathbb{R}^{T \times N}$ denote the raw spot yields (as defined earlier), before logging or differencing.
The dataset arriving at this step is not $\mathbf{Y}$ — it's the log-differenced series produced in Step 4: $\widetilde{\mathbf{Y}} \in \mathbb{R}^{(T-12)\times N}$, entries $\widetilde{y}_{s,n}$, $s=1,\dots,T-12$. To keep $\mathbf{Y}$ reserved for the raw yields, this step's input is written as $\widetilde{\mathbf{Y}}$ throughout, never plain $\mathbf{Y}$.
Demeaning proceeds in two operations:
- Column means — for each maturity $n$: $\bar{\widetilde{y}}_n = \dfrac{1}{T-12}\sum_{s=1}^{T-12} \widetilde{y}_{s,n}$, giving a mean vector $\vec{\widetilde{y}} \in \mathbb{R}^N$.
- Demean — subtract each column's mean from every entry in that column: $\widetilde{y}^{\,c}_{s,n} = \widetilde{y}_{s,n} - \bar{\widetilde{y}}_n$, producing the demeaned matrix $\widetilde{\mathbf{Y}}_c$.
step 1 - calculate the column means
import subprocess
%run ./dataframes/step5_column_of_means.py
%run ./dataframes/truncate_with_ellipsis.py
df = column_of_means()
subprocess.run(['wl-copy'], input=truncate_with_ellipsis(df, 3).to_html(index=False).encode())
| maturity | mean |
|---|---|
| 5 | 0.260555 |
| 5.5 | 0.243345 |
| 6 | 0.228913 |
| ... | ... |
| 39 | 0.125069 |
| 39.5 | 0.125486 |
| 40 | 0.125675 |

step 2 - calculate demeaned dataset
import subprocess
%run ./dataframes/step5_demeaning.py
%run ./dataframes/truncate_with_ellipsis.py
df = demeaning()
subprocess.run(['wl-copy'], input=truncate_with_ellipsis(df, 3).to_html(index=False).encode())
| Date | 5 | 5.5 | ... | 39 | 39.5 | 40 | |
|---|---|---|---|---|---|---|---|
| 2017-03-31 | -0.870814 | -0.800155 | ... | -0.439461 | -0.441606 | -0.448226 | |
| 2017-04-30 | -1.121694 | -1.026104 | ... | -0.484923 | -0.480886 | -0.482991 | |
| 2017-05-31 | -1.096803 | -0.999671 | ... | -0.404653 | -0.406653 | -0.408443 | |
| ... | ... | ... | ... | ... | ... | ... | |
| 2024-10-31 | -0.288925 | -0.26932 | ... | -0.137835 | -0.138279 | -0.138523 | |
| 2024-11-29 | -0.27058 | -0.248357 | ... | -0.091769 | -0.092038 | -0.092152 | |
| 2024-12-31 | -0.017668 | 0.009652 | ... | 0.094026 | 0.094107 | 0.094921 |
Python
filename: step5_column_of_means.py
from dataframes.step4_differencing import *
import pandas as pd
def column_of_means():
df = differencing()
value_cols = df.columns[1:]
means = df[value_cols].mean()
df_means = pd.DataFrame({"maturity": means.index, "mean": means.values})
return df_means
column-wise means of the log-differenced yields
filename: step5_demeaning.py
from dataframes.step5_column_of_means import *
def demeaning():
df = differencing()
means = column_of_means().set_index("maturity")["mean"]
value_cols = df.columns[1:]
df_demeaned = df.copy()
df_demeaned[value_cols] = df[value_cols] - means
return df_demeaned
subtract each column's mean from every value in that column