Bond Risk Measures and Immunization › Macaulay Duration
Quantitative FinanceAll chapters Bond Risk Measures and Immunization › Macaulay DurationOne section · Sections in this chapter3 / 13 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Macaulay duration is the weighted average time until a bond's cash flows are received. The weights are the present values of each cash flow as a proportion of the bond's total price.
Frederick Macaulay introduced duration in 1938 as a measure of the effective maturity of a bond. His insight was that a bond's stated maturity date tells only part of the story. A 10-year bond that pays substantial coupons behaves quite differently from a 10-year zero-coupon bond, even though both mature on the same date. Macaulay sought a single number that would capture the economic timing of all a bond's cash flows.
Rather than using only the final maturity date, duration accounts for all cash flows and their timing. The concept is analogous to finding the center of gravity of the cash flow stream. Just as a physical object balances at its center of mass, a bond's duration represents the "balance point" of its payments over time. For a bond paying cash flows at times :
where:
- : Macaulay duration in payment periods in this formula
- : the integer payment-period index; divide by the annual payment frequency to express duration in years
- : the cash flow at time
- : the yield to maturity per period (expressed as a decimal)
- : the bond price (sum of all present values)
- : the present value of cash flow , equal to
- : the total number of cash flow periods
Each term weights the time period by the present value of the cash flow received at that time. Dividing by the total price normalizes these weights to sum to one, so the result is a proper weighted average.
Macaulay duration summarizes the timing of present-value weights; it is not a payback date or a promise that accumulated coupons have recovered the purchase price. A zero-coupon bond has one receipt time, so its duration equals maturity. With positive earlier coupons, some present-value weight arrives sooner and the weighted mean is shorter than maturity.
For a zero-coupon bond, the calculation is trivial. The only cash flow is the face value at maturity, so Macaulay duration equals the time to maturity. With a positive coupon payment strictly before maturity, Macaulay duration is less than maturity because that earlier payment receives positive present-value weight. If all remaining cash flow arrives at maturity, duration equals maturity.
def macaulay_duration(
face_value, coupon_rate, years_to_maturity, yield_rate, frequency=2
):
"""Calculate Macaulay duration of a bond."""
periods, coupon_payment, periodic_yield = _bond_terms(
face_value, coupon_rate, years_to_maturity, yield_rate, frequency
)
# Calculate price
price = bond_price(
face_value, coupon_rate, years_to_maturity, yield_rate, frequency
)
# Calculate weighted average time
weighted_time = 0
for t in range(1, periods + 1):
if t < periods:
cf = coupon_payment
else:
cf = coupon_payment + face_value
pv_cf = cf / (1 + periodic_yield) ** t
time_in_years = t / frequency
weighted_time += time_in_years * pv_cf
return weighted_time / priceLet's calculate duration for several bonds to see how bond characteristics affect it:
# Compare durations for different bonds
bonds = [
{"name": "5-year, 5% coupon", "maturity": 5, "coupon": 0.05},
{"name": "10-year, 5% coupon", "maturity": 10, "coupon": 0.05},
{"name": "10-year, 2% coupon", "maturity": 10, "coupon": 0.02},
{"name": "10-year, 8% coupon", "maturity": 10, "coupon": 0.08},
{"name": "30-year, 5% coupon", "maturity": 30, "coupon": 0.05},
]
yield_rate = 0.05 # 5% yield
print("Bond Characteristics and Macaulay Duration")
print("=" * 55)
print(f"{'Bond':<25} {'Maturity':>10} {'Duration':>12}")
print("-" * 55)
for bond in bonds:
mac_dur = macaulay_duration(1000, bond["coupon"], bond["maturity"], yield_rate)
print(f"{bond['name']:<25} {bond['maturity']:>10} {mac_dur:>12.2f} years")Bond Characteristics and Macaulay Duration ======================================================= Bond Maturity Duration ------------------------------------------------------- 5-year, 5% coupon 5 4.49 years 10-year, 5% coupon 10 7.99 years 10-year, 2% coupon 10 8.95 years 10-year, 8% coupon 10 7.39 years 30-year, 5% coupon 30 15.84 years
The results confirm our intuition: longer maturity increases duration, and lower coupons increase duration because less of the bond's value comes from near-term cash flows. Notice that the 10-year, 2% coupon bond has a duration of nearly 9 years, while the 10-year, 8% coupon bond has a duration closer to 7 years. The higher coupon payments shift the center of gravity of the cash flows earlier in time.

