Calibrate to the Market

Bootstrap a Curve and Get Every Zero-Rate Risk for Free

TeaVM Java jointly bootstraps OIS discount and 3M forecast curves, reprices a swap and reports the quote sensitivities from the same bootstrap result.

Par quotes
YearOIS par (%)3M forecast par (%)
1y
2y
3y
4y
5y

Quotes are entered in percent. The annual quote pillars must cover the selected swap maturity.

Reprice a swapOptional
Java source
CurveBootstrapRiskStudio.java

This exact source runs in TeaVM. Form changes update its Java literals and reset manual edits.

import com.nablatensor.quant.CurveSet;
import com.nablatensor.quant.MultiCurveBootstrap;

public final class CurveBootstrapRiskStudio {
  public static void main(String[] args) {
    double[] ois = {
      0.03000000, 0.03150000, 0.03250000, 0.03320000, 0.03380000
    };
    double[] fwd3m = {
      0.03260000, 0.03420000, 0.03530000, 0.03610000, 0.03680000
    };
    MultiCurveBootstrap.Builder b = MultiCurveBootstrap.builder();
    for (int i = 0; i < ois.length; i++) {
      b.oisSwap(i + 1, ois[i]);
      b.forecastSwap("3M", i + 1, fwd3m[i]);
    }
    MultiCurveBootstrap.Result r = b.build()
        .solve();
    CurveSet cs = r.curves();
    for (int year = 1; year <= 5; year++) {
      double zo = cs.discount()
          .zeroRate(year), zf = cs.forecast("3M")
          .zeroRate(year);
      System.out.println("ROW|" + year + "|" + zo + "|" + zf + "|" + (1e4 * (zf - zo)));
    }
    double annuity = cs.annuity(4), par = cs.parSwapRate("3M", 4), pv = (0.03300000 - par) * annuity;
    System.out.println("RESULT|" + par + "|" + annuity + "|" + pv);
    String row = "z:3M:swap:4";
    for (String q : r.quoteLabels()) {
      double s = r.sensitivity(row, q);
      if (Math.abs(s) > 1e-9) System.out.println("JAC|" + q + "|" + s);
    }
  }
}
TeaVM compiles and runs the Java source above in this browser.
Implementation guide

From par quotes to a risk-bearing curve

Bootstrapping solves for curve points that make market instruments reprice to their observed quotes.

Core mechanism

Each pillar is solved sequentially or jointly from discounting equations. Differentiating that solve yields a Jacobian from quote changes to zero-rate or discount-factor moves.

Practical workflow

Apply instrument conventions accurately, clean and prioritise quotes, enforce interpolation choices, check repricing residuals, and report quote-to-curve sensitivities by tenor.

Key details

*Keywords: multi curve bootstrap java, ois discounting java, tenor basis java, curve bootstrap jacobian java, zero rate risk java, sofr curve java*

Feature F5. Post-LIBOR, discounting moved to an OIS curve and each floating tenor got its own forecast curve. This builds the stack and — because the whole bootstrap recursion is recorded against ADouble quotes and replayed through a MultiOutput — returns the exact d(zero rate) / d(quote) Jacobian from one adjoint sweep, the transformation a rates desk uses to turn instrument PV01s into zero-rate bucket risk.

Two stages: the OIS discount curve from OIS deposits and par swaps, then each forecast curve from instruments whose annuity and float legs discount on the OIS curve. A forecast zero rate therefore depends on the OIS quotes that move its discounting — those are the cross-block entries of the Jacobian; an OIS zero never depends on a forecast quote.

Stylised annual construction — fixed and float legs share an annual grid, so a swap of maturity N adds exactly one forecast pillar and every step is closed form. Sub-annual float frequency, curve interpolation inside the solve, and cross-currency basis are later refinements; the analytic block Jacobian is a possible optimisation over the recorded-and-replayed one used here.

Scope and review point

The sample simplifies multi-curve conventions and market-data treatment. A production curve build requires holiday calendars, day counts, instruments and fallbacks under governance.