Converting Nelson–Siegel–Svensson Yield Rates into Discount Factors
Summary
The document investigates whether discount factors calculated from a Nelson–Siegel–Svensson yield curve are implausibly small. It applies the model to maturities from six to thirty months, converts the fitted zero-coupon rates into discount factors, and uses those factors to price a bond with coupon and face-value cash flows. The resulting factors and price appear unexpectedly low to the questioner and could affect nonlinear parameter optimization.
The answer identifies a units issue: the modeled zero-coupon rates are expressed in percent, so they must be divided by one hundred before using them in the exponential discounting formula. This is a focused implementation correction, not evidence that the fitted curve parameters themselves are appropriate. The exchange does not assess the source or calibration quality of the parameters, compounding conventions, or whether the corrected prices fit market data.
Key ideas
- Nelson–Siegel–Svensson parameters produce zero-coupon rates that are used to calculate discount factors.
- The question applies exponential discounting to maturities expressed in years.
- The answer says the rates are in percent and must be converted to decimal units before discounting.
- The exchange does not validate the curve calibration or the chosen compounding convention.
Tags
Full text
# Correct Theoretical Discount Factors from Nelson-Siegel-Svensson?
# Correct Theoretical Discount Factors from Nelson-Siegel-Svensson?
I am calculating the theoretical discount factors associated with a bond that has 30 months to maturity from today with the parameters below obtained from here using the Nelson-Siegel-Svensson Model. The Python code is just a direct application of the Nelson-Siegel-Svensson Model formula. Are the theoretical Discount factors obtained from NSS meant to be this small?
```
beta_0 = 6.33120453
beta_1 =-6.22139731
beta_2 = -4.55116776
beta_3 = -8.72097716
tau_1 = 1.68437012
tau_2 = 11.18918219
months_to_maturity_array = numpy.array([6, 12, 18, 24, 30])
years_to_maturity_array = months_to_maturity_array/12
term_1 = (beta_0) + (beta_1*((1-numpy.exp(-years_to_maturity_array/tau_1))/(years_to_maturity_array/tau_1))) + (beta_2*((((1-numpy.exp(-years_to_maturity_array/tau_1))/(years_to_maturity_array/tau_1)))-(numpy.exp(-years_to_maturity_array/tau_1))) + (beta_3*((((1-numpy.exp(-years_to_maturity_array/tau_2))/(years_to_maturity_array/tau_2)))-(numpy.exp(-years_to_maturity_array/tau_2))))
test = numpy.exp(-years_to_maturity_array * (term_1))
print('RESULT:', test)
```
The output discount factors come out to be `[ 0.9032555 0.70209724 0.44987297 0.23612997 0.10293834]`, which seems very low. Such small discount factors will result in very small prices as expected, which effects the Non-Linear Optimization used to calculate the parameters. For example if the bond has the set of coupons and face values as shown below, then the `price` turns out to be `27.2861601745`.
```
coupons_and_facevals = [1.5, 1.5, 1.5, 102.5]
coupons_and_facevals = numpy.array(coupons_and_facevals)
price = 0
for i in range(0,4,1):
price = price + coupons_and_facevals[i] * test[i]
```
I've been dabbling with this for a while but am stuck.
Thank You
## Answer by Helin (score 1, accepted)
https://quant.stackexchange.com/a/19177
Your `term_1`, which represent the zero coupon rates, are expressed in %. You have to divide the values by 100 to compute discount factors.Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.