library(pacman); p_load(ggplot2, ggthemr, tidyr, dplyr, ggpubr)
data <- data.frame(
Flat = rep(.10, 101),
Rate = seq(0, 1, .01))
data$RealRateNom <- ((1 + data$Rate)/(1 + data$Flat)) - 1 #Constant inflation rate
data$AppRateNom <- data$Rate - data$Flat
data$NomRateGap <- data$RealRateNom - data$AppRateNom
data$InfRealRate <- ((1 + data$Flat)/(1 + data$Rate)) - 1 #Constant nominal rate
data$InfAppRate <- data$Flat - data$Rate
data$InfRateGap <- data$InfRealRate - data$InfAppRate
The real interest rate is given by the formula
\[\frac{1 + \text{Nominal Interest Rate}}{1 + \text{Inflation Rate}} - 1\]
but most students only take introductory economics classes, and they tend to learn that the real interest rate is given by
\[\text{Nominal Interest Rate} - \text{Inflation Rate}\]
These obviously diverge, but how bad is the approximation? The plot below varies the nominal and the inflation rates to show how the two equations diverge.
ggthemr("dust")
ConsNom2 <- ggplot(data, aes(x = Rate, y = RealRateNom)) +
geom_point() +
geom_point(aes(y = AppRateNom), color = "steelblue") +
labs(
x = NULL,
y = "Real Rate",
title = "How bad is the real interest rate approximation as a function of the nominal rate?",
caption = "Blue = Approximation, Red = Correct") +
theme(
plot.title = element_text(hjust = .5),
plot.caption = element_text(hjust = .5)) +
scale_x_continuous(labels = scales::percent) +
scale_y_continuous(labels = scales::percent)
ConsNom1 <- ggplot(data, aes(x = Rate, y = NomRateGap)) +
geom_point() +
labs(
x = "Nominal Rate",
y = "Gap between Equation and Approximation",
caption = "Inflation rate = 10%") +
theme(
plot.title = element_text(hjust = .5),
plot.caption = element_text(hjust = .5)) +
scale_x_continuous(labels = scales::percent) +
scale_y_continuous(labels = scales::percent)
ggarrange(ConsNom2, ConsNom1,
nrow = 2,
ncol = 1)
ConsInf2 <- ggplot(data, aes(x = Rate, y = InfRealRate)) +
geom_point() +
geom_point(aes(y = InfAppRate), color = "steelblue") +
labs(
x = NULL,
y = "Real Rate",
title = "How bad is the real interest rate approximation as a function of the inflation rate?",
caption = "Blue = Approximation, Red = Correct") +
theme(
plot.title = element_text(hjust = .5),
plot.caption = element_text(hjust = .5)) +
scale_x_continuous(labels = scales::percent) +
scale_y_continuous(labels = scales::percent)
ConsInf1 <- ggplot(data, aes(x = Rate, y = InfRateGap)) +
geom_point() +
labs(
x = "Inflation Rate",
y = "Gap between Equation and Approximation",
caption = "Nominal rate = 10%") +
theme(
plot.title = element_text(hjust = .5),
plot.caption = element_text(hjust = .5)) +
scale_x_continuous(labels = scales::percent) +
scale_y_continuous(labels = scales::percent)
ggarrange(ConsInf2, ConsInf1,
nrow = 2,
ncol = 1)
QuadPlot <- ggarrange(ConsNom2, ConsInf2,
ConsNom1, ConsInf1,
nrow = 2,
ncol = 2)
annotate_figure(QuadPlot,
top = text_grob("How bad is the real interest rate approximation?",
color = "#5b4f4c", face = "bold", size = 18),
bottom = text_grob("Blue = Approximation, Red = Correct",
color = "#5b4f4c", size = 12))
The econ 101 formula for the real rate would lead to severe misunderstandings about countries like Argentina and Zimbabwe where inflation is high, but it leads to quantitatively more minor misunderstandings when inflation is constant and nominal rates differ at the same scale.
sessionInfo()
## R version 4.2.2 (2022-10-31 ucrt)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 19045)
##
## Matrix products: default
##
## locale:
## [1] LC_COLLATE=English_United States.utf8
## [2] LC_CTYPE=English_United States.utf8
## [3] LC_MONETARY=English_United States.utf8
## [4] LC_NUMERIC=C
## [5] LC_TIME=English_United States.utf8
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] ggpubr_0.6.0 dplyr_1.1.0 tidyr_1.3.0 ggthemr_1.1.0 ggplot2_3.4.1
## [6] pacman_0.5.1
##
## loaded via a namespace (and not attached):
## [1] highr_0.10 bslib_0.4.2 compiler_4.2.2 pillar_1.8.1
## [5] jquerylib_0.1.4 tools_4.2.2 digest_0.6.31 jsonlite_1.8.4
## [9] evaluate_0.20 lifecycle_1.0.3 tibble_3.1.8 gtable_0.3.1
## [13] pkgconfig_2.0.3 rlang_1.0.6 cli_3.6.0 rstudioapi_0.14
## [17] yaml_2.3.7 xfun_0.37 fastmap_1.1.0 gridExtra_2.3
## [21] withr_2.5.0 knitr_1.42 generics_0.1.3 vctrs_0.5.2
## [25] sass_0.4.5 cowplot_1.1.1 grid_4.2.2 tidyselect_1.2.0
## [29] glue_1.6.2 R6_2.5.1 rstatix_0.7.2 fansi_1.0.4
## [33] rmarkdown_2.20 carData_3.0-5 farver_2.1.1 car_3.1-1
## [37] purrr_1.0.1 magrittr_2.0.3 backports_1.4.1 scales_1.2.1
## [41] htmltools_0.5.4 abind_1.4-5 colorspace_2.1-0 ggsignif_0.6.4
## [45] labeling_0.4.2 utf8_1.2.3 munsell_0.5.0 broom_1.0.3
## [49] cachem_1.0.6