US Macroeconomic Data Explorer | REPLACEMETITLE

US Treasury Interest Rates / Yield Curve Data


A look at the US Treasury yield curve, according to interest rates published by the US Treasury.

In [1]:
import pandas as pd
import altair as alt
import numpy as np
In [2]:
url = 'https://home.treasury.gov/resource-center/data-chart-center/interest-rates/TextView?type=daily_treasury_yield_curve&field_tdr_date_value={year}'
#url = 'https://www.treasury.gov/resource-center/data-chart-center/interest-rates/pages/TextView.aspx?data=yieldYear&year={year}'

def fetchRates(year):
    df = pd.read_html(url.format(year=year), skiprows=0, attrs={ "class": "views-table" })[0]

    df['Date'] = pd.to_datetime(df.Date)
    
    return df.set_index('Date').resample('1m').last().reset_index()

fetchTsRates = lambda years: pd.concat(map(fetchRates, years))

#fetchRates(2019).head()

How did past interest rates look (by instrument)?

In [3]:
years = range(2017, 2023)
fields = ['Date', '3 Mo', '1 Yr', '2 Yr', '7 Yr', '10 Yr']

dfm = fetchTsRates(years)[fields].melt(id_vars='Date', var_name='Maturity')

alt.Chart(dfm).mark_line().encode(
    alt.X('Date:T', axis=alt.Axis(title='')),
    alt.Y('value:Q',
          axis=alt.Axis(title='Interest Rate [%]'),
          scale=alt.Scale(domain=[np.floor(dfm['value'].apply(float).min()), np.ceil(dfm['value'].apply(float).max())])),
    alt.Color('Maturity:N', sort=fields[1:]),
    tooltip=[alt.Tooltip('Date:T', format='%b %Y'), alt.Tooltip('Maturity:N'), alt.Tooltip('value:Q')]
).properties(
    title='U.S. Treasury Yields from {y1} to {y2}'.format(y1=min(years), y2=max(years)),
    height=450,
    width=700,
    background='white'
)
Out[3]:

Same chart as above, just a different mix of instruments

In [4]:
years = range(2016, 2023)
fields = ['Date', '6 Mo', '2 Yr', '3 Yr', '10 Yr', '30 Yr']

dfm = fetchTsRates(years)[fields].melt(id_vars='Date', var_name='Maturity')

c = alt.Chart(dfm).mark_line().encode(
    alt.X('Date:T', axis=alt.Axis(title='')),
    alt.Y('value:Q',
          axis=alt.Axis(title='Interest Rate [%]'),
          scale=alt.Scale(domain=[np.floor(dfm['value'].apply(float).min()), np.ceil(dfm['value'].apply(float).max())])),
    alt.Color('Maturity:N', sort=fields[1:]),
    tooltip=[alt.Tooltip('Date:T', format='%b %Y'), alt.Tooltip('Maturity:N'), alt.Tooltip('value:Q')]
).properties(
    title='U.S. Treasury Yields from {y1} to {y2}'.format(y1=min(years), y2=max(years)),
    height=450,
    width=700,
    background='white'
)

c.save('us-treasury-rates.png')
c.display()

How did that chart look for the 4 years before 2008?

In [5]:
years = range(2004, 2010)
fields = ['Date', '6 Mo', '2 Yr', '3 Yr', '10 Yr', '30 Yr']

dfm2 = fetchTsRates(years)[fields].melt(id_vars='Date', var_name='Maturity')

alt.Chart(dfm2).mark_line().encode(
    alt.X('Date:T', axis=alt.Axis(title='', format='%b %Y')),
    alt.Y('value:Q',
          axis=alt.Axis(title='Interest Rate [%]'),
          scale=alt.Scale(domain=[np.floor(dfm2['value'].apply(float).min()), np.ceil(dfm2['value'].apply(float).max())])),
    alt.Color('Maturity:N', sort=fields[1:]),
    tooltip=[alt.Tooltip('Date:T', format='%b %Y'), alt.Tooltip('Maturity:N'), alt.Tooltip('value:Q')]
).properties(
    title='U.S. Treasury Yields from {y1} to {y2}'.format(y1=min(years), y2=max(years)),
    height=450,
    width=700,
    background='white'
)
Out[5]:
In [6]:
year = 2019

alt.Chart(fetchRates(year).melt(id_vars='Date', var_name='Maturity')).mark_line().encode(
    alt.X('Date:T', axis=alt.Axis(title='')),
    alt.Y('value:Q', axis=alt.Axis(title='Interest Rate [%]'), scale=alt.Scale(zero=False)),
    alt.Color('Maturity:N',
              sort=['1 Mo', '2 Mo', '3 Mo', '6 Mo', '1 Yr', '2 Yr', '3 Yr', '5 Yr', '7 Yr', '10 Yr', '20 Yr', '30 Yr']),
    tooltip=[alt.Tooltip('Date:T', format='%b %Y'), alt.Tooltip('Maturity:N'), alt.Tooltip('value:Q')]
).properties(
    title='U.S. Treasury Yields for {year}'.format(year=year),
    height=450,
    width=700
).interactive()
Out[6]:
In [7]:
year = 2007

