校准收益率曲线参数 Nelson Siegel Svensson

发布于 2025-01-20 20:42:52 字数 2820 浏览 6 评论 0原文

[编辑] 亲爱的团队

,我与 Nelson Siegel Svensson 收益率曲线合作,我需要通过最小二乘法校准参数 b0、b1、b2、b3 和 tau0、tau1,与实际 X、Y 数据和使用收益率曲线估计的 Y 相关,我有以下代码搜索校准,但我不确定这是实现目标的最佳策略:

from scipy.optimize import least_squares
import numpy as np
from math import exp as EXP, trunc
from nelson_siegel_svensson import NelsonSiegelSvenssonCurve
import pandas as pd
import matplotlib.pyplot as plt

def model(x, const):
    arr = np.array([])
    for val in const:
        arr = np.append(arr,(x[0])+(x[1]*((1-EXP(-val/x[4]))/(val/x[4])))+(x[2]*((((1-EXP(-val/x[4]))/(val/x[4])))-(EXP(-val/x[4]))))+x[3]*((((1-EXP(-val/x[5]))/(val/x[5])))-(EXP(-val/x[5]))))
    return arr
 
def fun(x, const, y_real):
    return y_real - model(x,const)
 
 
# days
const = np.array([30,90,270,548,913,1278,1643,2008,2373,2738,3103,3468,3833,4198,4563,4928,5293,5658,6023,6388,6935,7300,7665,8030])/365

# empty values represented with 0
y_real = np.array([3.33156,3.44928,3.62778,3.74313,3.96015,4.384,4.4705,4.55701,4.63817,4.69949,4.76081,4.82213,4.87285,4.8681,4.86336,4.85861,4.85387,4.84912,4.87039,4.89833,4.94286,4.98739,5.03192,5.07645])

# initial coefficients of Nelson Siegel Svensson
x0 = np.array([0.0001, 0.0001, 0.0001, 0.0001, 1.0, 1.0])

res = least_squares(fun, x0, bounds=(0,5000), args=(const, y_real), verbose=1)
 
print(res.x)

X_fix = np.linspace(start=const[0], stop=const[-1], num=(const.size*20))

NSS = NelsonSiegelSvenssonCurve(beta0=res.x[0], beta1=res.x[1], beta2=res.x[2], beta3=res.x[3], tau1=res.x[4], tau2=res.x[5])

pd_interpolation = pd.DataFrame(columns=['Period','Value'])

font = {'family': 'serif',
    'color':  '#1F618D',
    'weight': 'bold',
    'size': 14,
    }

font_x_y = {'family': 'serif',
    'color':  '#C70039',
    'weight': 'bold',
    'size': 13,
    'style': 'oblique' 
    }

fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(10, 6))

minx = -const[1]*3

config_manager = plt.get_current_fig_manager()
config_manager.set_window_title("Visualización " )

screen_x, screen_y = config_manager.window.wm_maxsize()

anchura = str(trunc(screen_x/12))
altura = str(trunc(screen_y/8))
middle_window = "+" + anchura + "+" + altura

config_manager.window.wm_geometry(middle_window)

plt.title('Interpolación ', fontdict=font, loc='center')
plt.xlabel('Periodo', fontdict=font_x_y)
plt.ylabel('Aproximación', fontdict=font_x_y, rotation=90, labelpad=10)

ax.set_ylim(ymin=0, ymax=(np.amax(y_real)*1.1))
ax.set_xlim(xmin=minx, xmax=(np.amax(const)*1.03))

ax.plot(const, y_real, 'ro', label='Dato real')
ax.plot(X_fix, NSS(X_fix),'--', label='Dato interpolado')
ax.legend(loc='lower right', frameon=False)

plt.show()

结果是:

在此处输入图像描述

您还有其他最佳选择吗?

提前致谢。

[Edited]
Dear Team

I work with Nelson Siegel Svensson Yield Curve and I need to calibrate parameters b0, b1, b2, b3 and tau0, tau1 by least squares, related to real X,Y data and Y estimated with Yield Curve, I have this code to search calibration, but I'm not sure its a best strategy to reach the goal:

from scipy.optimize import least_squares
import numpy as np
from math import exp as EXP, trunc
from nelson_siegel_svensson import NelsonSiegelSvenssonCurve
import pandas as pd
import matplotlib.pyplot as plt

def model(x, const):
    arr = np.array([])
    for val in const:
        arr = np.append(arr,(x[0])+(x[1]*((1-EXP(-val/x[4]))/(val/x[4])))+(x[2]*((((1-EXP(-val/x[4]))/(val/x[4])))-(EXP(-val/x[4]))))+x[3]*((((1-EXP(-val/x[5]))/(val/x[5])))-(EXP(-val/x[5]))))
    return arr
 
def fun(x, const, y_real):
    return y_real - model(x,const)
 
 
# days
const = np.array([30,90,270,548,913,1278,1643,2008,2373,2738,3103,3468,3833,4198,4563,4928,5293,5658,6023,6388,6935,7300,7665,8030])/365

# empty values represented with 0
y_real = np.array([3.33156,3.44928,3.62778,3.74313,3.96015,4.384,4.4705,4.55701,4.63817,4.69949,4.76081,4.82213,4.87285,4.8681,4.86336,4.85861,4.85387,4.84912,4.87039,4.89833,4.94286,4.98739,5.03192,5.07645])

# initial coefficients of Nelson Siegel Svensson
x0 = np.array([0.0001, 0.0001, 0.0001, 0.0001, 1.0, 1.0])

res = least_squares(fun, x0, bounds=(0,5000), args=(const, y_real), verbose=1)
 
print(res.x)

X_fix = np.linspace(start=const[0], stop=const[-1], num=(const.size*20))

NSS = NelsonSiegelSvenssonCurve(beta0=res.x[0], beta1=res.x[1], beta2=res.x[2], beta3=res.x[3], tau1=res.x[4], tau2=res.x[5])

pd_interpolation = pd.DataFrame(columns=['Period','Value'])

font = {'family': 'serif',
    'color':  '#1F618D',
    'weight': 'bold',
    'size': 14,
    }

font_x_y = {'family': 'serif',
    'color':  '#C70039',
    'weight': 'bold',
    'size': 13,
    'style': 'oblique' 
    }

fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(10, 6))

minx = -const[1]*3

config_manager = plt.get_current_fig_manager()
config_manager.set_window_title("Visualización " )

screen_x, screen_y = config_manager.window.wm_maxsize()

anchura = str(trunc(screen_x/12))
altura = str(trunc(screen_y/8))
middle_window = "+" + anchura + "+" + altura

config_manager.window.wm_geometry(middle_window)

plt.title('Interpolación ', fontdict=font, loc='center')
plt.xlabel('Periodo', fontdict=font_x_y)
plt.ylabel('Aproximación', fontdict=font_x_y, rotation=90, labelpad=10)

ax.set_ylim(ymin=0, ymax=(np.amax(y_real)*1.1))
ax.set_xlim(xmin=minx, xmax=(np.amax(const)*1.03))

ax.plot(const, y_real, 'ro', label='Dato real')
ax.plot(X_fix, NSS(X_fix),'--', label='Dato interpolado')
ax.legend(loc='lower right', frameon=False)

plt.show()

and the result is:

enter image description here

Can you have other best option to work this?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文