Skip to content

Instantly share code, notes, and snippets.

@alastairparagas
Last active September 16, 2022 15:06
Show Gist options
  • Save alastairparagas/d5e30d64252ff9e49bc4e77308c4f3b5 to your computer and use it in GitHub Desktop.
Save alastairparagas/d5e30d64252ff9e49bc4e77308c4f3b5 to your computer and use it in GitHub Desktop.
Treasury, TIPS and I-bonds: Playing with bonds
import numpy as np
import matplotlib.pyplot as plt
np.seterr(all="ignore")
import matplotlib.ticker as ticker
import numpy_financial
# Treasury, TIPS and I-bonds - these are all bonds, which allows you to lend
# a $ amount (principal) to the US government. The US government promises to pay
# you back in time (years).
# They also give you interest payments every so often to compensate you for
# lending the US government money. Every year, this $ in interest payment profit
# amounts to principal*coupon rate.
# The government in turn uses investors paying for bonds, to fund projects like
# build infrastructure and grow the US economy by allocating capital to industries
# that may not be as profitable but the government has an incentive
# to direct American society to. For ex: renewable energy, state-side semiconductor
# manufacturing, etc (industries where companies have relatively small profit
# margins, but the US government wants to keep them afloat until they mature)
# In turn, US taxpayers are the ones essentially paying the principal + coupons
# (interest payments) owed to investors, who lent money to the US government.
def calculate_tbond_return(years, principal, coupon_rate):
return numpy_financial.fv(0, np.arange(years+1), -1*principal*coupon_rate, -1*principal)
def calculate_ibond_return(years, principal, inflation):
return numpy_financial.fv(inflation, np.arange(years+1), 0, -1*principal)
def calculate_tips_return(years, principal, coupon_rate, inflation):
# TIPS guarantees principal/par stays constant - even in deflation
inflation = max(inflation, 0)
tips_bond_principal = numpy_financial.fv(inflation, np.arange(years+1), 0, -1*principal)
tips_bond_coupons = tips_bond_principal * coupon_rate
return tips_bond_principal + tips_bond_coupons
# These calculations assume you hold to maturity (you don't sell for the duration
# of the bond, which is 10 years in this example)
principal = 1000
# Treasury bonds selling at discount - $97.25~ for $100 of debt, repayment in 10 years
# In essence, you are lending the US government $100 using only $97.25.
# In 10 years, they will pay you back the $100.
# To add, they will make annual fixed interest payments of 1.0282% of $100 (aka coupon rate)
# or roughly $1.02 a year, to compensate you lending out $100 to them.
tbond_initial_value = principal*1.0282
# TIPS selling at premium - $111.18~ for $100 of debt, repayment in 10 years
# In essence, you are lending the US government $100 for $111.18!
# In 10 years, they will pay you back $100 OR the inflation adjusted equivalent of $100 in
# 10 years - whichever is higher - your $100 will grow to match inflation!
# To add, they will make annual fixed interest payments of 0.125% of $100 (aka coupon rate)
# or roughly $0.125 a year, to compensate you lending out $100 to them
tips_initial_value = principal*0.8994
# In the real world, the "yield" of a Treasury or TIPS bond combines the coupon rate
# and the premium/discount pricing of bonds. The difference in yield between the
# 10-year Treasury bond and the TIPS bond is the CURRENT (for the given day)
# market's estimate for the average annual inflation for the next 10 years.
# Currently (Sept 12 2022), 10 year Treasury yield is at 3.343% and 10 year TIPS yield
# is at 0.942%. As such market is assuming a 10 year average inflation rate of 2.401%.
# If 10 years into the future, the average inflation is above 2.401%, investing
# into TIPS would have made more money. If the average inflation is below 2.401%,
# investing into a 10-year Treasury would have made more money.
# US government bond yields also bleed into the stock market. The higher yields
# go, the more investors are likely to choose investing a "safe" US government
# bond over stocks (less risk, more assured profit). The lower bond yields go, the
# more investors are likely to choose investing into stocks (as there are not much
# profit to be made from bonds, investors flock to riskier assets)
# In the real world, when interest rates go up, companies find it harder to
# borrow money. Companies that depend on borrowing money to grow and increase their
# net profit (growth companies) will typically see their valuations (stock price)
# re-adjusted by the market. Mature companies that depend less on borrowed money
# (but may also not have the capability to increase net profits), see more stable
# valuations (stock price) as they can better weather the environment.
# 10-year Treasury coupon rate of 1.125%
treasury_bond = calculate_tbond_return(
years=10, principal=tbond_initial_value, coupon_rate=0.0125
)
# 10-year TIPS coupon rate of 0.125%
# TIPS 1% annual deflation, TIPS guarantees principal never dips even with deflation if held to maturity
tips_bond_1pctdeflation = calculate_tips_return(
years=10, principal=tips_initial_value, coupon_rate=0.00125,
inflation=-0.01
)
# TIPS 1% annual inflation
tips_bond_1pctinflation = calculate_tips_return(
years=10, principal=tips_initial_value, coupon_rate=0.00125,
inflation=0.01
)
# TIPS 2% annual inflation
tips_bond_2pctinflation = calculate_tips_return(
years=10, principal=tips_initial_value, coupon_rate=0.00125,
inflation=0.02
)
# TIPS 4% annual inflation
tips_bond_4pctinflation = calculate_tips_return(
years=10, principal=tips_initial_value, coupon_rate=0.00125,
inflation=0.04
)
# I-bond, 4% annual inflation
ibond_4pctinflation = calculate_ibond_return(
years=10, principal=principal,
inflation=0.04
)
fig3, fig3_ax1 = plt.subplots()
fig3_ax1.plot(treasury_bond, label='Treasury Bond')
fig3_ax1.plot(tips_bond_1pctdeflation, label='TIPS, 1% deflation')
fig3_ax1.plot(tips_bond_1pctinflation, label='TIPS, 1% inflation')
fig3_ax1.plot(tips_bond_2pctinflation, label='TIPS, 2% inflation')
fig3_ax1.plot(tips_bond_4pctinflation, label='TIPS, 4% inflation')
fig3_ax1.plot(ibond_4pctinflation, label='I-bond, 4% inflation')
fig3_ax1.set_xlabel('Years')
fig3_ax1.set_ylabel('Total Return, $')
fig3_ax1.set_title('10-year Treasury Bonds vs TIPS, Bought at $1k \n(TIPS at premium, Treasury at discount), Held to Maturity')
fig3_ax1.legend()
fig3_ax1.yaxis.set_major_formatter(ticker.FormatStrFormatter('$%.0f'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment