Bond Pricing Fundamentals: Yield to Maturity & Present Value

Michael BrenndoerferUpdated December 28, 202542 min read

Covers bond pricing through present value calculations, yield to maturity analysis, and price-yield relationships. Topics include fixed income fundamentals.

Quantitative FinanceAll chapters
Part 2 of 15Equity and Fixed Income Markets
Part 2 of 15Equity and Fixed Income Markets
Chapter 11Bond Fundamentals and Pricing › Bond Fundamentals and Pricing
Reading the full chapter · 14 sections · 42 min14 sections · 42 min

Book contents

All 14 sections · 42 min read

Bond Fundamentals and Pricing › Bond Fundamentals and PricingFull chapter · Sections in this chapter1 / 14 ↓
Track your reading progress

Sign in to mark sections as read and track your learning journey

Sign in →
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

Bond Fundamentals and Pricing

A bond can keep paying the same $30 coupon every six months while its market price rises or falls. The payment promise and the price are different objects: pricing asks what those future payments are worth today at the yield investors require.

Issuers use bonds to borrow from investors; bondholders are creditors rather than equity owners. In its 2026 Capital Markets Fact Book, SIFMA reports $160.7 trillion of global fixed-income debt outstanding and $157.8 trillion of global equity market capitalization for 2025. Outstanding debt and equity market capitalization measure different types of claims on issuers.

We will price a regular coupon bond, recover its yield from a price, and distinguish the quoted clean price from the full settlement amount. The floating-rate example then shows why a coupon reset alone does not guarantee a par price.

Anatomy of a Bond

A bond is a contractual agreement between an issuer (the borrower) and investors (the lenders). The issuer promises to make a series of payments according to a predetermined schedule in exchange for receiving capital upfront. The key parameters that define a bond are:

  • Face Value (Par Value): The principal amount promised at maturity. A $1,000 face value is common in corporate-bond examples, but actual denominations vary. A price quoted as 100 means 100% of face value, not necessarily a $100 principal amount. The face value is the basis for calculating coupons.

  • Coupon Rate: The annual interest rate applied to the face value to determine periodic payments. A 5% coupon on a $1,000 face value bond pays $50 per year in interest.

  • Maturity Date: The date when the issuer must repay the face value. Maturities range from short-term (under 1 year) to long-term (30 years or more).

  • Payment Frequency: How often coupon payments occur. Most bonds pay semiannually in the US, while European bonds often pay annually.

  • Issuer: The entity borrowing money. Issuers include sovereign governments, municipalities, corporations, and supranational organizations.

Par, Premium, and Discount

A bond trades at par when its price equals its face value, at a premium when the price exceeds face value, and at a discount when the price is below face value. These relationships depend on how the bond's coupon rate compares to prevailing market interest rates.

Government vs. Corporate Bonds

US Treasuries and German Bunds are often used as low-credit-risk benchmarks in their respective currencies. That does not make them free of interest-rate, inflation, or liquidity risk, and a benchmark must match the currency and horizon of the valuation. Government payment capacity and institutional arrangements differ: Germany, for example, does not independently issue euros to service its debt.

Corporate issuers can default on their obligations. Investors generally require compensation for that risk relative to an appropriate low-credit-risk reference. A credit spread compares a bond's yield with a stated reference yield of comparable maturity; it can reflect default and recovery expectations as well as liquidity, risk premia, and other contractual features. It is not a direct estimate of default probability alone.

Cash Flow Patterns

Start by identifying the amount and date of each promised payment. For the plain fixed-rate, noncallable bond used below, the contractual schedule is known at issuance. Actual receipt still depends on payment in full; floating coupons, embedded options, or default can change the amounts or timing. Equity dividends are different because they are not a fixed contractual coupon schedule.

Coupon Bonds

A standard coupon bond generates two types of cash flows: periodic coupon payments during its life and a final principal repayment at maturity. For a bond with face value FF, annual coupon rate cc, and semiannual payments, each coupon payment equals cF2\frac{cF}{2}.

The logic behind this calculation is straightforward. If a bond promises 6% annual interest on a $1,000 face value, the total annual interest obligation is $60. When this interest is distributed across two semiannual payments, each payment becomes $30. This division of the annual coupon into smaller periodic payments has practical implications for how we measure yield and compare bonds, as we will see when discussing compounding conventions.

Consider a 10-year bond with a $1,000 face value and 6% annual coupon paid semiannually. The bondholder receives:

  • 20 coupon payments of $30 each (every 6 months for 10 years)
  • One principal payment of $1,000 at maturity

The final payment at maturity includes both the last coupon and the face value, totaling $1,030.

In[3]:
Code
import numpy as np

# Bond parameters
face_value = 1000
coupon_rate = 0.06
years_to_maturity = 10
payments_per_year = 2

# Generate cash flows
coupon_payment = face_value * coupon_rate / payments_per_year
num_payments = years_to_maturity * payments_per_year

cash_flows = np.full(num_payments, coupon_payment)
cash_flows[-1] += face_value  # Add principal to final payment

# Create time points (in years)
times = np.arange(1, num_payments + 1) / payments_per_year
Out[4]:
Console
Bond Cash Flow Schedule (selected payments)
---------------------------------------------
Period     Time (yrs)      Cash Flow ($)  
---------------------------------------------
1          0.50            30.00          
2          1.00            30.00          
3          1.50            30.00          
19         9.50            30.00          
20         10.00           1030.00        
---------------------------------------------
Total cash flows: $1,600.00
Out[5]:
Visualization
Bar chart showing bond cash flows over 10 years with small regular payments and a large final payment.
Cash flow pattern for a 10-year bond with a 6% annual coupon paid semiannually. Nineteen payments of \$30 are followed by a twentieth payment of \$1,030, which combines the last \$30 coupon and the \$1,000 principal repayment. The schedule contains twenty coupons and one principal repayment.

The total undiscounted cash flows exceed face value by the cumulative coupon payments. At a positive discount rate, each future payment has a smaller present value than its future dollar amount. Zero or negative rates require different comparisons, as the discounting formula makes explicit.

Zero-Coupon Bonds

