pickuma.
Finance

Bond Investing for Developers: Duration, Yield Curves, and Why Fixed Income Isn't Boring

An engineer's guide to bond investing — Treasury bonds, TIPS, bond ETFs, yield curve mechanics, duration and convexity explained with code, and how to think about fixed income in a portfolio.

7 min read

For the first five years I invested, I owned exactly zero bonds. The reasoning was simple: stocks return 9% per year on average, bonds return 3%, why would I allocate capital to the lower-returning asset? I was not alone in this — most developers I know who started investing after 2010 built 100% equity portfolios. The 2022 bond market crash, where long-term Treasuries lost 30% while stocks also dropped, seemed to validate the “bonds are pointless” thesis.

The flaw in this reasoning is not mathematical but mental-model-level. Bonds are not a lower-return substitute for stocks. They are a different instrument with different return drivers, different risk characteristics, and a different role in a portfolio. Understanding those differences — and the bond math that governs them — is what separates someone who reacts to market moves from someone who anticipated them. Here is what I wish I had understood about bonds when I started.

Bonds Are Just Loans With Price Tags

A bond is a contract: you lend money to an entity (US Treasury, corporation, municipality) and they pay you interest for a fixed period, then return your principal at maturity. That is it. The complexity comes from the fact that bonds trade on secondary markets, so their price fluctuates between issuance and maturity based on interest rate changes.

The relationship is mechanical and deterministic, not probabilistic like stock returns. If you buy a 10-year Treasury bond yielding 4% and rates rise to 5%, the market value of your bond drops because new bonds pay more. The price must fall until the effective yield on your discounted bond matches the new market rate. This is not the market “panicking” — it is the mathematical consequence of fixed cash flows discounted at a higher rate.

For a developer, the mental model that clicks: a bond is a function that takes a discount rate as input and returns a present value. When the discount rate changes, the present value changes deterministically:

def bond_price(face_value, coupon_rate, years, yield_to_maturity, payments_per_year=2):
    periods = int(years * payments_per_year)
    coupon = face_value * coupon_rate / payments_per_year
    ytm_period = yield_to_maturity / payments_per_year

    pv_coupons = sum([coupon / (1 + ytm_period) ** t for t in range(1, periods + 1)])
    pv_face = face_value / (1 + ytm_period) ** periods

    return pv_coupons + pv_face

# $1,000 face value, 4% coupon, 10-year, yielding 5%
price = bond_price(1000, 0.04, 10, 0.05)
print(f"Bond price: ${price:.2f}")  # ~$922

That 10-line function captures the core of fixed-income pricing. Play with the yield_to_maturity parameter and watch the price move — a 1% rate increase on a 10-year bond reduces its price by roughly 7-8%. That sensitivity is what the next concept, duration, quantifies.

Duration: The Number That Explains Everything

Duration measures a bond’s price sensitivity to interest rate changes. Modified duration tells you the approximate percentage price change for a 1% parallel shift in yields. A bond with modified duration of 7 will lose roughly 7% if rates rise 1%, and gain roughly 7% if they fall 1%.

Calculating it:

def modified_duration(face_value, coupon_rate, years, yield_to_maturity):
    epsilon = 0.0001  # 1 basis point shock
    price_up = bond_price(face_value, coupon_rate, years, yield_to_maturity + epsilon)
    price_down = bond_price(face_value, coupon_rate, years, yield_to_maturity - epsilon)
    price_current = bond_price(face_value, coupon_rate, years, yield_to_maturity)
    return (price_down - price_up) / (2 * epsilon * price_current)

dur = modified_duration(1000, 0.04, 10, 0.05)
print(f"Modified duration: {dur:.2f}")

The intuition that matters for portfolio construction: longer maturity = higher duration = more rate sensitivity. A 30-year Treasury bond has roughly three times the duration risk of a 10-year. If you expect rates to rise, shorten duration. If you expect rates to fall, extend it. This is the single most important tactical decision in fixed-income investing, and it is entirely separate from the credit quality decision (Treasury vs. corporate vs. junk).

The Yield Curve as a State Machine

The yield curve — a plot of Treasury yields across maturities from 1 month to 30 years — is the single best summary of bond market sentiment. Normally, longer maturities yield more: a 10-year bond pays more than a 2-year because you are taking more interest rate risk. When the curve inverts (2-year yields > 10-year yields), the bond market is pricing in a recession.

You can pull yield curve data from the US Treasury’s public API:

import requests
import xml.etree.ElementTree as ET

url = ("https://home.treasury.gov/resource-center/"
       "data-chart-center/interest-rates/pages/"
       "xml?data=daily_treasury_yield_curve&field_tdr_date_value=2026")
resp = requests.get(url)
root = ET.fromstring(resp.content)

for entry in root.findall('.//{http://www.w3.org/2005/Atom}entry'):
    # Extract maturity and yield from each entry
    pass  # Implementation depends on response structure

