A look at consumer credit card rates, according to the US Federal Reserve.
import pandas as pd
import altair as alt
import numpy as np
import re
df_cc = pd.read_html("https://www.federalreserve.gov/releases/g19/HIST/cc_hist_tc_levels.html")[0]
df_cc = df_cc.droplevel(0, axis=1)
df_cc['dt'] = df_cc['Date'].map(lambda v: pd.to_datetime(v.replace(" ", "-")) + pd.DateOffset(months=3))
#df_cc.head()
alt.Chart(df_cc).mark_line().encode(
alt.X('dt:T', axis=alt.Axis(title="")),
alt.Y('All creditcard amounts 1:Q', axis=alt.Axis(title="Interest Rate [%]"))
).properties(
title='Average Consumer Credit Card Rate',
width=750,
height=400
)
from os import environ
try:
# for local execution
apiKeyFromFile = open("/Users/kyledunn/fredApiKey.txt", "r").read().strip()
except FileNotFoundError:
apiKeyFromFile = None
pass
# for CI
apiKey = environ.get("FRED_API_KEY", apiKeyFromFile)
from io import BytesIO
from zipfile import ZipFile
from urllib.request import urlopen
def getSeries(series="", description=None, apiKey=apiKey):
"""
Fetch a data series from the St. Louis FED system (FRED)
and return it as a Pandas dataframe indexed by date
"""
baseUrl = "https://api.stlouisfed.org"
endpoint = "/fred/series/observations?series_id={s}&realtime_end=9999-12-31&api_key={k}&file_type=txt"
response = urlopen(baseUrl + endpoint.format(s=series, k=apiKey))
zipfile = ZipFile(BytesIO(response.read()))
filesInZip = zipfile.namelist()
data = zipfile.open(filesInZip[1])
if description is None:
description = series
df = pd.read_csv(data, sep="\t", header=None, skiprows=1,
names=["date", description, "rt_start", "rt_end"], na_values=".")
df['date'] = pd.to_datetime(df.date)
return df.set_index("date")
df_ff = getSeries('FEDFUNDS', 'prime')
df_m = df_cc.set_index('dt')['All creditcard amounts 1'].reset_index()\
.merge(df_ff.reset_index()[['date', 'prime']], left_on='dt', right_on='date')
df_m['decade'] = df_m['dt'].apply(lambda v: str(v.year)[:-1] + "0's")
hist = alt.Chart(df_m).mark_line(strokeDash=[4], strokeJoin='round').encode(
alt.X('prime:Q', sort=df_m.sort_values('dt')['All creditcard amounts 1'].unique().tolist()),
alt.Y('All creditcard amounts 1:Q', scale=alt.Scale(zero=False)),
alt.Color('decade:N', scale=alt.Scale(range=["purple", "#ff0000", "teal", "blue"]))
)
now = alt.Chart(df_m[df_m['dt'].isin([pd.to_datetime('2019-10-01')])]).mark_point(color='black').encode(
alt.X('prime:Q', axis=alt.Axis(title='Fed Funds Rate [%]')),
alt.Y('All creditcard amounts 1:Q', axis=alt.Axis(title='Average Rate [%]'))
)
nowText = now.mark_text(dy=-15).encode(
alt.Text('dt')
)
oh_eight = alt.Chart(df_m[df_m['dt'].isin([pd.to_datetime('2007-10-01')])]).mark_point(color='black').encode(
alt.X('prime:Q'),
alt.Y('All creditcard amounts 1:Q')
)
oh_eightText = oh_eight.mark_text(dy=-15, dx=-5).encode(
alt.Text('dt')
)
oh_eightPost = alt.Chart(df_m[df_m['dt'].isin([pd.to_datetime('2008-10-01')])]).mark_point(color='black').encode(
alt.X('prime:Q'),
alt.Y('All creditcard amounts 1:Q')
)
oh_eightPostText = oh_eightPost.mark_text(dy=15).encode(
alt.Text('dt')
)
dotcom = alt.Chart(df_m[df_m['dt'].isin([pd.to_datetime('2000-10-01')])]).mark_point(color='black').encode(
alt.X('prime:Q'),
alt.Y('All creditcard amounts 1:Q')
)
dotcomtText = dotcom.mark_text(dy=-15).encode(
alt.Text('dt')
)
dotcomPost = alt.Chart(df_m[df_m['dt'].isin([pd.to_datetime('2003-10-01')])]).mark_point(color='black').encode(
alt.X('prime:Q'),
alt.Y('All creditcard amounts 1:Q')
)
dotcomtPostText = dotcomPost.mark_text(dy=25, dx=-10).encode(
alt.Text('dt')
)
c = (hist + now + nowText\
+ oh_eight + oh_eightText + oh_eightPost + oh_eightPostText\
+ dotcom + dotcomtText + dotcomPost + dotcomtPostText).properties(
title='Path of historical credit card rates according to the Fed Funds Rate',
width=750,
height=400,
background='white'
)
c.save('creditcards.png')
c.display()