Zero-coupon bonds pay no periodic coupons and promise a single payment at maturity. With a positive yield and positive time to maturity, price is below face value; at zero yield it is at par, and a negative yield can put it above par. An investor who holds to maturity and is paid in full earns the difference between the redemption amount and purchase price before costs and taxes.

US Treasury bills (T-bills) with maturities up to one year are zero-coupon instruments. A T-bill with a face value of $10,000 might sell for $9,800, with the $200 difference representing the investor's interest income.

A deterministic coupon schedule can be valued as a collection of individual dated payments. This valuation decomposition is not a claim that every bond can be legally or economically stripped into separately tradeable instruments. The Treasury STRIPS program, Separate Trading of Registered Interest and Principal of Securities, does permit eligible Treasury principal and coupon components to be held and traded separately.

Bond Pricing by Discounting Cash Flows

The price of a bond equals the present value of all its future cash flows, discounted at an appropriate rate. This principle connects bond valuation to the time value of money. Bond pricing answers this simple question. What would a rational investor pay today in exchange for a known stream of future payments? The answer requires us to account for the opportunity cost of capital, the return an investor could earn by deploying funds elsewhere.

Present Value Framework

Discounting compares money available at different dates under a stated rate convention. If $100 can earn 5% for one year, it grows to $105, so $105 due next year has a present value of $100 at that rate. A positive rate makes present value smaller than the future amount; the statement is not unconditional when rates can be zero or negative.

For known cash flows C1,C2,…,CnC_1, C_2, \ldots, C_n at times t1,t2,…,tnt_1, t_2, \ldots, t_n in years, and a single effective annual discount rate r>−1r>-1, the price in this simplified model is:

P=∑i=1nCi(1+r)tiP = \sum_{i=1}^{n} \frac{C_i}{(1 + r)^{t_i}}

where:

  • PP: current price of the bond
  • CiC_i: cash flow received at time tit_i (coupon or principal)
  • tit_i: time in years until the ii-th cash flow
  • rr: annual discount rate (yield)
  • nn: total number of cash flows

The factor (1+r)ti(1+r)^{t_i} is the growth of one dollar over tit_i years under the effective annual rate convention. Dividing a future payment by it reverses that growth. At r>0r>0, a later otherwise identical payment has a lower present value; at r=0r=0 the values are equal, while a negative rate reverses the ordering.

Out[6]:
Visualization
Line chart showing exponential decay of discount factors from 1.0 at time 0 to about 0.56 at year 10.
Exponential decay of discount factors over time at a 6% annual yield, showing the time value of money. The chart shows how discount factors decrease from 1.0 at time zero to approximately 0.56 at year 10, showing that a dollar received 10 years from now is worth only about 56 cents in today's dollars. This decay pattern explains why distant cash flows contribute proportionally less to a bond's present value.

For the next examples, value a fixed-rate, noncallable bond immediately after a coupon date, with equally spaced payments, nonnegative coupons, positive face value, and a positive integer number of remaining periods. Let mm be the positive integer payment frequency and y>−my>-m the nominal annual yield compounded mm times per year. Its periodic yield is y/my/m, and the price is:

P=∑i=1nCi(1+ym)iP = \sum_{i=1}^{n} \frac{C_i}{\left(1 + \frac{y}{m}\right)^i}

where:

  • PP: bond price
  • CiC_i: cash flow at period ii
  • yy: annual yield to maturity
  • mm: number of payment periods per year
  • nn: total number of payment periods
  • ii: period counter (1, 2, ..., nn)

Here, ii counts payment periods rather than years, and we divide the annual yield by mm to get the per-period rate. This adjustment accounts for the compounding frequency. A bond paying semiannually compounds twice per year, so we use half the annual rate for each six-month period. The distinction matters. A 6% annual yield compounded semiannually is not the same as a 6% yield compounded annually. With semiannual compounding, you earn 3% in the first half of the year, then 3% on that larger balance in the second half, resulting in an effective annual yield slightly above 6%.

Pricing a Coupon Bond

Now that we understand how to discount individual cash flows, we can develop a simpler formula for pricing standard coupon bonds. Rather than discounting each payment individually, we can exploit the regular structure of coupon payments to derive a closed-form expression that separates the bond's value into two intuitive components.

For a standard coupon bond, we can separate the cash flows into an annuity (the coupons) and a lump sum (the face value). The coupon payments form what mathematicians call an ordinary annuity, a sequence of equal payments occurring at regular intervals. A compact formula exists for the present value of such an annuity, which we can combine with the discounted principal to get the total bond price.

Let cc be the coupon rate, FF the face value, yy the yield, mm the payment frequency, and nn the total number of periods. The price is:

P=cFm⋅1−(1+y/m)−ny/m+F(1+y/m)nP = \frac{cF}{m} \cdot \frac{1 - (1 + y/m)^{-n}}{y/m} + \frac{F}{(1 + y/m)^n}

where:

  • PP: bond price
  • cc: annual coupon rate (as a decimal)
  • FF: face value (par value)
  • mm: number of coupon payments per year
  • yy: annual yield to maturity
  • nn: total number of coupon periods (years×m\text{years} \times m)
  • cFm\frac{cF}{m}: the periodic coupon payment amount
  • 1−(1+y/m)−ny/m\frac{1 - (1 + y/m)^{-n}}{y/m}: the present value annuity factor for y≠0y\ne0; at y=0y=0 its continuous limit is nn.

The formula separates bond value into two components:

  1. Coupon annuity (first term): The stream of periodic coupon payments forms an ordinary annuity. The annuity factor 1−(1+y/m)−ny/m\frac{1 - (1 + y/m)^{-n}}{y/m} represents how much a dollar paid each period for nn periods is worth today. It's the sum of all the individual discount factors. To understand this factor, imagine receiving $1 at the end of each period for nn periods. The present value of the first dollar is 1/(1+y/m)1/(1+y/m), the second is 1/(1+y/m)21/(1+y/m)^2, and so on. The annuity factor is simply the sum of this geometric series, expressed in a single formula. As the number of periods increases or the yield decreases, this factor grows. You're receiving more dollars, or each dollar is worth more in present value terms.

  2. Principal repayment (second term): The face value received at maturity, discounted back to today by the factor (1+y/m)−n(1 + y/m)^{-n}. This term captures the return of the investor's principal. For long-maturity bonds, this discount factor can be quite small. At a 6% yield compounded semiannually over 30 years, the discount factor is approximately 0.17, meaning the present value of the $1,000 face value is only about $170.

