Class Svensson

java.lang.Object
com.quantfinlib.rates.Svensson

public final class Svensson extends Object
Svensson (Nelson-Siegel-Svensson) yield-curve fit — NelsonSiegel with a second curvature hump, the form most central banks actually publish (the ECB's daily curve is exactly this):
  z(t) = b0 + b1 * f1(t/l1) + b2 * f2(t/l1) + b3 * f2(t/l2)
  f1(x) = (1 - e^-x)/x        f2(x) = (1 - e^-x)/x - e^-x
  • b0 — the level: z(infinity);
  • b1 — the slope: z(0) = b0 + b1 (b1 > 0 is inversion);
  • b2, lambda1 — the first hump and where it sits;
  • b3, lambda2: the second hump, the long-end flex a single hump cannot bend into. Real curves routinely show a short-end bump (policy expectations) and a 10y+ dip (convexity demand), and plain Nelson-Siegel must split the difference.

Fitting mirrors NelsonSiegel exactly: for fixed (l1, l2) the model is linear in (b0, b1, b2, b3), an exact 4-regressor OLS solve, so the fit is a 2-D log-spaced grid over the lambdas with an OLS solve per node, deterministic and free of local-minimum roulette. Nodes with lambda2 <= lambda1 are skipped: the two f2 regressors collide as the lambdas meet (exact collinearity at equality), and the ordering makes the parameterization identifiable (hump one is always the shorter-dated one). Betas are not sign-constrained: an inverted or double-dipped curve is data, not an error.

With b3 = 0 the model is Nelson-Siegel, so with the lambdas free Svensson can always match NS in-sample; the two fitters search different lambda grids (NS: 80 nodes 1-D; here: 50 nodes 2-D with lambda1 < 10), so on data whose best single lambda falls between this grid's nodes NS can win by a grid-granularity sliver (rmse differences at the 1e-8 level, tested to agree within tolerance). The price of the extra hump is two more parameters — on sparse or single-hump curves prefer NS and let InformationCriteria referee. Research lane.

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static final record 
    Fitted parameters plus the fit's root-mean-square error.
  • Method Summary

    Modifier and Type
    Method
    Description
    fit(double[] tenorYears, double[] zeroRates)
    Fits by 2-D log-spaced lambda grid (0.1y-10y, 50 nodes per axis, lambda2 > lambda1 only) + exact 4-regressor OLS per node.

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • fit

      public static Svensson.Fit fit(double[] tenorYears, double[] zeroRates)
      Fits by 2-D log-spaced lambda grid (0.1y-10y, 50 nodes per axis, lambda2 > lambda1 only) + exact 4-regressor OLS per node.
      Parameters:
      tenorYears - observation tenors, ≥ 6 distinct, all > 0
      zeroRates - observed zero rates (continuously compounded)