Predicting future recessions

Even if this sounds incredible, yes, we can predict future recessions using a couple of time series, some simple econometric models, and … R

The basic idea is that the slope of the yield curve is somewhat linked to the probability of future recessions. In other words, the difference between the short and the long term rate can be used as a tool for monitoring business cycles. Nothing new about that: Kessel (1965) documented the cyclical behavior of the yield spread, and he showed that the yield spread tended to decline immediately before a recession. This relationship is one of the most famous stylized facts among economists (see Figure 1).

Figure_1_FRED
Figure 1: The yield spread and recessions

– So, why people don’t use this model to predict recessions ?
– Well, it seems to be related to the fact that (i) they think it only used to work in the US (ii) they don’t feel to be qualified to run a sophisticated R code to estimate this relationship.

This post is about answering these two questions: (i) yes, the yield curve does signal recessions (ii) yes, it is easy to monitor economic cycles with R using the EWS package !

First, if you have some doubts about the predictive power of the yield spread, please have a look on Hasse and Lajaunie (2022)’s recent paper, published in the Quarterly Review of Economics and Finance. The authors – Quentin and I –  reexamine the predictive power of the yield spread across countries and over time. Using a dynamic panel/dichotomous model framework and a unique dataset covering 13 OECD countries over the period 1975–2019, we empirically show that the yield spread signals recessions. This result is robust to different econometric specifications, controlling for recession risk factors and time sampling. Main results are reported in Table 1.

Table_1
Table 1: Estimation of the predictive power of the yield spread (1975–2019)

– Wait, what does mean “dichotomous model” ?
– Don’t be afraid: the academic literature provides a specific econometric framework to predict future recessions.

Estrella and Hardouvelis (1991) and Kauppi and Saikkonen (2008) have enhanced the use of binary regression models (probit and logit models) to model the relationship between recession dummies (i.e., binary variables) and the yield spread (i.e., continuous variable). Indeed, classic linear regressions cannot do the job here. If you have specific issues about probit/logit models, you should have a look on Quentin’s PhD dissertation. He is a specialist in nonlinear econometrics.

Now, let’s talk about the EWS R package. In a few words, the package is available on the CRAN package repository and it includes data and code you need to replicate our empirical findings. So you only have to run a few lines of code to estimate the predictive power of the yield spread. Not so bad eh ?

Here is an example focusing on the US: first install and load the package, then we extract the data we need.
# Load the package
library(EWS)

# Load the dataset included in the package
data("data_USA") # Print the first six rows of the dataframe head(data_USA)
Well, now we just have to run these few lines:
# Data process
Var_Y <- as.vector(data_USA$NBER)
Var_X <- as.vector(data_USA$Spread)
# Estimate the logit regression
results <- Logistic_Estimation(Dicho_Y = Var_Y, Exp_X = Var_X, Intercept = TRUE, Nb_Id = 1, Lag = 1, type_model = 1)
# print results
print(results)
The results can be printed… and plotted ! Here is an illustration what you should have:

$Estimation
name Estimate Std.Error zvalue Pr
1 Intercept -1.2194364 0.3215586 -3.792268 0.0001492776
2 1 -0.5243175 0.2062655 -2.541955 0.0110234400
and then what you could plot:

Figure_2
Figure 2: The predictive power of the yield spread in the US (1999-2020)

Nice output, let’s interpret what we have. First the estimation results: the intercept is equal to -1.21 and high significant, and the lagged yield spread is equal to -0.52 and is also highly significant. This basic result illustrates the predictive power of the yield spread.

– But what does mean “1” instead of the name of the lagged variable ? And what if we choose to have another lag  ? And if we choose model 2 instead of model 1 ?
– “1” refers to the number associated to the lagged variable, and you can change the model or the number of lags via the function arguments:
$Estimation
name Estimate Std.Error zvalue Pr
1 Intercept 0.08342331 0.101228668 0.8241075 4.098785e-01
2 1 -0.32340655 0.046847136 -6.9034433 5.075718e-12
3 Index_Lag 0.85134073 0.003882198 219.2934980 0.000000e+00

Last but not least, you can choose the best model according to AIC, BIC or R2 criteria:

$AIC
[1] 164.0884
$BIC
[1] 177.8501
$R2
[1] 0.2182592

Everything you need to know about the predictive power of the yield spread is here. These in-sample estimations confirm empirical evidences from the literature for the US. And for those who are interested in out-of-sample forecasting… the EWS package provides what you need. I’ll write an another post soon !

References

Estrella, A., & Hardouvelis, G. A. (1991). The term structure as a predictor of real economic activity. The Journal of Finance46(2), 555-576.