For this fixed positive-cash-flow schedule, increasing the admissible yield decreases each discounted payment and therefore the total price. At the same maturity, yield, and compounding convention, reducing the coupon shifts more of the value toward the final principal payment and increases percentage price sensitivity. A zero-coupon bond is the limiting case. This comparison concerns percentage sensitivity, not necessarily the dollar price change of bonds with the same face value.

In[7]:
Code
def _finite_number(value, name):
    """Convert one finite scalar; reject booleans and nonscalar inputs."""
    if isinstance(value, (bool, np.bool_)) or np.ndim(value) != 0:
        raise ValueError(f"{name} must be one finite number")
    try:
        result = float(value)
    except (TypeError, ValueError, OverflowError) as exc:
        raise ValueError(f"{name} must be one finite number") from exc
    if not np.isfinite(result):
        raise ValueError(f"{name} must be finite")
    return result


def _regular_bond_inputs(face_value, coupon_rate, years_to_maturity, payments_per_year):
    """Validate the regular coupon-date model, not a dated settlement schedule."""
    face = _finite_number(face_value, "face_value")
    coupon = _finite_number(coupon_rate, "coupon_rate")
    years = _finite_number(years_to_maturity, "years_to_maturity")
    frequency = _finite_number(payments_per_year, "payments_per_year")
    if face <= 0 or coupon < 0 or years < 0:
        raise ValueError("Require positive face value, nonnegative coupon and maturity")
    if frequency <= 0 or not frequency.is_integer():
        raise ValueError("payments_per_year must be a positive integer")
    periods = years * frequency
    if not np.isfinite(periods) or abs(periods - round(periods)) > 1e-10:
        raise ValueError(
            "Maturity times frequency must be a finite integer period count"
        )
    return face, coupon, years, int(frequency), int(round(periods))


def price_bond(
    face_value, coupon_rate, years_to_maturity, yield_rate, payments_per_year=2
):
    """Price regular, nonnegative fixed coupons on a coupon-date boundary.

    Yield is a nominal annual quote compounded payments_per_year times.
    Require yield > -payments_per_year and a whole remaining period count.
    At zero remaining maturity, face value is due immediately. Irregular
    schedules and between-coupon settlement need a dated cash-flow model.
    """
    face, coupon, _, frequency, periods = _regular_bond_inputs(
        face_value, coupon_rate, years_to_maturity, payments_per_year
    )
    annual_yield = _finite_number(yield_rate, "yield_rate")
    periodic_yield = annual_yield / frequency
    if periodic_yield <= -1:
        raise ValueError("yield_rate must exceed -payments_per_year")
    periodic_coupon = coupon * face / frequency
    with np.errstate(over="ignore", invalid="ignore", under="ignore"):
        log_growth = np.log1p(periodic_yield)
        principal_factor = np.exp(-periods * log_growth)
        annuity_factor = (
            float(periods)
            if periodic_yield == 0
            else -np.expm1(-periods * log_growth) / periodic_yield
        )
        value = periodic_coupon * annuity_factor + face * principal_factor
    if not np.isfinite(value) or value <= 0:
        raise ValueError("Price is outside the supported floating-point range")
    return float(value)
In[8]:
Code
# Price a 10-year bond with 6% coupon at different yield levels
face_value = 1000
coupon_rate = 0.06
years = 10

yields = [0.04, 0.05, 0.06, 0.07, 0.08]
prices = [price_bond(face_value, coupon_rate, years, y) for y in yields]
Out[9]:
Console
Bond Prices at Different Yield Levels
---------------------------------------------
Yield           Price ($)       Price/Par      
---------------------------------------------
4.0%            1163.51         116.35%        
5.0%            1077.95         107.79%        
6.0%            1000.00         100.00%        
7.0%            928.94          92.89%         
8.0%            864.10          86.41%

This demonstrates the inverse relationship between yields and prices. When the yield equals the coupon rate (6%), the bond trades at par. When yields fall below the coupon rate, the bond trades at a premium because its fixed coupons are more attractive than market rates. When yields rise above the coupon rate, the bond trades at a discount.

Suppose new otherwise comparable bonds offer 7% coupons. A 6% coupon bond pays less interest per year for the same face value, so a lower purchase price can make its promised cash flows yield the required return. Comparisons need matching currency, credit, options, liquidity, and discounting assumptions. Equal promised-payment yields do not guarantee equal realized returns.

Out[10]:
Visualization
Stacked bar chart showing coupon PV and principal PV components at different yield levels.
Stacked bar chart decomposing a 10-year 6% coupon bond''s price into its two components: present value of coupon payments (blue bars, representing the annuity value) and present value of principal repayment (orange bars). As yields decrease from 8% to 4%, both components increase in value, but the principal component grows relatively faster due to the compounding effects of discounting over the full 10-year horizon.

Pricing a Zero-Coupon Bond

Zero-coupon bonds strip away the complexity of multiple cash flows, leaving us with the purest expression of present value. With only a single payment at maturity, the pricing formula reduces to its most elemental form, making zero-coupon bonds ideal pedagogical tools for understanding how time and yield interact to determine value.

Zero-coupon bonds have a simpler pricing formula since there's only one cash flow:

P=F(1+r)TP = \frac{F}{(1 + r)^{T}}

where:

  • PP: current price of the zero-coupon bond
  • FF: face value paid at maturity
  • rr: annual yield (discount rate)
  • TT: time to maturity in years

The simplicity of this formula makes zero-coupon bonds ideal building blocks for understanding fixed income. The price represents exactly how much an investor must pay today to receive FF dollars in TT years, given the market's required return of rr. Notice that the price is always less than the face value (assuming a positive yield), and the discount increases with both yield and time to maturity. A 30-year zero-coupon bond at a 5% yield trades at roughly 23% of its face value, which reflects the substantial time value of money over such a long horizon.

