Friday, October 7, 2011

Create Nelson-Siegel function for yield curve

U.S. Treasury bonds with maturity ranging from 1 year to 30 years are daily updated on the Treasury’s website. However, some yields, such as from 4 years maturity bond, have to be inferred. The Nelson-Siegel function is probably one of the most important formulas to construct the yield curve. Many people use EXCEL’s Solver to find the nonlinear estimates of the four parameters (a1, a2, a3 and beta) for the Nelson-Siegel function. SAS’s PROC NLIN can also do this job smoothly. I copied today’s yield data and imported into SAS. Then I assigned some initial values to the unknown parameters and solved those parameters. With the PROC FCMP, I was able to build a function to predict the yields at any given year. Finally I plotted the yield curve (I also fitted the real yields with a quadratic regression line). The results showed that the nonlinear Nelson-Siegel function behaves better at longer maturities than OLS regression.


**********************(1) IMPORT STEP******************************************;
data _1;
input ytm : $4. @@;
cards;
1mo 3mo 6mo 1yr 2yr 3yr 5yr 7yr 10yr 20yr 30yr
;;;

data _2;
input yield : 3.2 @@;
cards;
0.01 0.01 0.03 0.09 0.29 0.46 1.01 1.52 2.01 2.71 2.96
;;;

data _3(keep=yield years);
set _1;
set _2;
if find(ytm, 'yr') gt 0;
years = input(compress(ytm, 'yr'),3.);
yield = yield / 100;
run;

**********************(2) SOLVE PARAMETERS************************************;
proc nlin data=_3 method=newton;
parms a1 = 0.05 a2 = 0.05
a3 = 0.05 beta = 1;
model yield=a1+(a2+a3)*(beta/years)*(1-exp(-years/beta))-a3*exp(-years/beta);
ods output parameterestimates = parmds;
run;

data _null_;
set parmds;
call symput(parameter, estimate);
run;

**********************(3) BUILD FUNCTION AND APPLY IT****************************;
proc fcmp outlib = work.func.finance;
function nelson_siegel(years);
return(
&a1 + (&a2+&a3)*(&beta/years)*(1-exp(-years/&beta))
- &a3*exp(-years/&beta)
);
endsub;
run;
options cmplib=work.func;
data _4;
do years = 1 to 30;
predyield = nelson_siegel(years);
output;
end;
run;

data _5;
merge _3(rename=(yield=realyield)) _4(in=a);
by years;
if a;
run;

ods html style = money;
proc sgplot data = _5;
scatter x = years y = predyield;
series x = years y = realyield ;
reg x = years y = realyield / degree = 2;
xaxis grid; yaxis grid label = ' ';
format realyield percent8.2;
run;
ods html style = htmlbluecml;
********************END OF ALL CODING*****************************************;

1 comment:

  1. Hello, Charlie. Thank you for your input. However, it would be great if you could tell me what changes to the code I would have to do if I want to find a yield curve for each day of the year? In this case, I will need a's and beta's to be estimated for each date. Thanks.

    ReplyDelete