7 min read

Top Banks and the Banking Crash

Introduction

With the recent news of major bank collapses it seems like a good time to investigate the performance of US banks. We will start by examining data from the Federal Reserve and then take a look at stock performance where applicable.

The most recent US bank collapses are from Silicon Valley Bank (SVB) ranked 16th in our data and Signature Bank ranked 29th. We will be certain to examine their stock values leading up to their collapse.

As is standard with my R projects we will load the relevant R packages.

library(here)
library(readODS)
library(quantmod)
library(magrittr)
library(plotly)

We will go ahead and load up the Federal reserve banking data now and get the stock data later.

fp <- here("csv", "banks", "large_commercial_banks20221231.ods")

if (!file.exists(here::here("csv", "banks", "lcb_temp.RData")))
{
    banks <- readODS::read_ods(fp)
    save(banks, file = here::here("csv", "banks", "lcb_temp.RData"))
} else {
    load(here::here("csv", "banks", "lcb_temp.RData"))
}

Bank Dataset

Let’s get some statistics about these banks. Note that according to the data source these are “insured U.S.-chartered commercial banks that have consolidated assets of $300 million or more.” Let’s take a look at the data structure below.

str(banks)
## 'data.frame':	2135 obs. of  12 variables:
##  $ Bank Name / Holding Co Name: chr  "JPMORGAN CHASE BK NA/JPMORGAN CHASE & CO" "BANK OF AMER NA/BANK OF AMER CORP" "CITIBANK NA/CITIGROUP" "WELLS FARGO BK NA/WELLS FARGO & CO" ...
##  $ Nat'l Rank                 : num  1 2 3 4 5 6 7 8 9 10 ...
##  $ Bank ID                    : num  852218 480228 476810 451965 504713 ...
##  $ Bank Location              : chr  "COLUMBUS, OH" "CHARLOTTE, NC" "SIOUX FALLS, SD" "SIOUX FALLS, SD" ...
##  $ Charter                    : chr  "NAT" "NAT" "NAT" "NAT" ...
##  $ Consol Assets (Mil $)      : num  3201942 2418508 1766752 1717531 585136 ...
##  $ Domestic Assets (Mil $)    : num  2480688 2291312 1069311 1693335 574872 ...
##  $ Pct Domestic Assets        : num  77 95 61 99 98 100 100 90 100 100 ...
##  $ Pct Cumulative Assets      : num  15 26 34 42 45 47 50 52 54 56 ...
##  $ Domestic Branches          : num  4791 3819 661 4670 2236 ...
##  $ Foreign Branches           : num  33 24 144 10 1 1 0 2 1 0 ...
##  $ IBF                        : chr  "Y" "Y" "Y" "Y" ...

From this we can see that we have a dataset of 2135 banks. Let’s see how much their total assets are worth as well as total assets in the US.

total_assets <- sum(banks$`Consol Assets (Mil $)`) / 1000000
us_assets <- sum(banks$`Domestic Assets (Mil $)`) / 1000000

Reporting these results in trillions of dollars we have total assets of $21.696593 trillion and US assets of $19.826428 trillion.

Let’s take a quick look at the top 30 banks and their total Assets

knitr::kable(banks[1:30, c("Bank Name / Holding Co Name", "Nat'l Rank", "Consol Assets (Mil $)", "Domestic Assets (Mil $)")])
Bank Name / Holding Co Name Nat’l Rank Consol Assets (Mil $) Domestic Assets (Mil $)
JPMORGAN CHASE BK NA/JPMORGAN CHASE & CO 1 3201942 2480688
BANK OF AMER NA/BANK OF AMER CORP 2 2418508 2291312
CITIBANK NA/CITIGROUP 3 1766752 1069311
WELLS FARGO BK NA/WELLS FARGO & CO 4 1717531 1693335
U S BK NA/U S BC 5 585136 574872
PNC BK NA/PNC FNCL SVC GROUP 6 552307 550670
TRUIST BK/TRUIST FC 7 546228 546148
GOLDMAN SACHS BK USA/GOLDMAN SACHS GROUP THE 8 486967 439365
CAPITAL ONE NA/CAPITAL ONE FC 9 453313 452784
T D BK NA/TD GRP US HOLDS LLC 10 386799 386799
BANK OF NY MELLON/BANK OF NY MELLON CORP 11 324646 236858
STATE STREET B&TC/STATE STREET CORP 12 298020 209177
CITIZENS BK NA/CITIZENS FNCL GRP 13 226402 226402
FIRST REPUBLIC BK/ 14 212639 212639
MORGAN STANLEY PRIV BK NA/MORGAN STANLEY 15 209664 209664
SILICON VALLEY BK/SVB FNCL GRP 16 209026 194514
FIFTH THIRD BK NA/FIFTH THIRD BC 17 206289 206099
MORGAN STANLEY BK NA/MORGAN STANLEY 18 201363 201363
MANUFACTURERS & TRADERS TC/M&T BK CORP 19 200263 200263
KEYBANK NA/KEYCORP 20 187590 187588
HUNTINGTON NB/HUNTINGTON BSHRS 21 182326 182326
ALLY BK/ALLY FNCL 22 181890 181890
BMO HARRIS BK NA/BMO FNCL CORP 23 176980 176980
HSBC BK USA NA/HSBC N AMER HOLDS 24 162437 162436
AMERICAN EXPRESS NB/AMERICAN EXPRESS CO 25 155378 155378
NORTHERN TC/NORTHERN TR CORP 26 154523 112890
REGIONS BK/REGIONS FC 27 154203 154203
DISCOVER BK/DISCOVER FS 28 129386 129386
SIGNATURE BK/ 29 110364 110364
FIRST-CITIZENS B&TC/FIRST CITIZENS BSHRS 30 109180 109125