In[11]:
Code
def price_zero_coupon(face_value, years_to_maturity, yield_rate):
    """Price one future principal payment at an effective annual yield > -1."""
    face = _finite_number(face_value, "face_value")
    years = _finite_number(years_to_maturity, "years_to_maturity")
    annual_yield = _finite_number(yield_rate, "yield_rate")
    if face <= 0 or years < 0 or annual_yield <= -1:
        raise ValueError("Require positive face, nonnegative maturity and yield > -1")
    with np.errstate(over="ignore", under="ignore", invalid="ignore"):
        value = face * np.exp(-years * np.log1p(annual_yield))
    if not np.isfinite(value) or value <= 0:
        raise ValueError("Price is outside the supported floating-point range")
    return float(value)


# Price 5-year zero-coupon bonds at different yields
zcb_prices = [price_zero_coupon(1000, 5, y) for y in yields]
Out[12]:
Console
Zero-Coupon Bond Prices (5-year maturity)
-----------------------------------
Yield           Price ($)      
-----------------------------------
4.0%            821.93         
5.0%            783.53         
6.0%            747.26         
7.0%            712.99         
8.0%            680.58

At the same maturity and yield convention, a zero-coupon bond has greater percentage yield sensitivity than an otherwise comparable positive-coupon bond. Its value is concentrated in the terminal payment. Dollar price sensitivity also depends on the amount invested or face value, so it need not follow the same ranking.

Yield to Maturity

Traders can observe a market price and solve for its implied yield to maturity (YTM). It is the single rate equating that price to the present value of the promised payment schedule under the specified convention. The quote describes those promised payments rather than predicting the investor's realized return.

Yield to Maturity

YTM is the internal rate of return of the promised payment schedule at the observed full price, under a specified compounding and settlement convention. The calculation itself does not require an actual reinvestment strategy. Realizing the corresponding compound holding-to-maturity return additionally requires payment in full and reinvestment of coupons at that yield, before costs and taxes.

Calculating YTM

The calculation of yield to maturity reverses the pricing problem we solved earlier. Instead of taking a yield and computing a price, we observe a market price and work backward to find the yield that makes our pricing formula produce that exact price. For the multi-period coupon examples here, we solve this inverse problem by numerical iteration.

Finding the YTM requires solving for yy in the bond pricing equation:

P=∑i=1nCi(1+ym)iP = \sum_{i=1}^{n} \frac{C_i}{\left(1 + \frac{y}{m}\right)^i}

where:

  • PP: observed market price (known)
  • yy: yield to maturity (unknown, to be solved)
  • CiC_i, mm, nn: as defined previously

For a multi-period coupon bond, it is generally more practical to solve numerically than to derive an algebraic expression for yy. Special cases do have closed-form solutions, including a single remaining payment. Newton-Raphson or Brent's bracketed method can find a yield numerically; a Brent bracket must lie in the model domain and contain a sign change in the continuous price residual.

In[13]:
Code
from scipy.optimize import brentq


def yield_to_maturity(
    price,
    face_value,
    coupon_rate,
    years_to_maturity,
    payments_per_year=2,
    *,
    yield_bracket=(0.0001, 0.5),
):
    """Solve a nominal annual YTM only within an explicit finite bracket.

    The default covers 0.01% through 50%, matching these examples. Supply
    another admissible bracket for zero or negative yields; this helper
    does not automatically search every possible financial yield.
    """
    target = _finite_number(price, "price")
    face, coupon, years, frequency, periods = _regular_bond_inputs(
        face_value, coupon_rate, years_to_maturity, payments_per_year
    )
    if target <= 0 or periods == 0:
        raise ValueError("Require positive price and positive remaining maturity")
    try:
        lower, upper = yield_bracket
    except (TypeError, ValueError) as exc:
        raise ValueError("yield_bracket must have exactly two endpoints") from exc
    lower = _finite_number(lower, "lower yield endpoint")
    upper = _finite_number(upper, "upper yield endpoint")
    if lower <= -frequency or upper <= lower:
        raise ValueError("Require -frequency < lower < upper for yield_bracket")

    def price_difference(y):
        return price_bond(face, coupon, years, y, frequency) - target

    lower_value, upper_value = price_difference(lower), price_difference(upper)
    if lower_value == 0:
        return lower
    if upper_value == 0:
        return upper
    if np.signbit(lower_value) == np.signbit(upper_value):
        raise ValueError(
            "yield_bracket does not bracket this price; choose endpoints with opposite residual signs"
        )
    return float(brentq(price_difference, lower, upper))


# Calculate YTM for bonds at various prices
test_prices = [1100, 1050, 1000, 950, 900]
ytms = [yield_to_maturity(p, 1000, 0.06, 10) for p in test_prices]
Out[14]:
Console
Yield to Maturity Calculation
---------------------------------------------
Price ($)       YTM             vs Coupon Rate 
---------------------------------------------
1100            4.733         % Premium        
1050            5.348         % Premium        
1000            6.000         % Par            
950             6.694         % Discount       
900             7.435         % Discount

The results confirm our earlier observation: premium bonds (price > par) have yields below the coupon rate, while discount bonds have yields above the coupon rate.

YTM Assumptions and Limitations

Separate the quoted IRR from a realized investment return:

  • Payment and holding horizon: YTM uses the promised payments through maturity. Default or a sale before maturity changes the realized cash flows.
  • Coupon reinvestment: Realizing the YTM as a compound return through maturity requires reinvesting intermediate coupons at that rate. Available rates can differ, especially across many coupon dates.

YTM is a useful comparison quote, not a guaranteed total return or a complete measure of relative value. Credit, options, liquidity, taxes, costs, and the timing of cash flows still matter.

Fixed Rate vs. Floating Rate Bonds

The bonds we've discussed so far have fixed coupon rates set at issuance. Floating rate bonds (or floating rate notes, FRNs) have coupon rates that reset periodically based on a reference rate plus a spread. This fundamental structural difference creates very different risk profiles and pricing dynamics.

Floating Rate Mechanics

As an illustrative advance-reset contract, suppose a quarterly floater uses a specified three-month reference rate plus 100 basis points. A 4.5% reference fixing would produce a 5.5% annualized coupon. Do not equate that term fixing with overnight SOFR: SOFR-linked notes may instead compound daily overnight rates in arrears, so the period's final coupon is not known at its start.

The coupon for each period is calculated as:

