Swap Curve Calibration with Log-Linear Interpolation and Gauss-Newton
Summary
The document explains how interpolation can reduce the number of free discount factors when calibrating a swap curve. With two swap quotes but multiple payment-date discount factors, fitting every factor independently leaves the problem underdetermined. Fixing the curve start at one and using log-linear interpolation between selected curve nodes makes intermediate discount factors implied by a smaller set of unknown node values. The example uses two instruments to calibrate two such parameters with a Gauss-Newton solver.
It reports that the solver converges in three iterations to a very small fitting error, and gives example calibrated node and intermediate discount factors. It also distinguishes the Jacobian used to adjust curve parameters during calibration from sensitivities that map instrument quote changes into curve changes for risk analysis. The example demonstrates a workable setup, but it does not establish that the parameterization is uniquely appropriate for other instruments or curve conventions. Results depend on instrument specifications, interpolation choice, and the supplied market quotes.
Key ideas
- Two swap quotes cannot uniquely determine four independently variable discount factors.
- Log-linear interpolation makes intermediate discount factors functions of the selected curve nodes.
- A Gauss-Newton method can calibrate the reduced set of curve parameters to market swap quotes.
- Calibration gradients adjust discount factors, while quote-to-curve sensitivities support risk calculations.
Tags
Full text
# swap curve calibration with interpolation using newton-like method
# swap curve calibration with interpolation using newton-like method
suppose 2 swap market quotes for 1Y and 2Y and that swap payments occur semi-annually.
calibrating / obtaining the discount factors means finding 4 unknowns / discount factors that reproduce the market quotes such that
$$ \textrm{min } f = \sum_{i=1}^2 \epsilon_i \\ \textrm{ with } \epsilon_i = (mktQuote_i - modelQuote_i)^2 \\ \textrm{ and modelQuote}_i := floatLeg_i / fixLeg_i = \frac{\sum_{j=1}^N (\delta_j * fwrd_j * DF_j)}{\sum_{j=1}^N (\delta_j * DF_j)} $$ for j = 1, 2, ..., N payments on swap "i".
considering log-linear interpolation on the discount factors (DF) is to be used, is it possible to set up a nice Newton-like scheme, that is, $(DF_{k+1} = DF_k - J^{-1}(DF_k) * f(DF_k))$, with the Jacobian a square matrix, to solve this problem ?
References / articles / books that discuss this topic ?
## Answer by Attack68 (score 3, accepted)
https://quant.stackexchange.com/a/79465
You cannot solve for 4 degrees of freedom with two fixed parameters. That is an underspecified curve and it will (even though solvable, with infinite solutions) lead to chaotic behaviour within your solver.
In your case, however, you are adding hyper parameters, in the form of interpolation, so that 2 of the discount factors are implied, via interpolation from the other 3 (the first discount factor at the start of your curve is fixed at 1.0).
Yes, it is possible to setup a newton like solver. The one below solves for two parameters with two instruments.
```
# PYTHON
from rateslib import *
curve = Curve(
nodes={ # initialise 3 discount factors
dt(2024, 5, 22): 1.0,
dt(2025, 5, 22): 1.0,
dt(2026, 5, 27): 1.0,
},
calendar="nyc",
interpolation="log_linear"
)
solver = Solver(
curves=[curve],
instruments=[
IRS(dt(2024, 5, 24), "1y", frequency="S", spec="usd_irs", curves=curve),
IRS(dt(2024, 5, 24), "2y", frequency="S", spec="usd_irs", curves=curve),
],
s=[5.16, 4.76],
algorithm="gauss_newton"
)
SUCCESS: `func_tol` reached after 3 iterations (gauss_newton), `f_val`: 4.139106658800514e-14, `time`: 0.0023s
```
Relevant intermediate discount factors would then be known:
```
curve[dt(2024, 11, 24)] # 0.974328
curve[dt(2025, 11, 24)] # 0.927691
```
As well as those that have parametrised your curve:
```
curve.nodes
# {datetime.datetime(2024, 5, 22, 0, 0): 1.000000,
# datetime.datetime(2025, 5, 22, 0, 0): 0.950244,
# datetime.datetime(2026, 5, 27, 0, 0): 0.905908}
```
You can read more about this `Solver` at https://rateslib.readthedocs.io/en/latest/c_solver.html
The books I have personally written on this are "Coding Interest Rates: FX, Swaps and Bonds" which just documents algorithms used in rateslib, and "Pricing and Trading Interest Rate Derivatives: A Practical Guide to Swaps" which is broader and contains more generalist info related to swaps trading. (https://www.amazon.com/Pricing-Trading-Interest-Rate-Derivatives-dp-0995455546/dp/0995455546/ref=dp_ob_title_bk)
### Edit
Solver gradients are available. The API docs are at https://rateslib.readthedocs.io/en/latest/api/rateslib.solver.Gradients.html#rateslib.solver.Gradients although these don't make a huge amount of sense without the deriving documents.
The key gradients you are requesting are:
```
solver.grad_v_rT # alias of solver.J
# array([[-103.8040534 , -2.38011349],
# [ -1.45812049, -54.08994059]])
solver.grad_s_vT
# array([[-0.00963949, 0.00042417],
# [ 0.00025986, -0.01849916]])
```
The former is used in the calibration part where sensitivities to the rates determine by how much to adjust the discount factors.
The latter is used in risk sensitivities when you want to measure the economic sensitivity of a portfolio to the movement in the rates of instruments. The automatic differentiation returns sensitivities to discount factors and these have to be transformed to sensitivities to instruments rates. I.e
$$ \nabla_\mathbf{s} P = \nabla_\mathbf{s} \mathbf{v^T} \nabla_\mathbf{v} P $$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.