Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 3

Bond Prices & Yields: An Inverse Relationship

Recommended resources

Welcome back. In our previous lesson, we built a modular Python function, price_bond, to calculate a bond's clean and dirty price from its characteristics and yield to maturity (YTM). This provided a practical tool for translating a given yield into a price.

Today, we will leverage that tool and delve into the fundamental dynamics of bond valuation. Our focus is on the critical relationship between a bond's price and its yield. By the end of this lesson, you will be able to explain not just that this relationship is inverse, but also why it is non-linear, a property known as convexity, using intuitive reasoning, mathematical formulation, and visual proof.

1. The Inverse Relationship: Price vs. Yield

The most fundamental principle of bond pricing is that as yields rise, prices fall, and vice versa. Let's start with the intuition behind this.

A bond's price is the present value of its future cash flows. The yield is the discount rate used to calculate this present value. From a purely mathematical standpoint, the bond pricing formula is:

Here, the price is a function of the yield . Since the yield appears in the denominator of every term, an increase in necessarily decreases the value of each discounted cash flow, and therefore decreases the total price . Conversely, a decrease in inflates the value of each term and the total price.

The following short video from MIT OpenCourseWare provides a concise explanation of this principle.

Lecture 1, Part III: Bond “Mathematics”

In this segment, the lecturer defines yield and clearly explains the inverse relationship between price and yield.

Watch the section from yield definition to the end. Pay close attention to the statement around the 13:35 mark, where the lecturer directly addresses why the relationship is inverse by pointing to the discount factor formula.

Python Demonstration

Let's observe this relationship using the price_bond function we developed in the previous lesson. We will calculate the clean price of our example bond across a range of yields and plot the results.

First, ensure you have the code from the last lesson available. Here is the setup for convenience:

from collections import namedtuple
import yearfrac as yf
import matplotlib.pyplot as plt
import numpy as np




# --- Code from Previous Lesson ---
Bond = namedtuple("Bond", ["coupon_rate", "face_value", "coupon_freq", "coupon_schedule", "prev_coupon_date"])

def get_cash_flows(bond: Bond) -> list[float]:
    coupon_payment = bond.coupon_rate * bond.face_value / bond.coupon_freq
    cash_flows = [coupon_payment] * len(bond.coupon_schedule)
    cash_flows[-1] += bond.face_value
    return cash_flows

def get_time_factors(settlement_date: tuple, coupon_schedule: list, coupon_freq: int) -> list[float]:
    time_factors = []
    for date in coupon_schedule:
        time_factors.append(yf.d30360e(*settlement_date, *date, matu=False) * coupon_freq)
    return time_factors

def get_discount_factors(settlement_date: tuple, coupon_schedule: list, bond_yield: float, coupon_freq: int) -> list[float]:
    time_factors = get_time_factors(settlement_date, coupon_schedule, coupon_freq)
    periodic_yield = bond_yield / coupon_freq
    discount_factors = [1 / (1 + periodic_yield) ** tf for tf in time_factors]
    return discount_factors

def calculate_dirty_price(bond: Bond, settlement_date: tuple, bond_yield: float) -> float:
    cash_flows = get_cash_flows(bond)
    discount_factors = get_discount_factors(settlement_date, bond.coupon_schedule, bond_yield, bond.coupon_freq)
    return sum(cf * df for cf, df in zip(cash_flows, discount_factors))

def calculate_accrued_interest(bond: Bond, settlement_date: tuple) -> float:
    coupon_payment = bond.coupon_rate * bond.face_value / bond.coupon_freq
    accrued_days = yf.d30360e(*bond.prev_coupon_date, *settlement_date, matu=True) * 360
    days_in_period = yf.d30360e(*bond.prev_coupon_date, *bond.coupon_schedule[0], matu=True) * 360
    if days_in_period == 0: return 0.0
    return coupon_payment * (accrued_days / days_in_period)

def price_bond(bond: Bond, settlement_date: tuple, bond_yield: float, price_type: str = 'clean') -> float:
    dirty_px = calculate_dirty_price(bond, settlement_date, bond_yield)
    if price_type.lower() == 'dirty':
        return dirty_px
    accrued = calculate_accrued_interest(bond, settlement_date)
    return dirty_px - accrued



# --- End of Previous Lesson Code ---




# Bond Definition
settlement_date = (2024, 7, 16)
coupon_dates = [(y, m, 1) for y in range(2025, 2031) for m in (3, 9)]
example_bond = Bond(
    coupon_rate=0.05, face_value=1000, coupon_freq=2,
    coupon_schedule=coupon_dates, prev_coupon_date=(2024, 3, 1)
)




# Calculate prices for a range of yields
yields = np.arange(0.01, 0.101, 0.005) # Yields from 1% to 10%
prices = [price_bond(example_bond, settlement_date, y) for y in yields]




# Plotting
plt.figure(figsize=(10, 6))
plt.plot(yields, prices, 'b-o')
plt.title('Bond Price vs. Yield')
plt.xlabel('Yield to Maturity')
plt.ylabel('Clean Price ($)')
plt.grid(True)
plt.gca().yaxis.set_major_formatter('${x:,.2f}')
plt.gca().xaxis.set_major_formatter('{x:.1%}')
plt.show()