Coupon Rate=Reference Rate+Spread\text{Coupon Rate} = \text{Reference Rate} + \text{Spread}

where:

  • Coupon Rate\text{Coupon Rate}: the interest rate for the upcoming coupon period
  • Reference Rate\text{Reference Rate}: the contractually specified fixing or period benchmark; its observation timing depends on the advance-reset or in-arrears convention
  • Spread\text{Spread}: the contractual coupon margin, distinct from the current market-required discount margin

The contract determines the observation dates, lookback, and whether the rate is fixed in advance or compounded in arrears. Its quoted margin may be fixed at issuance, but the market-required margin can change with credit and liquidity conditions. Resets reduce some benchmark-rate exposure relative to an otherwise comparable fixed-rate bond; they do not remove credit, spread, basis, reset-lag, or liquidity risk.

Pricing Floating Rate Bonds

Future coupons depend on the contract's reference-rate observations. For a one-period valuation, assume the note's ex-coupon value will be FF immediately after its next coupon/reset. This is a pricing assumption, not a consequence of unchanged issuer credit quality alone.

Let cc be the current annualized fixed coupon, α\alpha the full current coupon-period accrual fraction, τ\tau the remaining time to payment under the same simple-accrual basis, and d=r+sd=r+s the current reference discount rate plus required discount margin. Between coupon dates the next full coupon is cFαcF\alpha, not merely interest on the remaining time.

Pdirty=F+cFα1+dτ=F+(cα−dτ)F1+dτ,d=r+s,1+dτ>0.P_{\mathrm{dirty}}=\frac{F+cF\alpha}{1+d\tau} = F+\frac{(c\alpha-d\tau)F}{1+d\tau},\qquad d=r+s,\quad 1+d\tau>0.

Here FF is face value, cc is the coupon fixed for the current period, α\alpha is that full coupon's accrual fraction, τ\tau is remaining time, rr is the chosen reference discount rate, and ss is the market-required discount margin. On a coupon date just after payment, τ=α\tau=\alpha for the new period, and this model is at par only if c=dc=d. Between dates, dirty price also includes accrued interest.

As the next payment approaches, τ→0\tau\to0 while the full coupon cFαcF\alpha remains due: dirty value tends to F+cFαF+cF\alpha before payment and drops by that coupon after payment. Under the matching simple accrual convention, clean price is dirty price minus cF(α−τ)cF(\alpha-\tau). A coupon reset does not erase an already accrued coupon.

In[15]:
Code
def price_frn_between_resets(
    face_value,
    current_coupon_rate,
    current_reference_rate,
    time_to_reset,
    *,
    coupon_accrual_fraction,
    spread=0,
):
    """Return dirty value under an explicit next-reset ex-coupon-par model.

    coupon_accrual_fraction is the FULL current coupon period, while
    time_to_reset is its remaining fraction on the same simple basis.
    Credit/basis/curve effects beyond the stated flat discount margin are
    not modeled. The coupon and principal are assumed to be paid in full.
    """
    face = _finite_number(face_value, "face_value")
    coupon_rate = _finite_number(current_coupon_rate, "current_coupon_rate")
    reference = _finite_number(current_reference_rate, "current_reference_rate")
    remaining = _finite_number(time_to_reset, "time_to_reset")
    alpha = _finite_number(coupon_accrual_fraction, "coupon_accrual_fraction")
    margin = _finite_number(spread, "spread")
    if face <= 0 or alpha <= 0 or not 0 <= remaining <= alpha:
        raise ValueError(
            "Require positive face and full accrual fraction, with 0 <= remaining <= full fraction"
        )
    payment = face * (1 + coupon_rate * alpha)
    denominator = 1 + (reference + margin) * remaining
    if payment <= 0 or denominator <= 0:
        raise ValueError(
            "Require positive promised next payment and discount denominator"
        )
    value = payment / denominator
    if not np.isfinite(value) or value <= 0:
        raise ValueError("Price is outside the supported floating-point range")
    return float(value)


# Example at the start of a quarter: fixed coupon 5.5%, reference 5%,
# full and remaining accrual fractions both 0.25, required margin 1%.
frn_price = price_frn_between_resets(
    face_value=1000,
    current_coupon_rate=0.055,
    current_reference_rate=0.05,
    time_to_reset=0.25,
    coupon_accrual_fraction=0.25,
    spread=0.01,  # 100 bps required discount margin
)

# Halfway through the same coupon period, the full $13.75 coupon remains due.
mid_period_dirty = price_frn_between_resets(
    1000, 0.055, 0.05, 0.125, coupon_accrual_fraction=0.25, spread=0.01
)
mid_period_accrued = 0.055 * 1000 * (0.25 - 0.125)
mid_period_clean = mid_period_dirty - mid_period_accrued
Out[16]:
Console
Floating Rate Note Price: $998.77
Price deviation from par: $-1.23
Mid-period dirty price:  $1006.20
Mid-period accrued:      $6.88
Mid-period clean price:  $999.33

The function returns about $998.77, or $1.23 below par. The fixed 5.5% coupon is below the 6% discount rate formed from the 5% reference rate and 1% required margin. This conditional example illustrates a small price deviation; it does not establish that FRN prices are stable under changes in credit spreads or other risks.

Clean Price, Dirty Price, and Accrued Interest

In many conventional bond markets, the quoted clean price excludes accrued interest, while the full or dirty price includes it. Express both prices and accrued interest on the same face-value basis before adding them. Flat-trading, defaulted, and ex-coupon securities can follow different rules.

For a standard cum-coupon settlement, the buyer receives the upcoming coupon and compensates the seller for the accrued portion through the settlement price. Entitlement follows the security's record-date and ex-coupon rules, not simply ownership on payment day. Special settlement adjustments can apply when a trade falls between the record date and payment date.

For a regular fixed coupon period using the stated actual-days coupon-period fraction, accrued interest is calculated as:

Accrued Interest=Coupon Payment×Days Since Last CouponDays in Coupon Period\text{Accrued Interest} = \text{Coupon Payment} \times \frac{\text{Days Since Last Coupon}}{\text{Days in Coupon Period}}

