SPB Git

Repository Public Research preview

02_daily_factors.py 2.3 KB 35 lines python

1"""Daily Nelson–Siegel factors from FRED CMT yields (primary) and GSW zero yields (robustness)."""2import sys, json3from pathlib import Path4import numpy as np, pandas as pd5ROOT = Path(__file__).resolve().parents[1]; sys.path.insert(0, str(ROOT / "src"))6from wp47.ns import read_fred, fit_panel, estimate_lambda, LAMBDA_DL, loadings7OUT = ROOT / "results" / "metrics"; OUT.mkdir(parents=True, exist_ok=True)8y = read_fred(ROOT / "data/external/fred").loc["2007-01-01":]9y = y[y.notna().sum(axis=1) >= 8]10F, R = fit_panel(y)11lam_hat = estimate_lambda(y.loc["2008":])12F_hat, R_hat = fit_panel(y, lam_hat)13F.to_csv(OUT / "daily_factors_cmt.csv"); F_hat.to_csv(OUT / "daily_factors_cmt_lambdahat.csv")14# GSW: zero-coupon yields SVENY01..SVENY30 (percent, continuously compounded)15g = pd.read_csv(ROOT / "data/external/fed/feds200628.csv", skiprows=9, na_values=["NA"])16g["Date"] = pd.to_datetime(g["Date"]); g = g.set_index("Date").loc["2007-01-01":]17cols = [f"SVENY{i:02d}" for i in range(1, 31) if f"SVENY{i:02d}" in g.columns]18taus = np.array([int(c[-2:]) for c in cols], float)19X = loadings(taus, LAMBDA_DL)20G = g[cols].dropna()21B = np.linalg.lstsq(X, G.values.T, rcond=None)[0].T22FG = pd.DataFrame(B, index=G.index, columns=["level", "slope", "curvature"]); FG.to_csv(OUT / "daily_factors_gsw.csv")23d = F.diff().dropna(); 24summary = {"lambda_dl": LAMBDA_DL, "lambda_hat_2008_2026": float(lam_hat), "n_days": int(F.dropna().shape[0]),25           "first": str(F.dropna().index[0].date()), "last": str(F.dropna().index[-1].date()),26           "rmse_fit_bp": float(np.sqrt(np.nanmean(R.loc["2008":].values ** 2)) * 100),27           "rmse_fit_bp_lambdahat": float(np.sqrt(np.nanmean(R_hat.loc["2008":].values ** 2)) * 100),28           "factor_means_2008_": F.loc["2008":].mean().round(3).to_dict(), "factor_sd_2008_": F.loc["2008":].std().round(3).to_dict(),29           "dfactor_sd_bp": (d.loc["2008":].std() * 100).round(2).to_dict(),30           "corr_dfactors": d.loc["2008":].corr().round(3).to_dict(),31           "corr_with_gsw_dfactors": {k: float(d[k].corr(FG.diff()[k].reindex(d.index))) for k in d.columns},32           "corr_level_vs_dgs10": float(F["level"].corr(y["DGS10"])), "corr_slope_vs_spread10y3m": float(F["slope"].corr(y["DGS3MO"] - y["DGS10"]))}33json.dump(summary, open(OUT / "daily_factors_summary.json", "w"), indent=1)34print(json.dumps(summary, indent=1))35
Files main
Menu

Theme