alt.Chart(fetchRates(year).melt(id_vars='Date', var_name='Maturity')).mark_line().encode(
    alt.X('Date:T', axis=alt.Axis(title='')),
    alt.Y('value:Q', axis=alt.Axis(title='Interest Rate [%]'), scale=alt.Scale(zero=False)),
    alt.Color('Maturity:N',
              sort=['1 Mo', '2 Mo', '3 Mo', '6 Mo', '1 Yr', '2 Yr', '3 Yr', '5 Yr', '7 Yr', '10 Yr', '20 Yr', '30 Yr']),
    tooltip=[alt.Tooltip('Date:T', format='%b %Y'), alt.Tooltip('Maturity:N'), alt.Tooltip('value:Q')]
).properties(
    title='U.S. Treasury Yields for {year}'.format(year=year),
    height=450,
    width=700
).interactive()
Out[7]:
In [8]:
year = 1996

alt.Chart(fetchRates(year).melt(id_vars='Date', var_name='Maturity')).mark_line().encode(
    alt.X('Date:T', axis=alt.Axis(title='')),
    alt.Y('value:Q', axis=alt.Axis(title='Interest Rate [%]'), scale=alt.Scale(zero=False)),
    alt.Color('Maturity:N'),
    tooltip=[alt.Tooltip('Date:T', format='%b %Y'), alt.Tooltip('Maturity:N'), alt.Tooltip('value:Q')]
).properties(
    title='U.S. Treasury Yields for {year}'.format(year=year),
    height=450,
    width=700
).interactive()
Out[8]:

Visualizing the "yield curve" of US Treasuries

In [9]:
years = range(2004, 2009)
instruments = {
    0.25: '3 Month T-bill',
    0.5: '6 Month T-bill',
    2: '2 Year Note',
    10: '10 Year Note',
    30: '30 Year Bond'
}
fieldsToYears = {'3 Mo': 0.25, '6 Mo': 0.5, '2 Yr': 2, '10 Yr': 10, '30 Yr': 30}
fields = [i for i in fieldsToYears.keys()]

dfm2 = fetchTsRates(years)[fields + ['Date']].melt(id_vars='Date', var_name='Maturity')

dfm2["Year"] = dfm2.Date.apply(lambda v: v.year)

alt.Chart(dfm2.groupby(["Maturity", "Year"]).agg({ "value": "mean" }).reset_index()).mark_line().encode(
    alt.X('Maturity:O', axis=alt.Axis(title='Maturity', labelAngle=0), sort=fields),
    alt.Y('value:Q', axis=alt.Axis(title='Interest Rate [%]')),
    alt.Color('Year:N'),
    tooltip=[alt.Tooltip('Date:T', format='%b %Y'), alt.Tooltip('Maturity:N'), alt.Tooltip('value:Q')]
).properties(
    title='U.S. Treasury Yield comparison [{y1} to {y2}]'.format(y1=min(years), y2=max(years)),
    height=450,
    width=700
)
Out[9]:
In [10]:
years = range(2017, 2023)
instruments = {
    0.25: '3 Month T-bill',
    0.5: '6 Month T-bill',
    2: '2 Year Note',
    10: '10 Year Note',
    30: '30 Year Bond'
}
fieldsToYears = {'3 Mo': 0.25, '6 Mo': 0.5, '2 Yr': 2, '10 Yr': 10, '30 Yr': 30}
fields = [i for i in fieldsToYears.keys()]

dfm2 = fetchTsRates(years)[fields + ['Date']].melt(id_vars='Date', var_name='Maturity')

dfm2["Year"] = dfm2.Date.apply(lambda v: v.year)

alt.Chart(dfm2.groupby(["Maturity", "Year"]).agg({ "value": "mean" }).reset_index()).mark_line().encode(
    alt.X('Maturity:O', axis=alt.Axis(title='Maturity', labelAngle=0), sort=fields),
    alt.Y('value:Q', axis=alt.Axis(title='Interest Rate [%]')),
    alt.Color('Year:N'),
    tooltip=[alt.Tooltip('Date:T', format='%b %Y'), alt.Tooltip('Maturity:N'), alt.Tooltip('value:Q')]
).properties(
    title='Yearly Average U.S. Treasury Yield comparison [{y1} to {y2}]'.format(y1=min(years), y2=max(years)),
    height=450,
    width=700
)
Out[10]:

© kdunn926