Outstanding mortgage rates

Charting oustanding mortgage interest rates

On Twitter Ali Wolf asks a question:

Mortgage rates, that’s something I know a little about.

Fortunately there is some publicly available data that can answer this question. The National Mortgage Database publishes some aggregate data on outstanding mortgages.

Using a snippet of R code I picked up from Jonathan Regenstein:

we can download the data direct from the FHFA website in R and plot our data.

First we can plot the average origination interest rate on outstanding mortgages. The US average is 4% in 2021Q2.

We can also compare the distribution of outstanding rates by state.

Here’s R code for the charts.

library(geofacet)
library(tidyverse)
library(readxl)
library(lubridate)
url1 <-"https://www.fhfa.gov/DataTools/Downloads/Documents/"
url2 <- "NATIONAL-MORTGAGE-DATABASE-(NMDB)-AGGREGATE-DATA/National-State-Statistics-for-Outstanding-Residential-Mortgages-in-the-United-States-2021Q2.xlsx"
destfile <- "nmdb2021Q3.xlsx"
curl::curl_download(paste0(url1,url2),destfile)

nmdb_data <-
  read_excel(destfile,sheet=3,skip=7) %>%
  rename(geo=1,
         avg_rate=11) %>%
  select(geo,avg_rate) %>%
  mutate(id=case_when(geo=="Nationwide"~0,
                      T~avg_rate)) %>%
  mutate(geof=fct_reorder(geo,id)) 

nmdb_data$us_rate=filter(nmdb_data,geo=="Nationwide")$avg_rate


# First Chart ----#

ggplot(data=nmdb_data,
       aes(y=geof, x=avg_rate))+
  geom_segment(aes(yend=geof,xend=us_rate))+
  geom_point(shape=21, fill="dodgerblue",size=3)+
  geom_point(shape=21, fill="white",aes(x=us_rate),size=3,stroke=0.75)+
  geom_text(aes(label=geo,hjust=ifelse(avg_rate>us_rate,-0.25,1.25)),
            fontface="bold")+
  scale_x_continuous(breaks=seq(3.5,4.5,.1))+
  theme_minimal()+
  theme(legend.position="top",
        legend.key.width=unit(2,"cm"),
        plot.caption=element_text(hjust=0),
        axis.text=element_text(size=rel(2)),
        axis.text.y=element_blank(),
        panel.grid.minor.x=element_blank(),
        panel.grid.major.y=element_blank(),
        plot.background = element_rect(fill="white",color=NA),
        panel.background = element_rect(fill="white",color=NA),
        plot.subtitle=element_text(face="italic",size=rel(1.5)),
        plot.title=element_text(size=rel(2),face="bold"))+
  labs(x="",y="",
       title="Contract Interest Rate at Origination for Residential Mortgages Active as of June 30, 2021",
       subtitle="All residential first-lien mortgages in 50 States and the District of Columbia from NMDB.",
       caption="@lenkiefer | Source: FHFA, National Mortgage Database (NMDB®)")


nmdb_data2 <-
  read_excel(destfile,sheet=3,skip=7) %>%
  rename(geo=1,
         lt3=12,
         b34=13,
         b45=14,
         b56=15,
         gt6=16) %>%
  select(geo,lt3,b34,b45,b56,gt6) %>%
  pivot_longer(cols=-geo)

nmdb_data2 <- mutate(nmdb_data2,
                     rf=factor(name,levels=c("lt3","b34","b45","b56","gt6")))

# Second Chart ----#

gmap1 <- 
ggplot(data=nmdb_data2,aes(x=rf,y=value))+geom_col()+facet_geo(~geo)+
  scale_x_discrete(labels=c("<3","(3-4]", "(4-5]","(5-6]", ">6"))+
  geom_text(aes(label=value),color="white",vjust=1,fontface="bold",size=3)+
  theme_minimal()+
  theme(legend.position="top",
        legend.key.width=unit(2,"cm"),
        plot.caption=element_text(hjust=0),
        axis.text.x=element_text(size=rel(0.75)),
        panel.grid.minor.x=element_blank(),
        panel.grid.major.y=element_blank(),
        plot.background = element_rect(fill="white",color=NA),
        panel.background = element_rect(fill="white",color=NA),
        plot.subtitle=element_text(face="italic",size=rel(1.5)),
        plot.title=element_text(size=rel(2),face="bold"))+
  labs(title="Distribution of Origination Interest Rate in 2021Q2",
       x="Contract Interest Rate at Origination",
       y="Percent Share",
       subtitle="All residential first-lien mortgages in 50 States and the District of Columbia from NMDB.",
       caption="@lenkiefer | Source: FHFA, National Mortgage Database (NMDB®)")
  
gbar2<-
  ggplot(data=filter(nmdb_data2,geo=="Nationwide"),aes(x=rf,y=value))+geom_col()+
  geom_text(aes(label=value),color="white",vjust=1,fontface="bold",size=6)+
  scale_x_discrete(labels=c("<3","(3-4]", "(4-5]","(5-6]", ">6"))+
  theme_minimal()+
  theme(legend.position="top",
        legend.key.width=unit(2,"cm"),
        plot.caption=element_text(hjust=0),
        axis.text.x=element_text(size=rel(1)),
        panel.grid.minor.x=element_blank(),
        panel.grid.major.y=element_blank(),
        plot.background = element_rect(fill="white",color=NA),
        panel.background = element_rect(fill="white",color=NA),
        plot.subtitle=element_text(face="italic",size=rel(1.5)),
        plot.title=element_text(size=rel(2),face="bold"))+
  labs(title="Distribution of Origination Interest Rate in 2021Q2",
       x="Contract Interest Rate at Origination",
       y="Percent Share",
       subtitle="All residential first-lien mortgages in 50 States and the District of Columbia from NMDB.",
       caption="@lenkiefer | Source: FHFA, National Mortgage Database (NMDB®)")

gmap1/gbar2+plot_layout(heights=c(4,1))

 Share!