GitHub profile

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:

  1. 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$.
  2. 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