where:

  • Coupon Payment\text{Coupon Payment}: the full periodic coupon amount (e.g., c×Fm\frac{c \times F}{m})
  • Days Since Last Coupon\text{Days Since Last Coupon}: calendar days from the last payment date to settlement
  • Days in Coupon Period\text{Days in Coupon Period}: total days in the current coupon period

The fraction represents the portion of the coupon period that has elapsed. This is the seller's "fair share" of the upcoming coupon. If exactly half the period has elapsed, the seller is entitled to half the coupon.

The dirty price is then:

Dirty Price=Clean Price+Accrued Interest\text{Dirty Price} = \text{Clean Price} + \text{Accrued Interest}

where:

  • Dirty Price\text{Dirty Price}: the full bond price on the stated face-value basis, before transaction charges
  • Clean Price\text{Clean Price}: the quoted market price (excludes accrued interest)
Why Quote Clean Prices?

Many markets quote clean prices because dirty prices jump discontinuously at coupon payment dates. The clean price provides a smoother series that better reflects changes in interest rates and credit conditions rather than the mechanical passage of time through a coupon period.

In[17]:
Code
def calculate_accrued_interest(
    face_value,
    coupon_rate,
    days_since_coupon,
    days_in_period,
    payments_per_year=2,
):
    """Regular nonnegative fixed coupon, using the stated coupon-day ratio.

    Apply actual contractual dates and ex-coupon rules outside this example.
    """
    face, coupon_rate, _, frequency, _ = _regular_bond_inputs(
        face_value, coupon_rate, 1, payments_per_year
    )
    elapsed = _finite_number(days_since_coupon, "days_since_coupon")
    period = _finite_number(days_in_period, "days_in_period")
    if period <= 0 or not 0 <= elapsed <= period:
        raise ValueError("Require positive period days and 0 <= elapsed <= period")
    return (face * coupon_rate / frequency) * (elapsed / period)


# Example: 6% coupon bond, 45 days into a 182-day period
face_value = 1000
coupon_rate = 0.06
days_since_coupon = 45
days_in_period = 182

accrued = calculate_accrued_interest(
    face_value, coupon_rate, days_since_coupon, days_in_period
)
clean_price = 1025.50  # Quoted market price
dirty_price = clean_price + accrued
Out[18]:
Console
Bond Settlement Calculation
----------------------------------------
Clean Price (quoted):    $1,025.50
Accrued Interest:        $7.42
Dirty Price (paid):      $1,032.92

Days since last coupon: 45
Days in coupon period:  182
Fraction of period:     24.73%

When the buyer receives the next coupon payment, it will compensate them for both the accrued interest they paid and the interest earned during the remaining portion of the period they held the bond.

Out[19]:
Visualization
Line chart showing sawtooth pattern of dirty price versus flat clean price over two coupon periods.
Illustrative clean and dirty prices over two 182-day coupon periods. The primary-colored clean-price line is assumed constant at \$1,020; the rose dirty-price line adds linearly accrued interest. The accrued component resets at each coupon boundary. This is a quotation-mechanics illustration, not a simulated no-arbitrage path at constant yield, and the daily sampled jump is slightly less than the full \$30 coupon.

Day Count Conventions

The calculation of accrued interest depends on how days are counted, which varies by market and instrument type. These day count conventions affect both the numerator (days elapsed) and denominator (days in the period or year) of interest calculations. Though this seems like a minor technicality, day count conventions can significantly affect payments and valuations, particularly for large positions or over extended periods.

Common Conventions

A day-count convention is part of the contract, not an accuracy ranking. Different named conventions can produce different accrual fractions from the same calendar dates. Use the convention specified for the actual instrument, including any month-end, leap-year, or irregular-coupon rules.

Common day-count conventions include:

  • Actual/Actual: A family of conventions using actual calendar days. For the regular US Treasury coupon-period example here, accrued coupon interest uses elapsed actual days divided by actual days in the coupon period. Other Actual/Actual variants and irregular coupon periods need their specified rules.

  • 30/360: A family of conventions using a stylized 360-day year and defined month-end adjustments. Variants differ in how they treat the 31st and February month ends. The simplified helper below is only the explicitly stated date-adjustment rule, not a complete implementation of every US corporate or municipal convention.

  • Actual/360: Actual elapsed days divided by 360. It is used in a range of money-market and floating-rate contracts. At the same quoted annual rate and elapsed-day count, it produces more accrued interest than Actual/365 Fixed because 360 is the smaller denominator; the elapsed interval need not exceed 360 days.

  • Actual/365 Fixed: Actual elapsed days divided by 365, including intervals containing leap days. Distinguish this named fixed-denominator convention from other Actual/365 variants.

In[20]:
Code
from datetime import date


def day_count_30_360(start_date, end_date):
    """
    Illustrative 30/360 rule: cap start day at 30, then conditionally cap end.

    This is not a complete named US convention: February ends are not adjusted.
    """
    d1 = min(start_date.day, 30)
    d2 = end_date.day if d1 < 30 else min(end_date.day, 30)

    days = (
        360 * (end_date.year - start_date.year)
        + 30 * (end_date.month - start_date.month)
        + (d2 - d1)
    )
    return days


def day_count_actual(start_date, end_date):
    """Calculate actual days between two dates."""
    return (end_date - start_date).days


# Compare conventions for a corporate bond
last_coupon = date(2024, 6, 15)
settlement = date(2024, 8, 20)
next_coupon = date(2024, 12, 15)

actual_days = day_count_actual(last_coupon, settlement)
thirty_360_days = day_count_30_360(last_coupon, settlement)
period_actual = day_count_actual(last_coupon, next_coupon)
period_30_360 = day_count_30_360(last_coupon, next_coupon)
Out[21]:
Console
Day Count Convention Comparison
--------------------------------------------------
Last coupon date:  2024-06-15
Settlement date:   2024-08-20
Next coupon date:  2024-12-15

Convention           Days Elapsed    Period Days    
--------------------------------------------------
Actual/Actual        66              183            
30/360               65              180

The choice of convention affects the accrued interest calculation and therefore the dirty price. When comparing bonds or calculating returns, ensure consistent day count treatment.

The Price-Yield Relationship

The relationship between bond prices and yields is fundamental to fixed income analysis. Understanding this relationship helps explain interest rate risk and informs trading strategies. Every bond investor needs to understand how yield movements translate into price changes, since this relationship determines both risks and opportunities in fixed income markets.