Hasse, J. B., & Lajaunie, Q. (2022). Does the yield curve signal recessions? new evidence from an international panel data analysis. The Quarterly Review of Economics and Finance, 84, 9-22.

Hasse, J. B., & Lajaunie, Q. (2020). EWS: Early Warning System. 
R package version 0.1. 0.

Kauppi, H., & Saikkonen, P. (2008). Predicting US recessions with dynamic binary response models. The Review of Economics and Statistics90(4), 777-791.

Kessel, Reuben, A. “The Cyclical Behavior of the Term Structure of Interest Rates.” NBER Occasional Paper 91, National Bureau of Economic Research, 1965.

Monitoring systemic risk with R

Hi everyone !

This is my very first post… many researchers / students / practitioners from all over the world write to me regularly about my R package SystemicR. I’m glad to contribute to the community but questions about data management and plotting often come up. I guess that the package notice could be improved. As I receive more and more emails (which I always answer), I have to go a step further. In order to help the community in the most efficient way, I am launching a blog ! The purpose is to introduce my package proposing a tutorial. I hope you’ll find what you were looking for !

Tutorial : load, estimate and plot

First of all, you have to install and load the package SystemicR (available on CRAN so that’s the easy part) :

# Install and load SystemicR
install.packages("SystemicR")
library(SystemicR)


See ? By the way I use RStudio / R 3.6.3, please let me know in comments if you have problems with more recent versions.
Then, we have to deal with data input : (i) the data I used in my research paper entitled “Systemic Risk: a Network Approach”, or (ii) your own data. Let’s begin with my data (included in the package) :

# Data management
data("data_stock_returns")
head(data_stock_returns)
data("data_state_variables")
head(data_state_variables)


That’s it. Nothing too difficult. But things can be a bit more complicated if you choose to import your own data. First of all, you have to be very careful about the input file: please import a .txt or .csv file. This will avoid 90% of the issues you face and write to me about. Then, you have to be aware of the format of the variables that the functions can take as input. The first column is named “Date” but the variable is not a date. I used a character format when I created this dataframe. If you want to import your own data, please use the “dd/mm/yyyy” format. Furthermore, my advice would be to import the data from a .txt or .csv file, using the command :

# Import data
df_my_data <- read.table(file = "My_CSV_File", sep = ";")
df_my_data <- read.csv(file = "My_CSV_File", sep = ";")

And please be careful about sep =
Once data management is done, the remaining part of the code is straightforward. The package SystemicR is a toolbox that provides R users with useful functions to estimate and plot systemic risk measures.

Let’s begin with f_CoVaR_Delta_CoVaR_i_q(). This function computes the CoVaR and the ΔCoVaR of a given financial institution i for a given quantile q. I developed this function following each step of Adrian and Brunnermeier (2016)’s research article :

# Compute CoVaR_i_q and Delta_CoVaR_i_q
f_CoVaR_Delta_CoVaR_i_q(data_stock_returns)


Then, having estimated this static measure, let’s move on to the dynamic using f_CoVaR_Delta_CoVaR_i_q_t().Still, I developed this function following each step of Adrian and Brunnermeier (2016)’s research article :

# Compute CoVaR_i_q_t , Delta_CoVaR_i_q_t and Delta_CoVaR_t
l_result <- f_CoVaR_Delta_CoVaR_i_q_t(data_stock_returns, data_state_variables)


Of course, other systemic risk measures can be estimated. Following Billio et al. (2012), the function f_correlation_network_measures() estimates degree, closeness centrality, eigenvector centrality. This function also estimates SR and volatility as in Hasse (2020):

# Compute topological risk measures from correlation-based financial networks
l_result <- f_correlation_network_measures(data_stock_returns)

Last but not least, we shall now plot the evolution of one of the systemic risk measure using the function f_plot() :

# Plot Delta_CoVaR_t and SR_t
f_plot(l_result$Delta_CoVaR_t)
f_plot(l_result$SR)


And that’s it! Before the end of the year, I will do my best to propose a new version of this package, including updated data and other systemic risk measure. Any suggestions are welcome and you can contact me if needed. Last, please do not hesitate to share your thoughts or questions above !

References

Adrian, Tobias, and Markus K. Brunnermeier. “CoVaR”. American Economic Review 106.7 (2016): , 106, 7, 1705-1741.

Billio, M., Getmansky, M., Lo, A. W., & Pelizzon, L. (2012). Econometric measures of connectedness and systemic risk in the finance and insurance sectors. Journal of Financial Economics, 104(3), 535-559.

Hasse, Jean-Baptiste. “Systemic Risk: a Network Approach”. AMSE Working Paper (2020)