Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problems fitting the current Bund yield curve #17

Open
pquan opened this issue Oct 11, 2023 · 1 comment
Open

Problems fitting the current Bund yield curve #17

pquan opened this issue Oct 11, 2023 · 1 comment

Comments

@pquan
Copy link

pquan commented Oct 11, 2023

  • Nelson-Siegel-Svensson Model version: 0.5.0
  • Python version: 3.10.3
  • Operating System: Anaconda on Windows 11 x64

Description

I'm trying to fit the current Bund yield curve. The model is having issues fitting it, and is very susceptible to the initial outliers. Even removing the firs couple of outliers in the beginning of the curve, it still fails.

What I Did

Here's the current yields tuple array:
[(217, 3.7) (177, 3.67) (65, 3.61) (247, 3.6) (156, 3.52) (127, 3.5) (338, 3.5) (309, 3.43) (373, 3.4) (428, 3.38) (519, 3.28) (493, 3.27) (548, 3.21) (610, 3.17) (85, 3.09) (674, 3.09) (708, 3.04) (730, 3.01) (5330, 3.0) (5745, 3.0) (4834, 2.98) (4600, 2.92) (858, 2.91) (4234, 2.9) (912, 2.89) (3919, 2.82) (1094, 2.81) (1039, 2.79) (3596, 2.77) (3415, 2.75) (3415, 2.74) (1283, 2.73) (1223, 2.73) (1362, 2.72) (3231, 2.72) (3049, 2.69) (2592, 2.69) (2227, 2.69) (1465, 2.68) (2642, 2.67) (2865, 2.67) (1646, 2.67) (2500, 2.67) (2684, 2.66) (1496, 2.66) (1404, 2.66) (2500, 2.66) (1546, 2.66) (2865, 2.65) (1588, 2.65) (2135, 2.65) (1862, 2.64) (2277, 2.63) (2319, 2.63) (1728, 2.62) (1954, 2.61) (1770, 2.61) (1465, 2.6)]


t = np.array(x['t'])
y = np.array(x['y'])

print(*zip(t,y))

curve, status = calibrate_ns_ols(t, y, tau0=60) # starting value of 1.0 will make a much worse fit.
assert status.success
print(status)
i = np.linspace(min(t), max(t), 100)
x_t = dt.date.today() + np.array([dt.timedelta(days=int(d)) for d in i]) 

plt.subplots(figsize=(10,4))

plt.plot(x_t, curve(i))
plt.scatter(x['Expiry'],y)
plt.show()
curve

The curve shows as: NelsonSiegelCurve(beta0=2.5846778100250116, beta1=-0.0699579846346146, beta2=3.514586203990244, tau=91.21267697168356)

Removing the first few outliers, using only the following data: (217, 3.7) (177, 3.67) (247, 3.6) (156, 3.52) (127, 3.5) (338, 3.5) (309, 3.43) (373, 3.4) (428, 3.38) (519, 3.28) (493, 3.27) (548, 3.21) (610, 3.17) (674, 3.09) (708, 3.04) (730, 3.01) (5330, 3.0) (5745, 3.0) (4834, 2.98) (4600, 2.92) (858, 2.91) (4234, 2.9) (912, 2.89) (3919, 2.82) (1094, 2.81) (1039, 2.79) (3596, 2.77) (3415, 2.75) (3415, 2.74) (1283, 2.73) (1223, 2.73) (1362, 2.72) (3231, 2.72) (3049, 2.69) (2592, 2.69) (2227, 2.69) (1465, 2.68) (2642, 2.67) (2865, 2.67) (1646, 2.67) (2500, 2.67) (2684, 2.66) (1496, 2.66) (1404, 2.66) (2500, 2.66) (1546, 2.66) (2865, 2.65) (1588, 2.65) (2135, 2.65) (1862, 2.64) (2277, 2.63) (2319, 2.63) (1728, 2.62) (1954, 2.61) (1770, 2.61) (1465, 2.6)

The NSS Curve is still not fitted and results in NelsonSiegelCurve(beta0=2.5938433203011453, beta1=-4.606659531771271, beta2=9.466695852698784, tau=60.88625970741441)

The NSS model fits even worse.

Now, the curves are what they are (and I have not shown you the other EU contries!), but some noise is inevitable and the NSS model and it seems very affected by outliers in the first few points.

I'd expect it to fit a much closer curve and to ignore the outliers in a much more robust way

@DiggMath2410
Copy link

Hey @pquan;

First of all, when computing your values on my computer, I found exactly the same as you,

(for those interested in doing the same you could add this line at the beginning of his code :
x = [(217, 3.7) ,(177, 3.67) ,(65, 3.61) ,(247, 3.6) ,(156, 3.52) ,(127, 3.5) ,(338, 3.5) ,(309, 3.43) ,(373, 3.4) ,(428, 3.38) ,(519, 3.28) ,(493, 3.27) ,(548, 3.21) ,(610, 3.17) ,(85, 3.09) ,(674, 3.09) ,(708, 3.04) ,(730, 3.01) ,(5330, 3.0) ,(5745, 3.0) ,(4834, 2.98) ,(4600, 2.92) ,(858, 2.91) ,(4234, 2.9) ,(912, 2.89) ,(3919, 2.82) ,(1094, 2.81) ,(1039, 2.79) ,(3596, 2.77) ,(3415, 2.75) ,(3415, 2.74) ,(1283, 2.73) ,(1223, 2.73) ,(1362, 2.72) ,(3231, 2.72) ,(3049, 2.69) ,(2592, 2.69) ,(2227, 2.69) ,(1465, 2.68) ,(2642, 2.67) ,(2865, 2.67) ,(1646, 2.67) ,(2500, 2.67) ,(2684, 2.66) ,(1496, 2.66) ,(1404, 2.66) ,(2500, 2.66), (1546, 2.66), (2865, 2.65) ,(1588, 2.65), (2135, 2.65) ,(1862, 2.64) ,(2277, 2.63) ,(2319, 2.63) ,(1728, 2.62) ,(1954, 2.61) ,(1770, 2.61) ,(1465, 2.6)]

I have some questions :

I implemented manually Nelson-Siegel and NSS on another computer, as soon as I have access to it, I will check if it's fit better or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants