Choosing Bond Weights When Fitting Government Discount Curves
Summary
The document explains how bond weights shape a fitted government discount curve when the curve is calibrated by minimizing weighted price errors. Equal price weights give each bond the same influence. Weighting inversely by squared DV01 roughly shifts the objective toward yield errors, improving the fit at the front end while potentially sacrificing the long end. A blended weighting scheme lets the curve builder balance price and yield fit. Market-specific segmentation and adjustments for benchmark status or liquidity can further change individual bond influence.
A second answer notes that weights matter mainly when the fitting problem is overspecified, with more bond observations than curve degrees of freedom. In a fully specified fit, the solver can match prices exactly, making weights immaterial; an underspecified setup may be unstable, so additional constraints or pseudo-instruments can help. Interpolation choices and the placement of curve nodes also affect curve shape. The examples are practical guidance rather than a universal prescription: appropriate choices depend on market conventions, conditions, and how the curve will be used.
Key ideas
- Equal price weights treat each bond’s price error equally.
- Inverse squared DV01 weighting roughly emphasizes yield errors and can favor front-end fit over long-end fit.
- Blended weights can balance price and yield error objectives.
- Liquidity, benchmark status, and maturity segmentation can motivate bond-specific weight adjustments.
- Weights affect fitted results primarily in overspecified problems, while node placement and interpolation also shape the curve.
Tags
Full text
# Bond curve fitting, practical question
# Bond curve fitting, practical question
when fitting gov bond curves, What are different logic's used by traders to set the weight for the different bonds ?
## Answer by Helin (score 9, accepted)
https://quant.stackexchange.com/a/78702
Let's define the problem as follows: Given a set of $N$ bonds, we wish to create a discount curve, composed of $M$ degrees of freedom, so as to minimize the weighted price errors: $$ \min_{m_1...m_M} \sum_{i}^N w_i(P_i - \hat{P}_i(m_1..m_M))^2, $$ where $P_i$ is the quoted price of bond $i$, $\hat{P}_i$ is the theoretical price of bond $i$ using the fitted discount curve, and $w_i$ is the weight assigned to bond $i$, and $m_j$ is the value taken by one of the degrees of freedom. You are specifically asking about how to choose $w_i$.
There are many options, depending on preferences and markets:
- The easiest is $w_i = 1$ so all the prices are weighted equally. This is actually a good option if you don't care about the short end of the yield curve that much (e.g., you are a long bond trader).
- The most popular choice is $w_i = 1 / \text{DV01}_i^2$. This roughly translates the minimization problem into minimizing yield errors. This would generate much better fit at the front end of the curve, while sacrificing the long end.
- The next option is to use a blended approach, setting $w_i = \lambda + (1 - \lambda) / \text{DV01}_i^2$. By choosing $\lambda\in[0,1]$, you effectively can control the relative importance of price errors and yield errors.
- More exotic schemes based on market segmentation are used as well; e.g., I've seen folks use duration-weighting for <1-year issues, uniform low weights for 1-10 year issues, and uniform high weights for 10-30 year bonds.
- On top of the more systematic weighting schemes above, you can also multiply $w_i$ by an additional ad-hoc adjustment factor to scale it up and down for specific bonds: While traders in the US typically exclude on-the-run issues from curve fitting, JGB traders there fitted curves to closely mirror on-the-run issues. So in those cases, you simply multiply $w_i$ of benchmark bonds by a number greater than 1 (say 10). Some prefer to lower the weights of seasoned, less liquid bonds. You can define liquidity in many ways, but the easiest method is to simply treat bonds that have rolled out of their original maturity bucket as illiquid (e.g., a 30-year Treasury bond with less than 10-years to maturity), in which case you may assign a very low weight to these bonds. I've also seen people set different weight factors depending on the distance to the original maturity.
There's no rule that fits all scenarios. It depends on the market generally, the market conditions in real-time, and how you plan to use the curve.
## Answer by Attack68 (score 7)
https://quant.stackexchange.com/a/78758
@Helin provided a great answer for the specific question.
I would note that when curve building your framework always falls under one of three regimes:
When completely specified, weights are essentially (to machine tolerance) irrelevant because the minimum solver solution is attained at zero.
When underspecified, the solver is chaotic. It is practical to add information (usually pseudo-instruments) to convert to the completely specified case (or overspecified).
Only in the overspecified case do weights have an impact.
But there are other subjective choices besides weights that influence the shape of resultant curves. Below are three example factors. Suppose calculating a matrix of curves from the following set of combinations:
- Position of degrees of freedom: [(5y, 10y)] (1 combination)
- Interpolation [(log linear), (log cubic)] (2 combinations)
Here is a numerical example of the first of those combinations, in an overspecified regime with 3 bonds: apprx 3y, 6y and 10y:
```
# PYTHON
from rateslib import *
b1 = FixedRateBond(dt(1999, 2, 4), "3y", fixed_rate=2.0, spec="ust", curves="curve")
b2 = FixedRateBond(dt(1999, 5, 10), "6y", fixed_rate=2.0, spec="ust", curves="curve")
b3 = FixedRateBond(dt(1999, 7, 4), "10y", fixed_rate=2.0, spec="ust", curves="curve")
curve = Curve(
nodes={
dt(2000, 1, 1): 1.0, # 0y
dt(2005, 1, 1): 1.0, # 5y
dt(2010, 1, 1): 1.0, # 10y
},
id="curve",
)
solver = Solver(
curves=[curve],
instruments=[
(b1, (), {"metric": "clean_price"}),
(b2, (), {"metric": "clean_price"}),
(b3, (), {"metric": "clean_price"}),
],
s=[101.0243, 101.27159, 101.301937], # clean bond prices
weights=[1., 1., 1.]
)
SUCCESS: `conv_tol` reached after 5 iterations (levenberg_marquardt), `f_val`: 0.19429355288961916, `time`: 0.0296s
```
Constructing all these combinations and plotting `curve.plot("1b", comparators=[curve2, curve3, curve4])`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.