Inverse Relationship

For the option-free bond with fixed positive cash flows used here, price decreases as its quoted yield increases within the model domain. That price-yield identity should not be read as saying every observed market-rate increase moves every bond price down: floating payments, embedded options, credit changes, and other drivers can change the comparison.

For an otherwise comparable bond paying a 5% coupon when the required nominal yield is 6%, the regular coupon-date price is below par. With yield and coupon held fixed, extending the payment schedule can change the price further. Duration measures the local percentage response to yield changes; maturity alone does not determine every dollar price-change comparison.

Out[22]:
Visualization
Line chart showing declining bond prices as yields increase from 2% to 10% for three different coupon rates.
Price-yield curves for three ten-year, \$1,000 face-value bonds with 4%, 6%, and 8% coupons under the same semiannual convention. All prices decrease as yield increases. The higher-coupon bond has a larger dollar price change over this range, while the lower-coupon bond has greater percentage sensitivity at the same yield. Each curve crosses par where its own yield equals its coupon rate.

Convexity of the Price-Yield Curve

For an option-free bond with positive fixed payments and admissible yields, the price-yield curve is convex. Around the same base yield, a symmetric yield decline produces a larger price gain than the loss from an equal yield rise, with other inputs fixed. This does not guarantee a profitable holding period or describe bonds whose embedded options change their cash flows.

The curvature arises from the present value formula. Since price is a sum of terms like C/(1+y)tC/(1+y)^t, the second derivative with respect to yy is positive (d2Pdy2>0\frac{d^2P}{dy^2} > 0). To understand this intuitively, consider what happens as yields change. When yields fall, each basis point decrease has a larger dollar impact because you're multiplying the cash flows by increasingly larger discount factors. The discount factors are growing at an accelerating rate as yields decline. Conversely, as yields rise, the discount factors shrink, so each additional basis point increase has a diminishing effect on price because you're taking away smaller and smaller pieces of value. This asymmetry, where gains accelerate as yields fall and losses decelerate as yields rise, is precisely what convexity measures. Convexity quantifies how much the price-yield relationship curves away from a straight line.

In[23]:
Code
# Demonstrate convexity with price changes
base_yield = 0.06
yield_change = 0.01  # 100 basis points

price_base = price_bond(1000, 0.06, 10, base_yield)
price_up = price_bond(1000, 0.06, 10, base_yield + yield_change)
price_down = price_bond(1000, 0.06, 10, base_yield - yield_change)

change_up = price_up - price_base
change_down = price_down - price_base
Out[24]:
Console
Convexity Demonstration: 10-Year 6% Bond
--------------------------------------------------
Price at 6% yield:     $1,000.00
Price at 7% yield:     $928.94
Price at 5% yield:     $1,077.95

Price change (+100bp): $-71.06 (-7.11%)
Price change (-100bp): $77.95 (7.79%)

Asymmetry: Gain $6.88 more than loss
Out[25]:
Visualization
Plot comparing curved actual price-yield relationship with linear tangent line, showing convexity gap.
Convexity of a ten-year 6% coupon bond priced with semiannual compounding. The primary curve shows actual price and the dashed rose line its exact tangent at 6% nominal annual yield, using modified duration of about 7.4387 years. The curve lies on or above this tangent, with equality at the base yield. The shaded difference illustrates curvature, not a guaranteed investment return.

For otherwise matched fixed positive-cash-flow bonds, longer maturity and lower coupon generally increase normalized yield convexity. The comparison concerns the same yield and compounding convention; it does not establish that every longer bond has a larger dollar gain or that an option-bearing bond is positively convex.

Practical Example: Comparing Bond Investments

Consider two bonds with the same face value, maturity, and semiannual payment convention. We will compare their promised-payment yields, rather than infer a complete relative-value recommendation from coupon and price alone:

  • Bond A: 5-year maturity, 4% coupon, priced at $950
  • Bond B: 5-year maturity, 6% coupon, priced at $1,040
In[26]:
Code
# Bond A: 5-year, 4% coupon at $950
ytm_a = yield_to_maturity(950, 1000, 0.04, 5)

# Bond B: 5-year, 6% coupon at $1,040
ytm_b = yield_to_maturity(1040, 1000, 0.06, 5)

# Calculate total cash flows
total_cf_a = 40 * 5 + 1000  # 5 years of $40 coupons + face value
total_cf_b = 60 * 5 + 1000  # 5 years of $60 coupons + face value

# Current yields (annual coupon / price)
current_yield_a = 40 / 950
current_yield_b = 60 / 1040
Out[27]:
Console
Bond Comparison Analysis
=======================================================
Metric                    Bond A          Bond B         
-------------------------------------------------------
Coupon Rate               4.00%           6.00%          
Price                     $950.00         $1,040.00      
Current Yield             4.21          % 5.77          %
Yield to Maturity         5.15          % 5.08          %
Total Cash Flows          $1,200         $1,300        
-------------------------------------------------------

Bond A's YTM is about 5.15%, compared with 5.08% for Bond B under the same semiannual quote convention. The discount on Bond A contributes to its yield, while Bond B pays larger coupons but is purchased above par. These figures compare promised-payment IRRs; deciding which is better value also requires comparable credit, options, liquidity, taxes, costs, and investment objectives.

The current yield (annual coupon divided by price) can be misleading because it ignores price appreciation for discount bonds and price depreciation for premium bonds.

Limitations and Practical Considerations

Bond pricing in practice involves complexities beyond this simplified framework. Understanding these limitations helps practitioners apply theoretical models appropriately.

The assumption of a single discount rate (the YTM) for all cash flows is a significant simplification. In reality, interest rates vary by maturity, forming a yield curve. Short-term rates may differ substantially from long-term rates, and using a single rate ignores this term structure. More sophisticated approaches discount each cash flow at its own appropriate rate, a topic we'll address when discussing yield curve construction.

Credit risk affects corporate debt and can affect sovereign debt as well. Default probabilities and recovery expectations can change with issuer finances and economic conditions. A constant-spread model does not represent those changing exposures. Embedded options, such as an issuer call or holder put, can change payment timing and require valuation consistent with the contractual exercise rights.

