I have been working on getting input parameters to the Non-Linear Optimization which gives the Nelson Siegel Svensson model parameters and am carrying out the OLS regression as described in this answer. However, the input parameters obtained from the OLS are too far off the actual parameters, which I checked against some parameters I actually do have. I am using the equations shown in 'Figure 5' on Page 12 of this paper, and obtain the yield data, by choosing Par Bonds and using their coupons as Par Yields to bootstrap from to get the Spot Rates, which appears to be an okay method based on Page 3 of this paper. The code that I use is below, where I've just implemented the formula in the previous link and have carried out the regression in Python. My query is if there is an issue with the way I set matrix_of_params
or if it could be to do with the data in df
itself.
I run the function above for different values of tau_1
and tau_2
. I then have a function to get the params
associated with the lowest residuals
, which I am positive is correct.
#df is a Dataframe containing all the data about the Bonds
def obtainingparams(self, df, tau_1, tau_2, residuals):
values = []
face_values = df['FACE_VALUE'].values #Writing face values to an array
yields = (df['coupon'].values) #COUPON = YTM for Par Bonds
spot_rate = np.zeros((yields.shape[0]))
#Calculating Spot Rates
for x, value in np.ndenumerate(yields):
index = x[0]
if index == 0:
spot_rate[index] = (yields[index]/face_values[index]) * 100
else:
adding_negatives = 0
if index < spot_rate.shape[0]:
for i in range (0, index, 1):
adding_negatives = adding_negatives + (value*face_values[index]/200)/np.power((1+(spot_rate[i]/200)),i+1)
term_1 = face_values[index] - adding_negatives
spot_rate[index] = (2 * ((np.power(((((face_values[index] + ((value*face_values[index]/200)))/term_1))),1/(index+1)))-1))*100
matrix_of_params = np.empty(shape=[1, 4])
months_to_maturity_matrix = df.months_to_maturity.values #Writing months to maturity to an array
#Populating the Matrix of Parameter Coefficients
count = 0
for x, value in np.ndenumerate(months_to_maturity_matrix):
if count < months_to_maturity_matrix.shape[0]:
months_to_maturity = months_to_maturity_matrix[count]
years_to_maturity = months_to_maturity/12.0
#Applying the equation in the link
newrow = [1, ((1-np.exp(-years_to_maturity/tau_1))/(years_to_maturity/tau_1)), ((1-np.exp(-years_to_maturity/tau_1))/(years_to_maturity/tau_1))-(np.exp(-years_to_maturity/tau_1)), ((((1-np.exp(-years_to_maturity/tau_2))/(years_to_maturity/tau_2))))-(np.exp(-years_to_maturity/tau_2))]
count = count + 1
#Just adding the new row to the matrix of parameter coefficients
matrix_of_param_coefficients = np.vstack([matrix_of_params, newrow])
#Carrying out OLS Regression
params = np.linalg.lstsq(matrix_of_params,spot_rate)[0]
residuals = np.sqrt(((spot_rate - matrix_of_params.dot(params))**2).sum())
#To keep track of which params are associated with which residuals
values.append((tau_1, tau_2, residuals, params))
return values
Thank You
newrow
in the code above by 100? Thank You. $\endgroup$