For a simpler approach, the FRED API (covered in a separate guide) gives you clean time-series: DGS2 for 2-year, DGS10 for 10-year, DGS30 for 30-year yields. The spread calculation is DGS10 - DGS2 — negative values mean inversion. Every US recession since 1970 has been preceded by a yield curve inversion, typically 12-18 months before the recession starts. This is not a market prediction; it is a mechanical consequence of the bond market repricing future growth expectations.

TIPS: Inflation Protection With Nuance

Treasury Inflation-Protected Securities (TIPS) adjust their principal based on CPI. If inflation runs at 3%, your TIPS principal increases by 3%, and the coupon (paid on the adjusted principal) increases proportionally. This sounds like a free lunch — protection against inflation with government backing.

The catch: TIPS have lower nominal yields than nominal Treasuries of the same maturity. The difference between the nominal Treasury yield and the TIPS yield is the “breakeven inflation rate” — the inflation rate at which the two bonds deliver equal returns. If actual inflation exceeds the breakeven, TIPS outperform. If it comes in below, nominal Treasuries win.

As of mid-2026, the 10-year breakeven rate hovers around 2.3%. This means the market expects roughly 2.3% annual inflation over the next decade. If you think inflation will average higher than that, TIPS are cheap. If you think the Fed will crush inflation below 2%, nominal bonds are the better bet. This is the kind of decision that replaces “should I buy bonds?” with an actual analytical framework.

Bond ETFs vs. Individual Bonds

Developer-investors gravitate toward ETFs because they trade like stocks and require zero bond-specific knowledge. A bond ETF like AGG or BND holds hundreds of bonds and maintains a roughly constant duration. This is convenient but introduces a behavior difference that matters: individual bonds have a known maturity date when you get your principal back. Bond ETFs never mature — they constantly sell bonds approaching maturity and buy new ones to maintain their target duration.

Consequence: if you buy a 5-year Treasury bond yielding 4%, you will get your principal back in 5 years regardless of what rates do in between. If you buy a bond ETF with 5-year average duration, a rate spike in year 4 will crush its price, and there is no guaranteed date when the price recovers. The ETF’s duration stays constant; your individual bond’s duration declines as it approaches maturity.

The practical advice: if you have a known future expense (tuition in 5 years, a house down payment in 3 years), buy individual bonds matched to the date. If you are managing a retirement portfolio with no specific withdrawal date, a low-cost bond ETF is simpler and adequately diversified.

FAQ

Should I own bonds if I am under 30?
The standard advice says no — with a 30+ year time horizon, stocks historically outperform bonds and you can ride out volatility. The counterargument: the behavioral benefit of bonds (reducing portfolio drawdowns so you don't panic-sell) applies regardless of age. A 10% bond allocation reduces peak-to-trough drawdowns by more than it reduces long-term returns. The right allocation is the one you will not abandon during a 40% stock crash. For most people under 30, that is somewhere between 0% and 20% bonds.
What is the difference between Treasury bonds, corporate bonds, and municipal bonds?
Treasuries: issued by the US government, considered default-free, interest is exempt from state and local taxes. Corporates: issued by companies, higher yield to compensate for default risk, rated by agencies (AAA to D). Municipals: issued by states and cities, interest is exempt from federal taxes and sometimes state taxes if you live in the issuing state. For taxable accounts in high tax brackets, munis often deliver higher after-tax yields than Treasuries of comparable maturity.
How do I buy individual Treasury bonds?
TreasuryDirect.gov lets you buy directly from the government at auction with no fees. Most brokerages (Fidelity, Schwab, Vanguard, IBKR) also offer Treasury auctions and secondary market trading with no commission. For individual bonds, the secondary market is preferable to auctions because you know your exact yield before buying; at auction, the yield is determined by competitive bidding and you won't know it until after your order is filled.
What happens to bonds during a recession?
It depends on what kind of recession and what kind of bonds. In a typical recession where the Fed cuts rates to stimulate the economy, Treasury bonds rally because existing bonds with higher coupons become more valuable. Corporate bonds are trickier — rate cuts help, but rising default risk hurts. In the 2008 recession, Treasuries gained 20% while corporate bonds lost 5-10%. The 2020 COVID recession saw both rally because the Fed backstopped corporate credit markets. There is no single bond-market recession playbook.
Can I implement a bond ladder in code?
Yes. A bond ladder means buying bonds that mature in consecutive years — e.g., one bond maturing each year from 2027 to 2036. When each bond matures, you reinvest the principal in a new 10-year bond at the far end of the ladder. This smooths interest rate risk and provides predictable cash flows. In Python, track maturity dates, current yields, and the reinvestment schedule. The logic is simpler than a stock portfolio tracker because bond cash flows are deterministic — the only unknown is the future reinvestment rate.

Related reading

See all Finance articles →

Get the best tools, weekly

One email every Friday. No spam, unsubscribe anytime.