So clearly these banks have a significant amount of assets. It would be interesting to see how these assets have changed over time, but we do not have that data and are more interested in looking at stock values to use as an indicator of a possible bank collapse.

Stock prices for Failing Banks

In this section we are going to look at the stock prices of the two banks which have collapsed: SVB and Signature Bank. We will also look at First Republic Bank which has been talked about as being at risk. Using the quantmod package we are able to get our data.

SIVB <- getSymbols("SIVB", src='yahoo', env=NULL, to="2023-03-28", periodicity = "monthly")
SBNY <- getSymbols("SBNY", src='yahoo', env=NULL, to="2023-03-28", periodicity = "monthly")
FRC <- getSymbols("FRC", src='yahoo', env=NULL, to="2023-03-28", periodicity = "monthly")

To graph our data using plotly we need create a function that does all the hard work for us. We will use a candlestick plot since we are using OHLC data.

# Function used to take xts symbol data and plot candlestick graph
convert_and_plot <- function (symbol, title) {
    # convert xts data to a dataframe
    df <- data.frame(Date=index(symbol), coredata(symbol))
    
    # create volume plot
    volume <- df %>% plot_ly(x=~Date, y=~df[, 6], type='bar',
                          name="Volume",
                          colors=c('#17BECF','#7F7F7F'))
    volume %<>% layout(yaxis=list(title="Volume"))
    
    # create the main candlestick plot
    main <- df %>% plot_ly(x = ~Date, type="candlestick",
                             open = ~df[, 2], close = ~df[, 5],
                             high = ~df[, 3], low = ~df[, 4])
    main %<>% layout(title = title,
                      xaxis = list(rangeslider = list(visible = FALSE)))
    
    # combine plots
    figure <- subplot(main, volume, heights=c(0.7, 0.2), nrows=2,
               shareX=TRUE, titleY=TRUE)
    
    return(figure)
}

Below we show plots for the three banks of interest.

convert_and_plot(SIVB, "Silicon Valley Bank Stock Price")
convert_and_plot(SBNY, "Signature Bank Stock Price")
convert_and_plot(FRC, "First Republic Bank Stock Price")

The common structure we can see in these plots is a sharp price decline starting around January 2022 when the Federal reserve bank started raising interest rates.

Stock Prices for Top 5 Banks

For the sake of comparison let’s take a look at the top 5 banks. Below we collect the data.

JPM <- getSymbols("JPM", src='yahoo', env=NULL, to="2023-03-28", periodicity = "monthly")
BAC <- getSymbols("BAC", src='yahoo', env=NULL, to="2023-03-28", periodicity = "monthly")
C <- getSymbols("C", src='yahoo', env=NULL, to="2023-03-28", periodicity = "monthly")
WFC <- getSymbols("WFC", src='yahoo', env=NULL, to="2023-03-28", periodicity = "monthly")
USB <- getSymbols("USB", src='yahoo', env=NULL, to="2023-03-28", periodicity = "monthly")

Now that we have the data we utilize our function to plot them out.

convert_and_plot(JPM, "JPMorgan Chase & Co Stock Price")
convert_and_plot(BAC, "Bank of America Corp Stock Price")
convert_and_plot(C, "Citigroup Inc Stock Price")
convert_and_plot(WFC, "Wells Fargo & Co Stock Price")
convert_and_plot(USB, "US Bancorp Stock Price")

The 5 top banks do not appear to be in as much trouble as the first 3 banks we looked at. Citigroup has the worst long term trend though and US Bancorp appears to have the worst reaction to the current market.

Conclusion

Based on these graphs it appears that the three weaker banks we first examined had very fast growth followed by a harsh decline. This decline was likely started due to the Federal reserve bank raising rates. It appears that in each case these banks had some slight relief before breaking down in price even further. The major banks while appearing to drop in price as well seem to have better price support. Instead of having a short relief in price the major banks appeared to have built up some price support. Essentially the larger banks appeared to enter a trading range while the weaker banks could not find support. Of course with the recent news the larger banks are once again in some possible trouble. It could take weeks or months to determine if they can continue to hold up to the current public concern.