Liquidity also influences prices. A bond that trades infrequently may have a wider bid-ask spread and a price that doesn't fully reflect current market conditions. Two bonds with identical cash flows may trade at different prices simply because one is more liquid than the other.

Despite these limitations, the discounted cash flow framework remains the foundation of bond analysis. Understanding this framework is essential before tackling more advanced topics like duration, convexity, and term structure models.

Summary

This chapter established the fundamental concepts for understanding and pricing bonds:

Bond Characteristics: Face value, coupon terms, maturity, payment frequency, and issuer define the payment contract. Low-credit-risk sovereign yields can serve as currency-specific benchmarks; corporate spreads can reflect credit, liquidity, and risk premia.

Pricing Framework: The regular coupon-date model discounts a fixed nonnegative coupon annuity and terminal principal under one stated yield convention. Zero-coupon bonds have one promised principal payment. Dated settlement, credit, and options need additional treatment.

Yield to Maturity: YTM is the price-equating IRR of the promised schedule. It is distinct from realized return, which depends on actual payments, holding period, reinvestment, and costs.

Fixed vs. Floating Rate: Fixed coupons create exposure to discount-yield changes. Floating resets reduce some benchmark exposure, but par at reset requires matching coupon and market valuation assumptions; changes in credit or discount margins still affect price.

Clean and Dirty Prices: In standard cum-coupon settlement, dirty price adds accrued interest to clean price on the same quotation basis. Contractual day-count, record-date, and ex-coupon rules determine the treatment.

Price-Yield Relationship: For positive fixed cash flows without embedded options, price decreases with yield and is convex. Symmetric yield declines and rises then produce asymmetric price changes, with other inputs fixed; this is not a guaranteed investment profit.

Key Parameters

The key parameters for bond pricing and analysis are:

  • Face Value (F): The principal amount repaid at maturity. Sets the baseline for calculating coupon payments and determines the bond's par value.

  • Coupon Rate (c): Annual fixed coupon divided by face value. At matched maturity, yield, and convention, higher coupons reduce percentage yield sensitivity; dollar sensitivity need not decline.

  • Years to Maturity (T): Time until final principal is due. In the regular schedule, TmT m is an integer period count. Maturity is one determinant of sensitivity, together with coupon, yield, and contractual terms.

  • Yield to Maturity (y): The rate equating the promised schedule's present value to price. Its compounding and settlement convention must be specified; the quote is not a guaranteed realized return.

  • Payment Frequency (m): Number of coupon payments per year. Affects compounding calculations. Semiannual payments use y/2 as the periodic rate.

  • Reference Rate: For floating rate bonds, the benchmark rate (e.g., SOFR) that determines coupon resets. Changes in this rate directly affect future coupon payments.

  • Spread: Distinguish the contractual margin used in the floating coupon from the current market-required discount margin. A fixed contractual margin need not equal the margin investors require later.

Quiz

Ready to test your understanding? Take this quick quiz to reinforce what you've learned about bond fundamentals and pricing.

Bond Fundamentals and Pricing

Question 1 of 80 of 8 completed
A regular, noncallable fixed-coupon bond is priced just after a coupon payment at $1,050, above its $1,000 face value. Its annual coupon rate is 5%. Under matching regular compounding conventions, what can you conclude about its YTM?
Track your reading progress

Sign in to mark sections as read and track your learning journey

Sign in →
Keep the thread going

Continue reading

Book contents
A different angle
All writing
Quantitative Finance · Vol. 1

Bond Risk Measures: Duration, Convexity, and Immunization

Measure and manage bond interest rate risk using duration, convexity, and immunization. Topics include portfolio hedging and liability-driven investing.

51 min read
Quantitative Finance · Vol. 1

Term Structure of Interest Rates: Yield Curve Construction

Covers yield curve construction through zero rates, forward rates, and bootstrapping. Interpret curve shapes and build production-quality curves.

47 min read
Quantitative Finance · Vol. 1

Equity Markets and Stock Instruments: Trading & Valuation

Covers equity market fundamentals including stock ownership, order book mechanics, trading execution, and key valuation metrics for quantitative finance.

55 min read
Join the discussionAsk a question or share what you learned.

Comments

Add to the conversation

A question, a correction, or an example from your own work.

No comments yet. Be the first to share your thoughts!

About the author

Reference

Citation details

Cite or share this article.

BIBTEXAcademic
@misc{brenndoerfer2025bondpricing, author = {Michael Brenndoerfer}, title = {Bond Pricing Fundamentals: Yield to Maturity & Present Value}, year = {2025}, url = {https://mbrenndoerfer.com/writing/bond-pricing-fundamentals-yield-to-maturity-present-value}, organization = {mbrenndoerfer.com}, note = {Accessed: 2026-10-22} }
APAAcademic
Michael Brenndoerfer (2025). Bond Pricing Fundamentals: Yield to Maturity & Present Value. Retrieved from https://mbrenndoerfer.com/writing/bond-pricing-fundamentals-yield-to-maturity-present-value
MLAAcademic
Michael Brenndoerfer. "Bond Pricing Fundamentals: Yield to Maturity & Present Value." 2026. Web. October 22, 2026. <https://mbrenndoerfer.com/writing/bond-pricing-fundamentals-yield-to-maturity-present-value>.
CHICAGOAcademic
Michael Brenndoerfer. "Bond Pricing Fundamentals: Yield to Maturity & Present Value." Accessed October 22, 2026. https://mbrenndoerfer.com/writing/bond-pricing-fundamentals-yield-to-maturity-present-value.
HARVARDAcademic
Michael Brenndoerfer (2025) 'Bond Pricing Fundamentals: Yield to Maturity & Present Value'. Available at: https://mbrenndoerfer.com/writing/bond-pricing-fundamentals-yield-to-maturity-present-value (Accessed: October 22, 2026).
SimpleBasic
Michael Brenndoerfer (2025). Bond Pricing Fundamentals: Yield to Maturity & Present Value. https://mbrenndoerfer.com/writing/bond-pricing-fundamentals-yield-to-maturity-present-value
Newsletter

Stay up to date

Get new articles, book updates, and notes on AI and technology.

Unsubscribe at any time. Privacy policy