Why Bond Pricing Uses Discount and Forward Yield Curves
Summary
The document explains why fixed-rate and floating-rate bonds can require distinct curves in a pricing setup. A discount curve supplies the factors used to value a bond’s cash flows, while a forward curve estimates the reference rate that determines future floating coupons. The example describes bootstrapping a bond discount curve from short-maturity zero-coupon instruments and longer fixed-rate bonds, and a separate deposit-and-swap curve for a three-month LIBOR index.
It also notes that curves can reflect different risks: a discount curve may incorporate bond credit risk or represent a risk-free curve when credit is handled separately, while a forecast curve reflects the risk embedded in the floating reference rate. To obtain a zero-coupon yield at an intermediate maturity, the cited explanation points to a term-structure zero-rate query. The discussion is conceptual and tied to an older LIBOR-based example; curve construction and discounting conventions depend on the instrument, market, and framework.
Key ideas
- Discount curves provide discount factors for a bond’s expected cash flows.
- Floating-rate coupons require a forward curve for their reference index.
- Curves can be bootstrapped from different market instruments across maturities.
- A term structure can return a zero rate at an intermediate date, subject to its interpolation setup.
Tags
Full text
# Bootstrap yield curve with QLNet / Quantlib
# Bootstrap yield curve with QLNet / Quantlib
I am trying to grasp QLNet (C# version of Quantlib, all the functions of Quantlib have the same name and work the same way, so if you just know Quantlib, you can still help me), especially for pricing bonds. So I dug into the official examples, downloaded in the same time than the QLNet dll. The example called "Bonds" prices three bond types : zero coupon, fixed coupon rate, and floating coupon rate.
For the two last types, this example use two different yield curve : - The first one called discountingTermStructure for the fixed rate bond, made up of zero coupon bonds for the short end and of bonds (I'm not sure here what these simple bonds are) for the long end - The second one called forecastingTermStructure for the floating rate bond, made up of deposit for the short end and of swaps for the long end
My first question is why do they use different yield curve?
I am also trying to return a yield from a bootstrapped yield curve. For example, if I build the yield curve with 3 ZC bonds of 3 months, 6 months and 1 year maturities, I want to get the interpolated yield at 9 months. How could I do that?
Many thanks for your help
## Answer by SmallChess (score 5, accepted)
https://quant.stackexchange.com/a/17838
While @Baruch Youssin answers correctly in the general sense, the first part of his answer isn't what happened in the example code.
While QLNet is a port of QuantLib, it's not a direct port. Your quoted example doesn't show up in QLNet. The example in QuantLib was written in a very complicated way, in fact it's a simple example.
discountingTermStructure is simply a variable in the code. I can name it as something else. It links to bondDiscountingTermStructure, a yield-curve derived by today's market quotes. The yield-curve is derived by zero-coupon-rates and fixed-rate bonds.
```
// Adding the ZC bonds to the curve for the short end
bondInstruments.push_back(zc3m);
bondInstruments.push_back(zc6m);
bondInstruments.push_back(zc1y);
// Adding the Fixed rate bonds to the curve for the long end
for (Size i=0; i<numberOfBonds; i++) {
bondInstruments.push_back(bondsHelpers[i]);
}
boost::shared_ptr<YieldTermStructure> bondDiscountingTermStructure(
new PiecewiseYieldCurve<Discount,LogLinear>(
settlementDate, bondInstruments,
termStructureDayCounter,
tolerance));
```
This curve can be used for discounting in bond pricing.
```
boost::shared_ptr<PricingEngine> bondEngine(
new DiscountingBondEngine(discountingTermStructure));
```
DiscountingBondEngine would ask the underlying fixed-rate bond for the cash-flow amount. This amount would need to be discounted. The discount rate is supplied by the discountingTermStructure yield-curve.
Next, we'd want to price a floating-rate bond. It requires a forward curve. In particular, we need a forward curve of 3M USD LIBOR because the bond links to the 3M LIBOR index.
```
FloatingRateBond floatingRateBond(
settlementDays,
faceAmount,
floatingBondSchedule,
libor3m,
Actual360(),
ModifiedFollowing,
Natural(2),
// Gearings
std::vector<Real>(1, 1.0),
// Spreads
std::vector<Rate>(1, 0.001),
// Caps
std::vector<Rate>(),
// Floors
std::vector<Rate>(),
// Fixing in arrears
true,
Real(100.0),
Date(21, October, 2005));
```
This forward curve bootstrapped by:
```
// A depo-swap curve
std::vector<boost::shared_ptr<RateHelper> > depoSwapInstruments;
depoSwapInstruments.push_back(d1w);
depoSwapInstruments.push_back(d1m);
depoSwapInstruments.push_back(d3m);
depoSwapInstruments.push_back(d6m);
depoSwapInstruments.push_back(d9m);
depoSwapInstruments.push_back(d1y);
depoSwapInstruments.push_back(s2y);
depoSwapInstruments.push_back(s3y);
depoSwapInstruments.push_back(s5y);
depoSwapInstruments.push_back(s10y);
depoSwapInstruments.push_back(s15y);
boost::shared_ptr<YieldTermStructure> depoSwapTermStructure(
new PiecewiseYieldCurve<Discount,LogLinear>(
settlementDate, depoSwapInstruments,
termStructureDayCounter,
tolerance));
```
The relationship between zero rates and swap rates will tell us the forward rates.
## Answer by Baruch Youssin (score 2)
https://quant.stackexchange.com/a/17793
I do not yet know QuantLib but one question is general and easy to answer:
> My first question is why do they use different yield curve?
These two curves differ by risk levels inherent in them - the credit spreads over the risk-free yield curve (e.g., the OIS curve).
The discounting curve, discountingTermStructure, embeds the risk that this particular bond will not pay on time. Alternatively, it can be the risk-free curve if the default risk of the bond is taken care of otherwise and is not embedded in its price.
The forecast curve, forecastingTermStructure, embeds the risk of the underlying floating rate. Suppose the payments of your floating rate bond are linked to USD Libor; it is the rate at which large banks in London exchange USD deposits/loans. This rate includes the premium for the risk that borrowing bank will not pay on time.
I have also found the answer to the second question:
> I want to get the interpolated yield at 9 months. How could I do that?
According to Cogito Learning QuantLib: Yield Curves, the method YieldTermStructure::zeroRate returns the zero-coupon rate for any given moment.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.