Skip to content
All library documents

Separating Forecast and Discount Curves in QuantLib Swap Valuation

Article Quant Q&A · Author: robin

Summary

The post asks whether a QuantLib vanilla swap needs an explicit curve-linking step when a discount curve handle has already been created. Its code builds a zero curve, applies a spread, uses a discounting swap engine, and constructs a swap, but does not show how the floating-rate index is initialized. That omission prevents a complete check of the forecast setup.

The accepted answer distinguishes the two curves used in swap pricing: the index uses a forecast curve to project floating coupons, while the pricing engine uses a discount curve to value the resulting cash flows. The index’s constructor should receive the appropriate curve handle; the engine receives the discount curve. The answer explains that `linkTo` is useful for replacing a handle’s curve, such as during sensitivity analysis, and is unnecessary when the handle already points to the intended curve and will not change. The guidance is conceptual and conditional on the missing index initialization details.

Key ideas

  • A swap can use separate curves to forecast floating coupons and discount cash flows.
  • The floating-rate index must be initialized with the intended forecast curve handle.
  • The discounting swap engine receives the discount curve.
  • A handle can be relinked when switching curves, for example for sensitivity analysis.
  • No extra linking step is needed if the handle already points to the desired curve and will remain unchanged.

Tags

Full text
# Quantlib: Is linking the curve to the discount curve important in vanilla swaps?


# Quantlib: Is linking the curve to the discount curve important in vanilla swaps?












Below are steps I followed to value a few swaps. Just want to know if I have included the key steps in the below definitions. In some examples I found that we are also adding indexcurve.linkTo(). I believe linking is not required as my yield term structure is already linked to yts_discount. Please suggest.

```
#rates as below
rates = Maturity_Date   Zero_Rate
       8/25/2022    0.000556
       8/31/2022    0.000580
       9/7/2022     0.000569
       9/14/2022    0.000573
       9/23/2022    0.000577

def CurveBuilding(key_value):
   dc = ql.ActualActual()
   crv = ql.ZeroCurve(
   dates, rates, dc, ql.NullCalendar(), ql.Linear(), ql.Compounded, ql.Annual)
   crv.enableExtrapolation()
   shifted = ql.ZeroSpreadedTermStructure(ql.YieldTermStructureHandle(crv),ql.QuoteHandle(shift))
   return ql.YieldTermStructureHandle(shifted)

def ConstructSwap():
    yts = curves.get(floatindex)
    yts_discount = curves.get(disc_curve)
    fixingCalendar = index.fixingCalendar()
    fixedSchedule = ql.MakeSchedule(effectiveDate, terminationDate, fixed_leg_tenor)
    floatSchedule = ql.MakeSchedule(effectiveDate, terminationDate, float_leg_tenor,
                                             convention=ql.ModifiedFollowing, endOfMonth=True
                                              ,calendar=fixingCalendar)
 
    swap = ql.VanillaSwap(
    ql.VanillaSwap.Receiver, notional,
    fixedSchedule, fixedRate, fixed_leg_daycount,floatSchedule, index, spread, float_leg_daycount)

    engine = ql.DiscountingSwapEngine(yts_discount)
    swap.setPricingEngine(engine)
    return swap, original_tenor

#dataframe of few swaps
for idx, row in df.iterrows():
    swap, original_tenor = ConstructSwap()
    npv = swap.NPV()
```

## Answer by Luigi Ballabio (score 1, accepted)

https://quant.stackexchange.com/a/76537

There are two different curves involved in swap pricing: the forecast curve that the index will use to forecast future coupons and the discount curve that will be used to discount the coupon amounts. In QuantLib, the discount curve is passed to the engine; that's `yts_discount` in your code. The forecast curve is passed to the index. Your code doesn't show how `index` is initialized, so I can't comment on that, but the curve handle should have been passed to its constructor.

If you're asking specifically about the `linkTo` method, that's used in case you want to switch to a different curve, for instance because you want to do a sensitivity calculation. If your handle was already created with a curve (like you do in `CurveBuilding` here) and you don't want to change it, `linkTo` is not needed.

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.