The resulting plot clearly demonstrates the inverse relationship. As you move from left to right along the x-axis (increasing yield), the curve moves downward (decreasing price). But notice something else: the relationship is not a straight line. It's a curve.


2. The Non-Linear Relationship: Convexity

The curved nature of the price-yield relationship is one of the most important concepts in fixed income risk management. This curvature is called convexity.

Bond Price-Yield Relationship and Convexity
This graph illustrates the characteristic convex shape of the price-yield curve for two different bonds. The straight "Duration" line represents a linear approximation, highlighting how the actual price deviates from a simple linear estimate, especially for large yield changes.

Why is the relationship non-linear? Let's explore this from two perspectives that align with your background: first, an intuitive, arithmetical approach, and second, a more formal calculus-based derivation.

An Intuitive View: The "Differential" Approach

A clever way to understand this non-linearity is to reframe the bond price calculation. Instead of just discounting all cash flows, think of a bond's price as its face value, adjusted by the present value of the difference between its coupon payments and the payments a par-yield bond would make.

Consider a 6% coupon bond.

  • If the required market yield rises to 7%, the bond is "under-paying" by 1% each year compared to the market rate. The price must fall below par to compensate the investor. The size of this discount is the present value of that 1% stream of underpayments, discounted at 7%.
  • If the required market yield falls to 5%, the bond is "over-paying" by 1% each year. The price must rise above par. The size of this premium is the present value of that 1% stream of overpayments, discounted at 5%.

The key to non-linearity lies in the discount rate used. The present value of the $10 annual overpayment (discounted at 5%) is greater than the present value of the $10 annual underpayment (discounted at 7%). Therefore, a 1% drop in yield increases the price by more than a 1% rise in yield decreases it. This asymmetry creates the convex curve.

The following paper formalizes this "differential approach" and uses it to explain convexity intuitively.

Teaching Bond Valuation: A Differential Approach

This paper provides an alternative, intuitive way to understand bond premiums and discounts, and uses it to clearly explain the non-linear price-yield relationship (convexity).

First, read the section "Bond Valuation Convexity". It walks through the numerical example we just discussed, showing precisely why the price change is asymmetric for equal changes in yield. Then, for mathematical completeness, review the "Appendix Proof" at the end. It demonstrates that this differential pricing formula is algebraically equivalent to the traditional one, confirming its validity.

A Formal View: The Calculus Approach

Your background in mathematics and engineering makes the calculus-based explanation of convexity particularly relevant. The price-yield relationship is non-linear because its derivatives are not constant.

We can analyze the function using a Taylor series expansion around a starting yield :

  1. First Derivative (Slope): The term represents the slope of the price-yield curve. As we've established, this slope is negative, confirming the inverse relationship. This first-order sensitivity measure is known as duration, a topic we will explore in depth later.

  2. Second Derivative (Curvature): The term represents the curvature. For a standard bond, this second derivative is positive. A positive second derivative means the function is convex.

This positive second derivative explains the asymmetry. When is squared, the result is always positive. This means the second-order term, , adds a positive amount to the price change calculation regardless of whether yields rise or fall. This "convexity adjustment" counteracts some of the price loss when yields rise and adds to the price gain when yields fall, creating the asymmetric effect we observed.

The following reading from ETH Zurich provides a rigorous, academic treatment of this concept.

Quantitative Finance: Bond Fundamentals

This lecture slide deck formally introduces the price-yield relationship using a Taylor expansion, defining duration and convexity in terms of derivatives.

Start reading from slide 29, titled with the header "We will now address the question: what happens to the price of the bond when the yield changes...". Continue until the end of slide 40. Focus on: The formulation of the Taylor expansion on slide 29. The definitions of Dollar Duration and Dollar Convexity as the first and second derivatives on slides 30-31. The summary of the price change approximation on slide 34. The graph on slide 39, which brilliantly visualizes the exact price curve against the first-order (linear) and second-order (duration + convexity) approximations.


Conclusion

In this lesson, we have moved beyond a simple calculation to a deeper understanding of the dynamics between bond price and yield.

Key takeaways:

  • The relationship between a bond's price and its yield is inverse: as yields increase, prices decrease. This is a direct consequence of the yield being the discount rate in the present value formula.
  • This relationship is non-linear and convex. This curvature arises because the price is a sum of powers of the discount factor.
  • The practical implication of convexity is that price gains from a drop in yield are larger than price losses from an equivalent rise in yield.
  • We can understand this non-linearity both intuitively (by analyzing the present value of over/under-paid coupons at different rates) and mathematically (by examining the positive second derivative of the price-yield function).

You now have a solid grasp of how and why a bond's price moves in response to yield changes. In our next lesson, we will tackle the inverse problem: given a bond's market price, how do we find the yield-to-maturity? As the non-linear equation suggests, there's no simple algebraic solution, which will lead us into the world of numerical root-finding algorithms in Python.