Yield Term Structures
- class YieldTermStructure
Abstract base class for interest-rate term structures.
This class defines the interface for all concrete interest rate term structures in QuantLib. It is not meant to be instantiated directly, but provides the common API for all yield curve objects such as FlatForward, ZeroCurve, ForwardCurve, etc.
Child classes inherit the following important methods:
Discount Factors
- discount(date: ql.Date, extrapolate=False)
- discount(time: float, extrapolate=False)
Returns the discount factor from the given date or time to the reference date.
- Parameters:
date (ql.Date) – The date for which the discount factor is requested.
time (float) – The time (in years) from the reference date.
extrapolate (bool) – Whether to allow extrapolation beyond the curve’s range.
- Returns:
The discount factor.
- Return type:
float
Zero-Yield Rates
- zeroRate(date: ql.Date, dayCounter: ql.DayCounter, compounding: ql.Compounding, frequency=Annual, extrapolate=False)
- zeroRate(time: float, compounding: ql.Compounding, frequency=Annual, extrapolate=False)
Returns the implied zero-coupon yield for the given date or time.
- Parameters:
date (ql.Date) – The date for which the zero rate is requested.
time (float) – The time (in years) from the reference date.
dayCounter (ql.DayCounter) – The day count convention for the result.
compounding (ql.Compounding) – The compounding convention (e.g., Continuous, Compounded).
frequency (ql.Frequency) – The compounding frequency (default: Annual).
extrapolate (bool) – Whether to allow extrapolation beyond the curve’s range.
- Returns:
The zero rate as a ql.InterestRate object.
- Return type:
ql.InterestRate
Forward Rates
- forwardRate(date1: ql.Date, date2: ql.Date, dayCounter: ql.DayCounter, compounding: ql.Compounding, frequency=Annual, extrapolate=False)
- forwardRate(date: ql.Date, period: ql.Period, dayCounter: ql.DayCounter, compounding: ql.Compounding, frequency=Annual, extrapolate=False)
- forwardRate(time1: float, time2: float, compounding: ql.Compounding, frequency=Annual, extrapolate=False)
Returns the forward rate between two dates or times.
- Parameters:
date1 (ql.Date) – The start date.
date2 (ql.Date) – The end date.
period (ql.Period) – The period from the start date.
time1 (float) – The start time (in years).
time2 (float) – The end time (in years).
dayCounter (ql.DayCounter) – The day count convention for the result.
compounding (ql.Compounding) – The compounding convention.
frequency (ql.Frequency) – The compounding frequency (default: Annual).
extrapolate (bool) – Whether to allow extrapolation beyond the curve’s range.
- Returns:
The forward rate as a ql.InterestRate object.
- Return type:
ql.InterestRate
Jump Inspectors
- jumpDates()
Returns the list of dates at which jumps (discontinuities) in the curve occur.
- Returns:
List of jump dates.
- Return type:
list of ql.Date
- jumpTimes()
Returns the list of times (in years) at which jumps in the curve occur.
- Returns:
List of jump times.
- Return type:
list of float
Notes
All concrete term structure classes (such as FlatForward, ZeroCurve, etc.) inherit these methods.
The discount, zeroRate, and forwardRate methods are the primary interface for querying the curve.
The extrapolate argument controls whether the curve can be queried outside its original range.
FlatForward
Flat interest-rate curve.
- ql.FlatForward(date, quote, dayCounter, compounding, frequency)
- ql.FlatForward(integer, Calendar, quote, dayCounter, compounding, frequency)
- ql.FlatForward(integer, rate, dayCounter)
Examples:
ql.FlatForward(ql.Date(15,6,2020), ql.QuoteHandle(ql.SimpleQuote(0.05)), ql.Actual360(), ql.Compounded, ql.Annual)
ql.FlatForward(ql.Date(15,6,2020), ql.QuoteHandle(ql.SimpleQuote(0.05)), ql.Actual360(), ql.Compounded)
ql.FlatForward(ql.Date(15,6,2020), ql.QuoteHandle(ql.SimpleQuote(0.05)), ql.Actual360())
ql.FlatForward(2, ql.TARGET(), ql.QuoteHandle(ql.SimpleQuote(0.05)), ql.Actual360())
ql.FlatForward(2, ql.TARGET(), 0.05, ql.Actual360())
DiscountCurve
Term structure based on log-linear interpolation of discount factors.
- ql.DiscountCurve(dates, dfs, dayCounter, cal=ql.NullCalendar())
Example:
dates = [ql.Date(7,5,2019), ql.Date(7,5,2020), ql.Date(7,5,2021)]
dfs = [1, 0.99, 0.98]
dayCounter = ql.Actual360()
curve = ql.DiscountCurve(dates, dfs, dayCounter)
ZeroCurve
ZeroCurve
LogLinearZeroCurve
CubicZeroCurve
NaturalCubicZeroCurve
LogCubicZeroCurve
MonotonicCubicZeroCurve
- ql.ZeroCurve(dates, yields, dayCounter, cal, i, comp, freq)
Dates |
The date sequence, the maturity date corresponding to the zero interest rate. Note: The first date must be the base date of the curve, such as a date with a yield of 0.0. |
yields |
a sequence of floating point numbers, zero coupon yield |
dayCounter |
DayCounter object, number of days calculation rule |
cal |
Calendar object, calendar |
i |
Linear object, linear interpolation method |
comp and freq |
are preset integers indicating the way and frequency of payment |
dates = [ql.Date(31,12,2019), ql.Date(31,12,2020), ql.Date(31,12,2021)]
zeros = [0.01, 0.02, 0.03]
ql.ZeroCurve(dates, zeros, ql.ActualActual(), ql.TARGET())
ql.LogLinearZeroCurve(dates, zeros, ql.ActualActual(), ql.TARGET())
ql.CubicZeroCurve(dates, zeros, ql.ActualActual(), ql.TARGET())
ql.NaturalCubicZeroCurve(dates, zeros, ql.ActualActual(), ql.TARGET())
ql.LogCubicZeroCurve(dates, zeros, ql.ActualActual(), ql.TARGET())
ql.MonotonicCubicZeroCurve(dates, zeros, ql.ActualActual(), ql.TARGET())
ForwardCurve
Term structure based on flat interpolation of forward rates.
- ql.ForwardCurve(dates, rates, dayCounter)
- ql.ForwardCurve(dates, rates, dayCounter, calendar, BackwardFlat)
- ql.ForwardCurve(dates, date, rates, rate, dayCounter, calendar)
- ql.ForwardCurve(dates, date, rates, rate, dayCounter)
dates = [ql.Date(15,6,2020), ql.Date(15,6,2022), ql.Date(15,6,2023)]
rates = [0.02, 0.03, 0.04]
ql.ForwardCurve(dates, rates, ql.Actual360(), ql.TARGET())
ql.ForwardCurve(dates, rates, ql.Actual360())
Piecewise
Piecewise yield term structure. This term structure is bootstrapped on a number of interest rate instruments which are passed as a vector of RateHelper instances. Their maturities mark the boundaries of the interpolated segments.
Each segment is determined sequentially starting from the earliest period to the latest and is chosen so that the instrument whose maturity marks the end of such segment is correctly repriced on the curve.
PiecewiseLogLinearDiscount
PiecewiseLogCubicDiscount
PiecewiseLinearZero
PiecewiseCubicZero
PiecewiseLinearForward
PiecewiseSplineCubicDiscount
- ql.Piecewise(referenceDate, helpers, dayCounter)
helpers = []
helpers.append( ql.DepositRateHelper(0.05, ql.Euribor6M()) )
helpers.append(
ql.SwapRateHelper(0.06, ql.EuriborSwapIsdaFixA(ql.Period('1y')))
)
curve = ql.PiecewiseLogLinearDiscount(ql.Date(15,6,2020), helpers, ql.Actual360())
- ql.PiecewiseYieldCurve(referenceDate, instruments, dayCounter, jumps, jumpDate, i=Interpolator(), bootstrap=bootstrap_type())
referenceDate = ql.Date(15,6,2020)
ql.PiecewiseLogLinearDiscount(referenceDate, helpers, ql.ActualActual())
jumps = [ql.QuoteHandle(ql.SimpleQuote(0.01))]
ql.PiecewiseLogLinearDiscount(referenceDate, helpers, ql.ActualActual(), jumps)
jumpDates = [ql.Date(15,9,2020)]
ql.PiecewiseLogLinearDiscount(referenceDate, helpers, ql.ActualActual(), jumps, jumpDates)
import pandas as pd
pgbs = pd.DataFrame(
{'maturity': ['15-06-2020', '15-04-2021', '17-10-2022', '25-10-2023',
'15-02-2024', '15-10-2025', '21-07-2026', '14-04-2027',
'17-10-2028', '15-06-2029', '15-02-2030', '18-04-2034',
'15-04-2037', '15-02-2045'],
'coupon': [4.8, 3.85, 2.2, 4.95, 5.65, 2.875, 2.875, 4.125,
2.125, 1.95, 3.875, 2.25, 4.1, 4.1],
'px': [102.532, 105.839, 107.247, 119.824, 124.005, 116.215, 117.708,
128.027, 115.301, 114.261, 133.621, 119.879, 149.427, 159.177]})
calendar = ql.TARGET()
today = calendar.adjust(ql.Date(19, 12, 2019))
ql.Settings.instance().evaluationDate = today
bondSettlementDays = 2
bondSettlementDate = calendar.advance(
today,
ql.Period(bondSettlementDays, ql.Days))
frequency = ql.Annual
dc = ql.ActualActual(ql.ActualActual.ISMA)
accrualConvention = ql.ModifiedFollowing
convention = ql.ModifiedFollowing
redemption = 100.0
instruments = []
for idx, row in pgbs.iterrows():
maturity = ql.Date(row.maturity, '%d-%m-%Y')
schedule = ql.Schedule(
bondSettlementDate,
maturity,
ql.Period(frequency),
calendar,
accrualConvention,
accrualConvention,
ql.DateGeneration.Backward,
False)
helper = ql.FixedRateBondHelper(
ql.QuoteHandle(ql.SimpleQuote(row.px)),
bondSettlementDays,
100.0,
schedule,
[row.coupon / 100],
dc,
convention,
redemption)
instruments.append(helper)
params = [bondSettlementDate, instruments, dc]
piecewiseMethods = {
'logLinearDiscount': ql.PiecewiseLogLinearDiscount(*params),
'logCubicDiscount': ql.PiecewiseLogCubicDiscount(*params),
'linearZero': ql.PiecewiseLinearZero(*params),
'cubicZero': ql.PiecewiseCubicZero(*params),
'linearForward': ql.PiecewiseLinearForward(*params),
'splineCubicDiscount': ql.PiecewiseSplineCubicDiscount(*params),
}
ImpliedTermStructure
Implied term structure at a given date in the future
- ql.ImpliedTermStructure(YieldTermStructure, date)
crv = ql.FlatForward(ql.Date(10,1,2020),0.04875825,ql.Actual365Fixed())
yts = ql.YieldTermStructureHandle(crv)
ql.ImpliedTermStructure(yts, ql.Date(20,9,2020))
ForwardSpreadedTermStructure
Term structure with added spread on the instantaneous forward rate.
- ql.ForwardSpreadedTermStructure(YieldTermStructure, spread)
crv = ql.FlatForward(ql.Date(10,1,2020),0.04875825,ql.Actual365Fixed())
yts = ql.YieldTermStructureHandle(crv)
spread = ql.QuoteHandle(ql.SimpleQuote(0.005))
ql.ForwardSpreadedTermStructure(yts, spread)
ZeroSpreadedTermStructure
Term structure with an added spread on the zero yield rate
- ql.ZeroSpreadedTermStructure(YieldTermStructure, spread)
crv = ql.FlatForward(ql.Date(10,1,2020),0.04875825,ql.Actual365Fixed())
yts = ql.YieldTermStructureHandle(crv)
spread = ql.QuoteHandle(ql.SimpleQuote(0.005))
ql.ZeroSpreadedTermStructure(yts, spread)
PiecewiseZeroSpreadedTermStructure
Represents a yield term structure constructed by applying a piecewise-linear interpolation of zero-rate spreads to an existing base curve. The resulting zero rate at any date is the base curve’s zero rate plus the interpolated spread at that date.
This structure is useful when modeling a market-implied yield curve that deviates from a base curve by a known set of spreads at given dates.
Other interpolations:
SpreadedLinearZeroInterpolatedTermStructure (alias for PiecewiseZeroSpreadedTermStructure)
SpreadedCubicZeroInterpolatedTermStructure
SpreadedKrugerZeroInterpolatedTermStructure
SpreadedSplineCubicZeroInterpolatedTermStructure
SpreadedParabolicCubicZeroInterpolatedTermStructure
SpreadedMonotonicParabolicCubicZeroInterpolatedTermStructure
- ql.PiecewiseZeroSpreadedTermStructure(baseCurve: ql.YieldTermStructureHandle, spreads: List[ql.Handle], dates: List[ql.Date], compounding: ql.Compounding = ql.Continuous, freq: ql.Frequency = ql.NoFrequency, dc: ql.DayCounter)
- Parameters:
baseCurve (ql.YieldTermStructureHandle) – The base yield term structure to which zero-rate spreads are applied.
spreads (List[ql.Handle]) – A list of handles to quotes representing the zero-rate spreads.
dates (List[ql.Date]) – The dates corresponding to each spread value. Must be in strictly increasing order.
compounding (ql.Compounding, optional) – The compounding method used for zero rates. Defaults to ql.Continuous.
freq (ql.Frequency, optional) – The frequency of compounding. Only relevant if compounding is not continuous. Defaults to ql.NoFrequency.
dc (ql.DayCounter, optional) – The day count convention used for year fractions.
calendar = ql.TARGET()
today = ql.Date(9, 6, 2009)
ql.Settings.instance().evaluationDate = today
day_count = ql.Actual360()
compounding = ql.Continuous
# Build base term structure
settlement_days = 2
settlement_date = calendar.advance(today, ql.Period(settlement_days, ql.Days))
ts_days = [13, 41, 75, 165, 256, 345, 524, 703]
rates = [0.035, 0.033, 0.034, 0.034, 0.036, 0.037, 0.039, 0.040]
dates = [settlement_date] + [calendar.advance(today, n, ql.Days) for n in ts_days]
curve_rates = [0.035] + rates
term_structure = ql.ZeroCurve(dates, curve_rates, day_count)
# Spreads and spread dates
spread_1 = ql.makeQuoteHandle(0.02)
spread_2 = ql.makeQuoteHandle(0.03)
spreads = [spread_1, spread_2]
spread_dates = [
calendar.advance(today, 8, ql.Months),
calendar.advance(today, 15, ql.Months)
]
# PiecewiseZeroSpreadedTermStructure
spreaded_term_structure = ql.PiecewiseZeroSpreadedTermStructure(
ql.YieldTermStructureHandle(term_structure),
spreads, spread_dates
)
interpolation_date = calendar.advance(today, 6, ql.Months)
t = day_count.yearFraction(today, interpolation_date)
interpolated_zero_rate = spreaded_term_structure.zeroRate(t, compounding).rate()
PiecewiseLinearForwardSpreadedTermStructure
Represents a yield term structure constructed by applying a piecewise-linear interpolation of forward-rate spreads to an existing base curve. The resulting forward rate at any date is the base curve’s forward rate plus the interpolated spread at that date.
This structure is useful when modeling market-implied forward curves that deviate from a base term structure by a known set of spreads at given dates.
Other interpolations:
PiecewiseForwardSpreadedTermStructure (Backward-flat interpolated)
- ql.PiecewiseLinearForwardSpreadedTermStructure(baseCurve: ql.YieldTermStructureHandle, spreads: List[ql.Handle], dates: List[ql.Date], dc: ql.DayCounter)
- Parameters:
baseCurve (ql.YieldTermStructureHandle) – The base yield term structure to which forward-rate spreads are applied.
spreads (List[ql.Handle]) – A list of handles to quotes representing the forward-rate spreads.
dates (List[ql.Date]) – The dates corresponding to each spread value. Must be in strictly increasing order.
dc (ql.DayCounter, optional) – The day count convention used for computing year fractions.
Unlike the zero-spreaded structure, this one applies spreads to instantaneous forward rates, not zero yields. Therefore, the impact on discount factors and derived instruments may differ.
today = ql.Date(10, ql.January, 2024)
ql.Settings.instance().evaluationDate = today
# Define forward curve dates and rates (annualized, continuous compounding)
dates = [
today,
today + ql.Period(3, ql.Months),
today + ql.Period(6, ql.Months),
today + ql.Period(1, ql.Years),
today + ql.Period(2, ql.Years),
today + ql.Period(3, ql.Years),
today + ql.Period(5, ql.Years),
today + ql.Period(10, ql.Years)
]
forwards = [0.02, 0.021, 0.022, 0.023, 0.025, 0.025, 0.023, 0.022]
# Build the forward curve
calendar = ql.TARGET()
day_count = ql.Actual365Fixed()
forward_curve = ql.ForwardCurve(dates, forwards, day_count, calendar)
fwd_crv_handle = ql.YieldTermStructureHandle(forward_curve)
spreads = [ql.makeQuoteHandle(0.00), ql.makeQuoteHandle(0.005), ql.makeQuoteHandle(0.0025), ql.makeQuoteHandle(0.0)]
spread_dates = [ today,
calendar.advance(today, ql.Period(3, ql.Years)),
calendar.advance(today, ql.Period(5, ql.Years)),
calendar.advance(today, ql.Period(10, ql.Years))]
spreaded_fwd_crv = ql.PiecewiseLinearForwardSpreadedTermStructure(fwd_crv_handle, spreads, spread_dates, day_count)
FittedBondCurve
- ql.FittedBondDiscountCurve(bondSettlementDate, helpers, dc, method, accuracy=1.0e-10, maxEvaluations=10000, guess=Array(), simplexLambda=1.0)
Methods:
CubicBSplinesFitting
ExponentialSplinesFitting
NelsonSiegelFitting
SimplePolynomialFitting
SvenssonFitting
pgbs = pd.DataFrame(
{'maturity': ['15-06-2020', '15-04-2021', '17-10-2022', '25-10-2023',
'15-02-2024', '15-10-2025', '21-07-2026', '14-04-2027',
'17-10-2028', '15-06-2029', '15-02-2030', '18-04-2034',
'15-04-2037', '15-02-2045'],
'coupon': [4.8, 3.85, 2.2, 4.95, 5.65, 2.875, 2.875, 4.125,
2.125, 1.95, 3.875, 2.25, 4.1, 4.1],
'px': [102.532, 105.839, 107.247, 119.824, 124.005, 116.215, 117.708,
128.027, 115.301, 114.261, 133.621, 119.879, 149.427, 159.177]})
calendar = ql.TARGET()
today = calendar.adjust(ql.Date(19, 12, 2019))
ql.Settings.instance().evaluationDate = today
bondSettlementDays = 2
bondSettlementDate = calendar.advance(
today,
ql.Period(bondSettlementDays, ql.Days))
frequency = ql.Annual
dc = ql.ActualActual(ql.ActualActual.ISMA)
accrualConvention = ql.ModifiedFollowing
convention = ql.ModifiedFollowing
redemption = 100.0
instruments = []
for idx, row in pgbs.iterrows():
maturity = ql.Date(row.maturity, '%d-%m-%Y')
schedule = ql.Schedule(
bondSettlementDate,
maturity,
ql.Period(frequency),
calendar,
accrualConvention,
accrualConvention,
ql.DateGeneration.Backward,
False)
helper = ql.FixedRateBondHelper(
ql.QuoteHandle(ql.SimpleQuote(row.px)),
bondSettlementDays,
100.0,
schedule,
[row.coupon / 100],
dc,
convention,
redemption)
instruments.append(helper)
params = [bondSettlementDate, instruments, dc]
cubicNots = [-30.0, -20.0, 0.0, 5.0, 10.0, 15.0,20.0, 25.0, 30.0, 40.0, 50.0]
fittingMethods = {
'NelsonSiegelFitting': ql.NelsonSiegelFitting(),
'SvenssonFitting': ql.SvenssonFitting(),
'SimplePolynomialFitting': ql.SimplePolynomialFitting(2),
'ExponentialSplinesFitting': ql.ExponentialSplinesFitting(),
'CubicBSplinesFitting': ql.CubicBSplinesFitting(cubicNots),
}
fittedBondCurveMethods = {
label: ql.FittedBondDiscountCurve(*params, method)
for label, method in fittingMethods.items()
}
curve = fittedBondCurveMethods.get('NelsonSiegelFitting')