# Wrong discount factors when finding Nelson Siegel Svensson model parameters

I am trying to determine the parameters for the Nelson Siegel Svensson model and am solving a Non- Linear Optimization problem to do this. Some of the code I have written is below and this is where my problem lies as I find that some of my discount factors are of the order 10^-30 and I don't know where I am going wrong. I am using the procedure presented in Pg. 5 of this paper. df is a dataframe which consists of observed bond data. All coupon payments will take place in 6 month intervals.

def calculatingprices(df, beta_0, beta_1, beta_2, beta_3, tau_1, tau_2):
#I am just creating a dict 'd' which will have the months to maturity for each bond as keys and
#a list as its values. The lists will contain the months to maturity - payments associated
#with the bond
months_to_maturity_matrix = df['months_to_maturity'].values
number_of_rows = df.shape
theoretical_price_for_bonds = np.zeros((number_of_rows, 1))
d = {}
for months_to_maturity_bond in months_to_maturity_matrix:
l = []
#Adding the difference in dates to the dict d. Differences, will just be multiples of 6 upto 360 (i.e. the 30 year bond)
for i in range(6, 360, 6):
if i <= months_to_maturity_bond:
l.append(months_to_maturity_bond - i)
else:
l.append(0)
d[months_to_maturity_bond] = l
d_ordered = collections.OrderedDict(sorted(d.items()))

#I then use the formula for the discount factor as follows
for x, value in np.ndenumerate(months_to_maturity_matrix):
diff_between_maturity_and_payments_array = np.array(d_ordered[value])
years_diff_between_maturity_and_payments_array = diff_between_maturity_and_payments_array/12
theoretical_discount_factor = np.exp(-years_diff_between_maturity_and_payments_array * (beta_0 + ((beta_1 + beta_2)*((1-np.exp(-years_diff_between_maturity_and_payments_array/tau_1))/years_diff_between_maturity_and_payments_array/tau_1))-(beta_2*np.exp(-years_diff_between_maturity_and_payments_array/tau_1)) + (beta_3*(((1-np.exp(-years_diff_between_maturity_and_payments_array/tau_2))/years_diff_between_maturity_and_payments_array/tau_2) -np.exp(-years_diff_between_maturity_and_payments_array/tau_2)))))


Edit: Please let me know if I need to provide more information. I realize in the paper I have cited they just consider the Nelson Siegel model, however in the code above I have accounted for the extra parameters associated with the Nelson Siegel Svensson model.

Thank You

if I read it correctly the paper you mention is about Nelson-Siegel and not Nelson-Siegel Svensson. The easier way to cross check it is to simply start by fixing theta and estimate the remaining parameters by OLS. If that works, then the optimization algorithm should work similarly. Below I attach a simple matlab code that does it and that you can adapt for your purposes:

    % Define yield structure used in the estimation
maturity = [ 1/12; 2/12; 3/12; 4/12; 5/12; 6/12; 9/12; 12/12; 18/12; 24/12;];

%************************    PARAMETERS     *****************************

yn = size(maturity,1);  % number of yields
lamda=0.3;         % as in Diebold, Rudebusch and Aruoba(2003)
Roll=1;              % Rolling estimation (1) or recursive estimation (0).
length = size(xdata,1); % data length

mat = 1:1:120;
pNS1 = ones(1,120);
pNS2 = zeros(1,120);
pNS3 = zeros(1,120);
for imat = 1:120;
pNS2(imat) = exp(-(imat/12)/lamda);
pNS3(imat) = ((imat/12)/lamda)*exp(-(imat/12)/lamda);
end;

CCw = [pNS1; pNS2; pNS3]'; %Coefficient matrix for all maturity 1:120
CC = CCw((maturity')*12,:);

% Extract (Estimate) Nelson-Siegel factors for yields by OLS.
yield= xdata(1:length,1:10);
NS = ((CC'*CC)\eye(size(CC,2)))*CC'*yield';

% Plot the NS factors and their empirical proxies
tm = dates;
tm = tm';
figure(2)
subplot(3,1,1)
ymin = min(NS(1,:))-0.05; ymax = max(NS(1,:))+0.05;
plot(tm,NS(1,:),'r-', tm, yield(:,10), 'b:');
h = legend('NS 1st factor','2year yield',1);
axis([tm(1),tm(length),ymin,ymax])
%xlabel('Time')
ylabel('%')
%title('');

subplot(3,1,2)
plot(tm,NS(2,:),'r-', tm, -(yield(:,10)-yield(:,1)), 'b:');
h = legend('NS 2nd factor',' -(2year - 1month)',1);
axis([tm(1),tm(length),min(NS(2,:))-0.05,max(NS(2,:))+0.05])
%xlabel('Time')
ylabel('%')
%title('');

subplot(3,1,3)
plot(tm,NS(3,:),'r-', tm, 2*yield(:,3)-(yield(:,1)+yield(:,10)), 'b:');
h = legend('NS 3rd factor','2*3month - (1month + 24month)',1);
axis([tm(1),tm(length),min(NS(2,:))-0.05,max(NS(2,:))+0.05])
xlabel('Time')
ylabel('%')

• Thank You. However, I would like to continue with solving the Non-Linear Optimization problem and hence just want to understand where I'm going wrong with my code. – Jojo Jul 22 '15 at 15:25