Nelson-Siegel-Svensson Yield Curve Fitting

The Nelson-Siegel-Svensson (NSS) model represents the zero-rate curve as a small set of economically interpretable level, slope, and hump factors. It is a smoothing model, not an arbitrage-free curve construction method: use bootstrapped discount factors for pricing, and use NSS where a stable low-dimensional representation is useful for reporting, scenarios, and relative value.

The functional form

For maturity τ, a continuously compounded NSS zero rate is:

y(τ) = β0 + β1 L1(τ, λ1) + β2 L2(τ, λ1) + β3 L2(τ, λ2)
L1 = (1 - exp(-λτ)) / (λτ)
L2 = L1 - exp(-λτ)

β0 is the long-run level because all loading terms decay to zero. β1 controls the short-end slope, while β2 and β3 create medium- and long-dated humps. The locations of those humps are governed by λ1 and λ2; their effects are nonlinear and are the source of most fitting fragility.

ParameterLimiting or primary effectPractical interpretation
β0y(∞)long-end level
β1short rate relative to β0slope
β2hump near 1.8 / λ1medium curvature
β3second hump near 1.8 / λ2long curvature
λ1, λ2loading decayhump locations

Fit rates with one compounding convention and maturities expressed in year fractions. Feeding a mix of par yields, bond yields, and zero rates into the same regression gives parameters a misleading appearance of precision. Start with an arbitrage-consistent curve from yield-curve bootstrapping, then sample its zero rates at a deliberate maturity grid.

Conditional linear estimation

Conditional on λ1 and λ2, the betas are ordinary weighted least squares. This separates a difficult six-dimensional optimization into a two-dimensional nonlinear search plus a stable linear solve.

import numpy as np

def nss_loadings(tau, lam1, lam2):
    def l1(lam):
        x = lam * np.asarray(tau)
        return -np.expm1(-x) / x
    a = l1(lam1)
    return np.column_stack([np.ones_like(a), a, a - np.exp(-lam1*tau),
                            l1(lam2) - np.exp(-lam2*tau)])

def fit_betas(tau, zeros, weights, lam1, lam2):
    X = nss_loadings(np.asarray(tau), lam1, lam2)
    W = np.sqrt(np.asarray(weights))[:, None]
    return np.linalg.lstsq(W * X, W[:, 0] * zeros, rcond=None)[0]

Search on transformed positive parameters, for example log(λ1) and log(λ2), and impose an ordering such as λ1 > λ2 to avoid label-switching. Multi-start optimization matters: very different lambdas can generate nearly identical in-sample curves but unstable extrapolation. Weighting should reflect the use case. Equal weights overemphasize a dense short-end grid; inverse bid-offer or DV01 weights better connect residuals to economically meaningful error.

Residuals are risk signals

The root-mean-square residual is insufficient. Inspect residuals in basis points by maturity, changes in fitted parameters through time, and forward-rate behavior outside the observed nodes. A smooth zero curve can imply oscillating instantaneous forwards, especially when the two hump loadings nearly coincide.

DiagnosticFailure signatureResponse
parameter time serieslambda jumps with little curve moveconstrain or regularize
residual by tenorpersistent local clusteradd a knot or revise weights
implied forwardsnegative/oscillating tailsshorten extrapolation or constrain
holdout repricingerrors at liquid benchmarksfit discount factors more carefully

An NSS fit should not replace the production discount curve. Discounting a swap with a curve that does not reprice its input instruments introduces P&L unrelated to the market. A robust workflow stores both: the bootstrapped curve for valuation and the NSS factors for state compression.

Relative value and scenarios

NSS makes a cross-sectional residual observable: compare a bond's market-implied zero or spread-adjusted yield with the fitted curve at its duration-equivalent maturity. That residual is only a candidate signal. It can reflect liquidity, tax treatment, repo specialness, credit, or a cash-flow approximation rather than a mispricing.

For risk, shock betas and lambdas separately. A β0 shock is approximately parallel only at long maturities; β1 is concentrated at the front end. Lambda shocks move the locations of curvature and are nonlinear, so calculate full repriced P&L rather than attaching a fixed “curvature DV01.” Combine factor shocks with the key-rate perspective in duration and convexity.

Key takeaways

  • NSS is a compact descriptive factor model, not a substitute for an instrument-repricing curve.
  • Conditional least squares makes calibration more stable than unconstrained six-parameter fitting.
  • Parameter bounds, ordering, and economically motivated weights prevent spurious humps.
  • Validate residual patterns, forward curves, and out-of-sample behavior—not RMSE alone.
  • Treat fitted residuals as hypotheses after controlling for liquidity and instrument-specific effects.
#yield curve #Nelson-Siegel-Svensson #fixed income #calibration