1 Setup and Load Packages

library(dplyr)
library(knitr)
library(tidyverse)
library(lubridate)
library(kableExtra)
library(pander)

2 Directory Setup

# ============================================================================
# PATH SETUP
# ============================================================================
BASE_PATH <- "C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025"
DATA_PROC <- file.path(BASE_PATH, "01_data/processed")

# Output directories
OUTPUT_PATH <- file.path(BASE_PATH, "03_documentation/borrowing_t_stat")
TABLE_PATH <- file.path(OUTPUT_PATH, "tables")
FIG_PATH <- file.path(OUTPUT_PATH, "figures")

# Create directories if they don't exist
dir.create(TABLE_PATH, recursive = TRUE, showWarnings = FALSE)
dir.create(FIG_PATH, recursive = TRUE, showWarnings = FALSE)

cat("Output directories:\n")
## Output directories:
cat("  Tables:", TABLE_PATH, "\n")
##   Tables: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables
cat("  Figures:", FIG_PATH, "\n")
##   Figures: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/figures

3 Helper Functions

# ==============================================================================
# HELPER FUNCTIONS
# ==============================================================================

# Safe division to avoid Inf/NaN
safe_div <- function(num, denom) {
  result <- num / denom
  result[!is.finite(result)] <- NA_real_
  return(result)
}

# Format numbers with commas
fmt_num <- function(x, digits = 2) {
  formatC(x, format = "f", digits = digits, big.mark = ",")
}

# Calculate T-statistic for difference in means (Welch's t-test)
# Returns only t-statistic (for backward compatibility)
calc_tstat <- function(vals1, vals2) {
  # Remove NAs
  vals1 <- vals1[!is.na(vals1)]
  vals2 <- vals2[!is.na(vals2)]
  
  n1 <- length(vals1)
  n2 <- length(vals2)
  
  # Need at least 2 observations in each group
  if (n1 < 2 | n2 < 2) return(NA_real_)
  
  mean1 <- mean(vals1)
  mean2 <- mean(vals2)
  var1 <- var(vals1)
  var2 <- var(vals2)
  
  # Welch's t-statistic
  se <- sqrt(var1/n1 + var2/n2)
  if (se == 0 | !is.finite(se)) return(NA_real_)
  
  t_stat <- (mean1 - mean2) / se
  return(t_stat)
}

# ==============================================================================
# NEW: Calculate T-statistic with p-value and significance stars
# ==============================================================================
calc_tstat_with_stars <- function(vals1, vals2) {
  # Remove NAs
  vals1 <- vals1[!is.na(vals1)]
  vals2 <- vals2[!is.na(vals2)]
  
  n1 <- length(vals1)
  n2 <- length(vals2)
  
  # Need at least 2 observations in each group
  if (n1 < 2 | n2 < 2) {
    return(list(tstat = NA_real_, pval = NA_real_, stars = ""))
  }
  
  # Perform Welch's t-test
  test_result <- tryCatch({
    t.test(vals1, vals2, var.equal = FALSE)
  }, error = function(e) {
    return(NULL)
  })
  
  if (is.null(test_result)) {
    return(list(tstat = NA_real_, pval = NA_real_, stars = ""))
  }
  
  t_stat <- test_result$statistic
  p_val <- test_result$p.value
  
  # Determine significance stars
  stars <- ""
  if (!is.na(p_val)) {
    if (p_val < 0.01) {
      stars <- "***"
    } else if (p_val < 0.05) {
      stars <- "**"
    } else if (p_val < 0.10) {
      stars <- "*"
    }
  }
  
  return(list(tstat = as.numeric(t_stat), pval = p_val, stars = stars))
}

4 Period Definitions

# ==============================================================================
# PERIOD DEFINITIONS
# ==============================================================================

periods <- tribble(
  ~period_num, ~period_name, ~start_date, ~end_date, ~description,
  0, "Pre-BTFP",   "2023-03-01", "2023-03-10", "DW only available",
  1, "Acute",      "2023-03-13", "2023-05-01", "Peak crisis phase",
  2, "Post-Acute", "2023-05-02", "2023-10-31", "Stabilization",
  3, "Arbitrage",  "2023-11-01", "2024-01-24", "BTFP rate < IORB",
  4, "Wind-down",  "2024-01-25", "2024-03-11", "BTFP closing announced"
) %>% 
  mutate(across(c(start_date, end_date), as.Date))

# Key dates
BTFP_LAUNCH <- as.Date("2023-03-12")
BTFP_CLOSE <- as.Date("2024-03-11")
DW_DATA_END <- as.Date("2023-12-31")
BASELINE_DATE <- "2022Q4"

# Display periods
periods %>%
  kable(col.names = c("Period", "Name", "Start", "End", "Description"),
        caption = "Analysis Period Definitions") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Analysis Period Definitions
Period Name Start End Description
0 Pre-BTFP 2023-03-01 2023-03-10 DW only available
1 Acute 2023-03-13 2023-05-01 Peak crisis phase
2 Post-Acute 2023-05-02 2023-10-31 Stabilization
3 Arbitrage 2023-11-01 2024-01-24 BTFP rate < IORB
4 Wind-down 2024-01-25 2024-03-11 BTFP closing announced

5 Load Data

# ==============================================================================
# LOAD DATA
# ==============================================================================

cat("=== LOADING DATA ===\n")
## === LOADING DATA ===
call_q <- read_csv(file.path(DATA_PROC, "final_call_gsib.csv"), show_col_types = FALSE) %>%
  mutate(idrssd = as.character(idrssd))

btfp_loans_raw <- read_csv(file.path(DATA_PROC, "btfp_loan_bank_only.csv"), show_col_types = FALSE) %>%
  mutate(rssd_id = as.character(rssd_id), 
         btfp_loan_date = mdy(btfp_loan_date))

dw_loans_raw <- read_csv(file.path(DATA_PROC, "dw_loan_bank_2023.csv"), show_col_types = FALSE) %>%
  mutate(rssd_id = as.character(rssd_id), 
         dw_loan_date = ymd(dw_loan_date))

cat("Call Report:", nrow(call_q), "observations\n")
## Call Report: 75989 observations
cat("BTFP Loans:", nrow(btfp_loans_raw), "loans\n")
## BTFP Loans: 6734 loans
cat("DW Loans:", nrow(dw_loans_raw), "loans\n")
## DW Loans: 10008 loans

6 Define Exclusions

# ============================================================================
# DEFINE EXCLUDED BANKS AND GSIB IDENTIFICATION
# ============================================================================

# Identify GSIBs at baseline
gsib_banks <- call_q %>%
  filter(period == '2022Q4', gsib == 1) %>%
  pull(idrssd)

# Identify failed banks
failed_banks <- call_q %>%
  filter(period == '2022Q4', failed_bank == 1) %>%
  pull(idrssd)

# Exclude failed + GSIBs for main analysis
excluded_banks <- union(gsib_banks, failed_banks)

cat("=== EXCLUSIONS ===\n")
## === EXCLUSIONS ===
cat("G-SIBs:", length(gsib_banks), "\n")
## G-SIBs: 33
cat("Failed banks:", length(failed_banks), "\n")
## Failed banks: 8
cat("Total excluded:", length(excluded_banks), "\n")
## Total excluded: 41

7 Prepare Baseline Data (2022Q4)

cat("\n=== PREPARING BASELINE DATA (2022Q4) ===\n")
## 
## === PREPARING BASELINE DATA (2022Q4) ===
# Step 1: Filter to baseline quarter and exclude failed/GSIB banks

has_failed_bank <- "failed_bank" %in% names(call_q)
has_gsib <- "gsib" %in% names(call_q)


baseline_q <- call_q %>%
  filter(period == '2022Q4')

cat("Baseline observations (after exclusions):", nrow(baseline_q), "\n")
## Baseline observations (after exclusions): 4737
# Step 3: Calculate medians for cutoffs (BEFORE adding derived variables)
medians <- baseline_q %>%
  summarise(
    median_uninsured = median(uninsured_deposit_to_total_asset, na.rm = TRUE),
    median_mtm = median(mtm_loss_to_total_asset, na.rm = TRUE),
    q75_uninsured = quantile(uninsured_deposit_to_total_asset, 0.75, na.rm = TRUE),
    q75_mtm = quantile(mtm_loss_to_total_asset, 0.75, na.rm = TRUE)
  )

cat("Median uninsured ratio:", round(medians$median_uninsured, 2), "%\n")
## Median uninsured ratio: 21.97 %
cat("Median MTM loss ratio:", round(medians$median_mtm, 2), "%\n")
## Median MTM loss ratio: 5.26 %
cat("Q75 uninsured ratio:", round(medians$q75_uninsured, 2), "%\n")
## Q75 uninsured ratio: 30.27 %
cat("Q75 MTM loss ratio:", round(medians$q75_mtm, 2), "%\n")
## Q75 MTM loss ratio: 6.95 %
# Step 4: Add ALL derived variables to baseline
baseline_q <- baseline_q %>%
  mutate(
    # Market value adjustment: (Book Asset / MV Asset) - 1
    
    cet1_ratio = safe_div(cet1, total_asset) * 100,
    mv_asset = mm_asset,
    mv_adjustment = if_else(mv_asset == 0 | is.na(mv_asset), NA_real_, 
                            (total_asset / mv_asset) - 1),
    
    # IDCR: (MV_Asset - s*Uninsured - Insured) / Insured
    idcr_s50 = safe_div(mv_asset - 0.5 * uninsured_deposit - insured_deposit, insured_deposit),
    idcr_s100 = safe_div(mv_asset - 1.0 * uninsured_deposit - insured_deposit, insured_deposit),
    
    # Capital Insolvency: (Equity - s*Uninsured*MVAdj) / Assets
    cap_insolvency_s50 = safe_div((total_asset - total_liability) - 0.5 * uninsured_deposit * mv_adjustment, total_asset),
    cap_insolvency_s100 = safe_div((total_asset - total_liability) - 1.0 * uninsured_deposit * mv_adjustment, total_asset),
    
    # Adjusted Equity (book equity ratio - MTM loss ratio, both in %)
    adjusted_equity = book_equity_to_total_asset - mtm_loss_to_total_asset,
    adjusted_tier1 = tier1cap_to_total_asset - mtm_loss_to_total_asset,
    adjusted_cet1 = cet1_ratio - mtm_loss_to_total_asset,
    
    # MTM Insolvent dummy (adjusted equity < 0)
    mtm_insolvent = as.integer(adjusted_equity < 0),
    mtm_insolvent_tier1 = as.integer(adjusted_tier1 < 0),
    mtm_insolvent_cet1 = as.integer(adjusted_cet1 < 0),
    
    # Uninsured leverage (uninsured deposit / book equity)
    uninsured_leverage = uninsured_deposit_to_total_asset,
    liquidity_available = safe_div(cash + rerepo + fed_fund_sold, total_asset) * 100,
    
   
    
    # Run risk dummies
    # a. Solvent and Liquid (both uninsured and MTM below median)
    run_risk_1 = as.integer(
      uninsured_deposit_to_total_asset < medians$median_uninsured & 
        mtm_loss_to_total_asset < medians$median_mtm
    ),
    # b. Solvent and Illiquid
    run_risk_2 = as.integer(
      uninsured_deposit_to_total_asset > medians$median_uninsured & 
        mtm_loss_to_total_asset < medians$median_mtm
    ),
   # c. Insolvent and Liquid  
        run_risk_3 = as.integer(
      uninsured_deposit_to_total_asset < medians$median_uninsured & 
        mtm_loss_to_total_asset > medians$median_mtm
    ),
    # d. Insolvent and ILLiquid (both uninsured and MTM above median)  
        run_risk_4 = as.integer(
      uninsured_deposit_to_total_asset > medians$median_uninsured & 
        mtm_loss_to_total_asset > medians$median_mtm
    ),
    
    # IDCR insolvency dummies
    idcr_insolvent_s50 = as.integer(idcr_s50 < 0),
    idcr_insolvent_s100 = as.integer(idcr_s100 < 0),
    
    # Capital insolvency dummies
    cap_insolvent_s50 = as.integer(cap_insolvency_s50 < 0),
    cap_insolvent_s100 = as.integer(cap_insolvency_s100 < 0)
  ) %>%
  filter(
    gsib == 0 | is.na(gsib),
    failed_bank == 0 | is.na(failed_bank),
    !is.na(omo_eligible) & omo_eligible > 0
  )

cat("\nDerived variables added successfully.\n")
## 
## Derived variables added successfully.
cat("Final baseline observations:", nrow(baseline_q), "\n")
## Final baseline observations: 4292

8 Table Functions

# ==============================================================================
# TABLE FORMAT FUNCTIONS WITH T-STATISTICS AND SIGNIFICANCE STARS
# ==============================================================================

# Main function to create summary table with consistent format
# Format: Mean (Median) [T-stat]*** with N below each row
# T-stat compares each group to Non-Borrower group
# Significance: *** p<0.01, ** p<0.05, * p<0.10

create_summary_table_v2 <- function(data, group_var, group_levels = NULL, reference_group = "Non-Borrower") {
  
  # Define variable specifications
  var_specs <- tribble(
    ~var_name, ~var_label, ~is_dummy,
    "book_equity_to_total_asset", "Book Equity Ratio", FALSE,
    "loss_asset_htm_only", "MTM Loss (HTM)", FALSE,
    "mtm_loss_omo_eligible_to_total_asset", "MTM Loss (BTFP Elg.)", FALSE,
    "mtm_loss_to_total_asset", "MTM Loss (Total)", FALSE,
    "adjusted_equity", "Adjusted Equity", FALSE,
    "mtm_insolvent", "Adjusted Equity < 0", TRUE,
    "adjusted_tier1", "Adj. Tier1 Equity", FALSE,
    "mtm_insolvent_tier1", "Adj. Tier1 Equity < 0", TRUE,
    "adjusted_cet1", " Adj. Common equity tier1",FALSE, 
    "mtm_insolvent_cet1", "Adj. Common equity tier1 < 0", TRUE,
    "uninsured_leverage", "Uninsured Leverage", FALSE,
    "mtm_insolvent", "MTM Insolvent", TRUE,
    "run_risk_1", "Solvent and Liquid", TRUE,
    "run_risk_2", "Solvent and Illiquid", TRUE,
    "run_risk_3", "Insolvent and Liquid", TRUE,
    "run_risk_4", "Insolvent and Illiquid", TRUE,
    "idcr_insolvent_s50", "IDCR Insolvent (s=0.5)", TRUE,
    "idcr_insolvent_s100", "IDCR Insolvent (s=1.0)", TRUE,
    "cap_insolvent_s50", "Capital Insolvent (s=0.5)", TRUE,
    "cap_insolvent_s100", "Capital Insolvent (s=1.0)", TRUE,
    "liquidity_available", "Available Liquidity Ratio", FALSE,
    "change_uninsured_fwd_q", "Change Uninsured Deposits (Fwd Q)", FALSE,
    "change_insured_deposit_fwd_q", "Change Insured Deposits (Fwd Q)", FALSE,
    "abnormal_insured_outflow_10pct", "Abnormal Insured Outflow (10%)", TRUE,
    "abnormal_insured_outflow_5pct", "Abnormal Insured Outflow (5%)", TRUE,
    "abnormal_uninsured_outflow_10pct", "Abnormal Uninsured Outflow (10%)", TRUE,
    "abnormal_uninsured_outflow_5pct", "Abnormal Uninsured Outflow (5%)", TRUE
    
  )
  
  # Get unique groups
  if (is.null(group_levels)) {
    group_levels <- unique(data[[group_var]])
  }
  
  # Calculate N for each group
  n_by_group <- data %>%
    group_by(.data[[group_var]]) %>%
    summarise(N = n(), .groups = "drop")
  
  # Get reference group data for T-stat calculation
  ref_data <- data %>% filter(.data[[group_var]] == reference_group)
  
  # Initialize output list
  output_rows <- list()
  
  # Add N row first
  n_row <- c(Variable = "N", Row_Type = "count")
  for (g in group_levels) {
    n_val <- n_by_group %>% filter(.data[[group_var]] == g) %>% pull(N)
    n_row[g] <- as.character(if(length(n_val) == 0) 0 else n_val)
  }
  output_rows[[1]] <- n_row
  
  row_idx <- 2
  
  # Process each variable
  for (i in seq_len(nrow(var_specs))) {
    v <- var_specs$var_name[i]
    label <- var_specs$var_label[i]
    is_dummy <- var_specs$is_dummy[i]
    
    # Stats row: Mean (Median)
    stats_row <- c(Variable = label, Row_Type = "stats")
    # T-stat row (below stats)
    tstat_row <- c(Variable = "", Row_Type = "tstat")
    # N row (below t-stat)
    obs_row <- c(Variable = "", Row_Type = "n")
    
    # Get reference group values for T-stat
    ref_vals <- if (v %in% names(ref_data)) ref_data[[v]] else numeric(0)
    ref_vals <- ref_vals[!is.na(ref_vals)]
    
    for (g in group_levels) {
      group_data <- data %>% filter(.data[[group_var]] == g)
      
      # Check if variable exists
      if (!v %in% names(group_data)) {
        stats_row[g] <- "—"
        tstat_row[g] <- ""
        obs_row[g] <- "0"
        next
      }
      
      vals <- group_data[[v]]
      vals <- vals[!is.na(vals)]
      
      if (length(vals) == 0) {
        stats_row[g] <- "—"
        tstat_row[g] <- ""
        obs_row[g] <- "0"
      } else {
        mean_val <- mean(vals, na.rm = TRUE)
        median_val <- median(vals, na.rm = TRUE)
        n_val <- length(vals)
        
        if (is_dummy) {
          stats_row[g] <- sprintf("%.2f (%.2f)", mean_val * 100, median_val * 100)
          n_val <- sum(vals)  # Count of banks where dummy = 1
        } else {
          stats_row[g] <- sprintf("%.2f (%.2f)", mean_val, median_val)
          n_val <- length(vals)  # Total non-NA observations
        }
        
        # Calculate T-stat vs reference group (skip for reference group itself)
        if (g == reference_group) {
          tstat_row[g] <- ""
        } else {
          # Use the new function with stars
          tstat_result <- calc_tstat_with_stars(vals, ref_vals)
          if (!is.na(tstat_result$tstat) && is.finite(tstat_result$tstat)) {
            tstat_row[g] <- sprintf("[%.2f]%s", tstat_result$tstat, tstat_result$stars)
          } else {
            tstat_row[g] <- ""
          }
        }
        
        obs_row[g] <- as.character(n_val)
      }
    }
    
    output_rows[[row_idx]] <- stats_row
    output_rows[[row_idx + 1]] <- tstat_row
    output_rows[[row_idx + 2]] <- obs_row
    row_idx <- row_idx + 3
  }
  
  # Convert to data frame
  result_df <- bind_rows(lapply(output_rows, function(x) as_tibble_row(x)))
  
  return(result_df)
}

# ==============================================================================
# LATEX TABLE EXPORT FUNCTION (UPDATED FOR T-STATS WITH STARS)
# ==============================================================================

export_latex_table <- function(summary_df, filepath, caption, label, note = NULL) {
  
  # Get column names (excluding Variable and Row_Type)
  group_cols <- names(summary_df)[!names(summary_df) %in% c("Variable", "Row_Type")]
  n_groups <- length(group_cols)
  
  # Clean column names for display
  clean_cols <- gsub("_", " ", group_cols)
  clean_cols <- gsub("Non Borrower", "Non-Borrower", clean_cols)
  
  # Build LaTeX
  latex <- c(
    "\\begin{table}[htbp]",
    "\\centering",
    "\\small",
    sprintf("\\caption{%s}", caption),
    sprintf("\\label{%s}", label),
    "",
    sprintf("\\begin{tabular}{l%s}", paste(rep("c", n_groups), collapse = "")),
    "\\toprule",
    paste0(" & ", paste(clean_cols, collapse = " & "), " \\\\"),
    "\\midrule"
  )
  
  # Add rows
  for (i in seq_len(nrow(summary_df))) {
    row <- summary_df[i, ]
    var_name <- as.character(row$Variable)
    row_type <- as.character(row$Row_Type)
    vals <- as.character(row[group_cols])
    
    if (row_type == "count") {
      # N row - bold
      latex <- c(latex, 
                 sprintf("N & %s \\\\", paste(vals, collapse = " & ")),
                 "\\midrule")
    } else if (row_type == "stats" && var_name != "") {
      # Variable name row with statistics
      latex <- c(latex, sprintf("%s & %s \\\\", var_name, paste(vals, collapse = " & ")))
    } else if (row_type == "tstat") {
      # T-stat row (smaller font, in brackets) - stars are already included
      tstat_vals <- paste0("\\scriptsize{", vals, "}")
      latex <- c(latex, sprintf("& %s \\\\", paste(tstat_vals, collapse = " & ")))
    } else if (row_type == "n") {
      # N below stats (italics)
      n_vals <- paste0("\\textit{", vals, "}")
      latex <- c(latex, sprintf("& %s \\\\[0.3em]", paste(n_vals, collapse = " & ")))
    }
  }
  
  latex <- c(latex,
             "\\bottomrule",
             "\\end{tabular}",
             "")
  
  # Add note if provided (updated to include significance legend)
  if (!is.null(note)) {
    latex <- c(latex,
               "\\vspace{0.3em}",
               "\\begin{minipage}{0.95\\textwidth}",
               "\\footnotesize",
               sprintf("\\textit{Notes:} %s T-statistics in brackets compare each borrower group to Non-Borrowers using Welch's t-test. Significance: *** p$<$0.01, ** p$<$0.05, * p$<$0.10.", note),
               "\\end{minipage}")
  }
  
  latex <- c(latex, "\\end{table}")
  
  # Write to file
  writeLines(latex, filepath)
  cat("LaTeX table saved:", filepath, "\n")
  
  return(invisible(latex))
}

# ==============================================================================
# HTML TABLE EXPORT FUNCTION
# ==============================================================================

export_html_table <- function(summary_df, filepath, caption) {
  
  # Get column names (excluding Row_Type)
  display_cols <- names(summary_df)[names(summary_df) != "Row_Type"]
  
  # Clean column names
  clean_names <- gsub("_", " ", display_cols)
  clean_names <- gsub("Non Borrower", "Non-Borrower", clean_names)
  
  # Create display dataframe
  display_df <- summary_df %>%
    select(all_of(display_cols))
  
  # Generate HTML table
  html_table <- display_df %>%
    kable(format = "html", 
          col.names = clean_names,
          caption = caption,
          escape = FALSE) %>%
    kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                  full_width = FALSE,
                  font_size = 12) %>%
    row_spec(1, bold = TRUE)  # Bold N row
  
  # Save to file
  save_kable(html_table, filepath)
  cat("HTML table saved:", filepath, "\n")
  
  return(invisible(html_table))
}

# ==============================================================================
# COMBINED EXPORT FUNCTION
# ==============================================================================

export_table <- function(summary_df, table_name, caption, label, note = NULL) {
  
  # LaTeX export
  latex_path <- file.path(TABLE_PATH, paste0(table_name, ".tex"))
  export_latex_table(summary_df, latex_path, caption, label, note)
  

  # HTML export
  html_path <- file.path(TABLE_PATH, paste0(table_name, ".html"))
  export_html_table(summary_df, html_path, caption)
  
  # CSV export (for reference)
  csv_path <- file.path(TABLE_PATH, paste0(table_name, ".csv"))
  write_csv(summary_df, csv_path)
  cat("CSV table saved:", csv_path, "\n")
  
  return(invisible(list(latex = latex_path, html = html_path, csv = csv_path)))
}

9 Table 1: March 10, 2023 - DW Borrowers vs Non-Borrowers

# ==============================================================================
# TABLE 1: March 10, 2023 Only - DW Borrowers vs Non-Borrowers
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("TABLE 1: March 10, 2023 - DW Borrowers vs Non-Borrowers\n")
## TABLE 1: March 10, 2023 - DW Borrowers vs Non-Borrowers
cat(strrep("=", 60), "\n")
## ============================================================
dw_mar10 <- dw_loans_raw %>%
  filter(dw_loan_date == as.Date("2023-03-10")) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

cat("DW borrowers on March 10:", length(dw_mar10), "\n")
## DW borrowers on March 10: 52
table1_data <- baseline_q %>%
  mutate(
    borrower_type = if_else(idrssd %in% dw_mar10, "DW Borrower", "Non-Borrower")
  )

table1 <- create_summary_table_v2(table1_data, "borrower_type", 
                                   group_levels = c("DW Borrower", "Non-Borrower"))

# Display
table1 %>%
  select(-Row_Type) %>%
  kable(caption = "Table 1: Pre-Crisis Bank Characteristics - DW Borrowers vs Non-Borrowers (March 10, 2023)") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Table 1: Pre-Crisis Bank Characteristics - DW Borrowers vs Non-Borrowers (March 10, 2023)
Variable DW Borrower Non-Borrower
N 47 4245
Book Equity Ratio 8.20 (8.45) 10.24 (8.85)
[-4.93]***
47 4245
MTM Loss (HTM) 0.23 (0.00) 0.20 (0.00)
[0.28]
47 4235
MTM Loss (BTFP Elg.) 0.89 (0.58) 0.68 (0.40)
[1.72]*
47 4235
MTM Loss (Total) 5.69 (5.66) 5.46 (5.31)
[0.72]
47 4235
Adjusted Equity 2.51 (2.44) 4.70 (3.64)
[-3.70]***
47 4235
Adjusted Equity < 0 23.40 (0.00) 19.22 (0.00)
[0.67]
11 814
Adj. Tier1 Equity 3.67 (2.90) 6.33 (5.06)
[-6.67]***
47 4235
Adj. Tier1 Equity < 0 4.26 (0.00) 3.31 (0.00)
[0.32]
2 140
Adj. Common equity tier1 3.66 (2.90) 6.28 (5.05)
[-6.60]***
47 4179
Adj. Common equity tier1 < 0 4.26 (0.00) 3.25 (0.00)
[0.33]
2 136
Uninsured Leverage 29.88 (28.54) 23.54 (22.22)
[3.44]***
47 4245
MTM Insolvent 23.40 (0.00) 19.22 (0.00)
[0.67]
11 814
Solvent and Liquid 10.64 (0.00) 22.42 (0.00)
[-2.57]**
5 951
Solvent and Illiquid 29.79 (0.00) 26.56 (0.00)
[0.48]
14 1126
Insolvent and Liquid 19.15 (0.00) 26.55 (0.00)
[-1.27]
9 1126
Insolvent and Illiquid 40.43 (0.00) 24.30 (0.00)
[2.22]**
19 1030
IDCR Insolvent (s=0.5) 2.13 (0.00) 4.23 (0.00)
[-0.98]
1 178
IDCR Insolvent (s=1.0) 34.04 (0.00) 28.40 (0.00)
[0.80]
16 1194
Capital Insolvent (s=0.5) 4.26 (0.00) 2.17 (0.00)
[0.70]
2 92
Capital Insolvent (s=1.0) 17.02 (0.00) 7.51 (0.00)
[1.71]*
8 318
Available Liquidity Ratio 3.27 (2.25) 9.36 (5.94)
[-13.94]***
47 4245
Change Uninsured Deposits (Fwd Q) -13.11 (-11.89) 0.18 (-4.54)
[-4.14]***
47 4181
Change Insured Deposits (Fwd Q) 5.35 (2.14) 3.83 (1.48)
[0.97]
47 4187
Abnormal Insured Outflow (10%) 6.38 (0.00) 7.51 (0.00)
[-0.31]
3 319
Abnormal Insured Outflow (5%) 0.00 (0.00) 2.69 (0.00)
[-10.82]***
0 114
Abnormal Uninsured Outflow (10%) 42.55 (0.00) 21.25 (0.00)
[2.91]***
20 902
Abnormal Uninsured Outflow (5%) 25.53 (0.00) 9.07 (0.00)
[2.55]**
12 385
# Export
export_table(
  table1, 
  "table1_dw_mar10",
  caption = "Pre-Crisis Bank Characteristics: DW Borrowers vs Non-Borrowers (March 10, 2023)",
  label = "tab:dw_mar10",
  note = "Bank characteristics from 2022Q4 Call Reports. Values shown as Mean (Median) with N observations below. Continuous variables in percentage points. Dummy variables show proportion (\\%) with value = 1. DW borrowers identified as banks with Discount Window loans on March 10, 2023 only. Sample excludes G-SIBs and failed banks."
)
## LaTeX table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table1_dw_mar10.tex 
## HTML table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table1_dw_mar10.html 
## CSV table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table1_dw_mar10.csv

10 Table 2: March 10-13, 2023 - DW Borrowers vs Non-Borrowers

# ==============================================================================
# TABLE 2: March 10-13, 2023 - DW Borrowers vs Non-Borrowers
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("TABLE 2: March 10-13, 2023 - DW Borrowers vs Non-Borrowers\n")
## TABLE 2: March 10-13, 2023 - DW Borrowers vs Non-Borrowers
cat(strrep("=", 60), "\n")
## ============================================================
dw_mar10_13 <- dw_loans_raw %>%
  filter(dw_loan_date >= as.Date("2023-03-10") & dw_loan_date <= as.Date("2023-03-13")) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

cat("DW borrowers March 10-13:", length(dw_mar10_13), "\n")
## DW borrowers March 10-13: 98
table2_data <- baseline_q %>%
  mutate(
    borrower_type = if_else(idrssd %in% dw_mar10_13, "DW Borrower", "Non-Borrower")
  )

table2 <- create_summary_table_v2(table2_data, "borrower_type",
                                   group_levels = c("DW Borrower", "Non-Borrower"))

# Display
table2 %>%
  select(-Row_Type) %>%
  kable(caption = "Table 2: Pre-Crisis Bank Characteristics - DW Borrowers vs Non-Borrowers (March 10-13, 2023)") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Table 2: Pre-Crisis Bank Characteristics - DW Borrowers vs Non-Borrowers (March 10-13, 2023)
Variable DW Borrower Non-Borrower
N 90 4202
Book Equity Ratio 8.55 (8.46) 10.26 (8.85)
[-5.17]***
90 4202
MTM Loss (HTM) 0.24 (0.00) 0.20 (0.00)
[0.55]
90 4192
MTM Loss (BTFP Elg.) 0.84 (0.55) 0.68 (0.40)
[1.92]*
90 4192
MTM Loss (Total) 5.54 (5.61) 5.47 (5.31)
[0.34]
90 4192
Adjusted Equity 3.01 (2.72) 4.71 (3.64)
[-3.86]***
90 4192
Adjusted Equity < 0 20.00 (0.00) 19.25 (0.00)
[0.17]
18 807
Adj. Tier1 Equity 4.03 (3.75) 6.35 (5.07)
[-7.80]***
90 4192
Adj. Tier1 Equity < 0 3.33 (0.00) 3.32 (0.00)
[0.01]
3 139
Adj. Common equity tier1 3.99 (3.82) 6.30 (5.06)
[-7.99]***
87 4139
Adj. Common equity tier1 < 0 3.45 (0.00) 3.26 (0.00)
[0.09]
3 135
Uninsured Leverage 32.99 (30.99) 23.41 (22.12)
[6.81]***
90 4202
MTM Insolvent 20.00 (0.00) 19.25 (0.00)
[0.17]
18 807
Solvent and Liquid 10.00 (0.00) 22.56 (0.00)
[-3.87]***
9 947
Solvent and Illiquid 33.33 (0.00) 26.45 (0.00)
[1.36]
30 1110
Insolvent and Liquid 12.22 (0.00) 26.77 (0.00)
[-4.11]***
11 1124
Insolvent and Illiquid 44.44 (0.00) 24.05 (0.00)
[3.84]***
40 1009
IDCR Insolvent (s=0.5) 5.56 (0.00) 4.18 (0.00)
[0.56]
5 174
IDCR Insolvent (s=1.0) 34.44 (0.00) 28.33 (0.00)
[1.20]
31 1179
Capital Insolvent (s=0.5) 5.56 (0.00) 2.12 (0.00)
[1.41]
5 89
Capital Insolvent (s=1.0) 16.67 (0.00) 7.42 (0.00)
[2.33]**
15 311
Available Liquidity Ratio 4.30 (2.86) 9.40 (5.97)
[-10.23]***
90 4202
Change Uninsured Deposits (Fwd Q) -10.14 (-8.93) 0.25 (-4.45)
[-3.97]***
90 4138
Change Insured Deposits (Fwd Q) 8.03 (2.39) 3.76 (1.45)
[1.48]
90 4144
Abnormal Insured Outflow (10%) 5.56 (0.00) 7.54 (0.00)
[-0.81]
5 317
Abnormal Insured Outflow (5%) 1.11 (0.00) 2.69 (0.00)
[-1.39]
1 113
Abnormal Uninsured Outflow (10%) 41.11 (0.00) 21.06 (0.00)
[3.82]***
37 885
Abnormal Uninsured Outflow (5%) 22.22 (0.00) 8.97 (0.00)
[2.99]***
20 377
# Export
export_table(
  table2, 
  "table2_dw_mar10_13",
  caption = "Pre-Crisis Bank Characteristics: DW Borrowers vs Non-Borrowers (March 10--13, 2023)",
  label = "tab:dw_mar10_13",
  note = "Bank characteristics from 2022Q4 Call Reports. Values shown as Mean (Median) with N observations below. DW borrowers identified as banks with Discount Window loans between March 10--13, 2023. Sample excludes G-SIBs and failed banks."
)
## LaTeX table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table2_dw_mar10_13.tex 
## HTML table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table2_dw_mar10_13.html 
## CSV table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table2_dw_mar10_13.csv

11 Table 3: March 9-14, 2023 - DW Borrowers vs Non-Borrowers

# ==============================================================================
# TABLE 3: March 9-14, 2023 - DW Borrowers vs Non-Borrowers
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("TABLE 3: March 9-14, 2023 - DW Borrowers vs Non-Borrowers\n")
## TABLE 3: March 9-14, 2023 - DW Borrowers vs Non-Borrowers
cat(strrep("=", 60), "\n")
## ============================================================
dw_mar9_14 <- dw_loans_raw %>%
  filter(dw_loan_date >= as.Date("2023-03-09") & dw_loan_date <= as.Date("2023-03-14")) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

cat("DW borrowers March 9-14:", length(dw_mar9_14), "\n")
## DW borrowers March 9-14: 137
table3_data <- baseline_q %>%
  mutate(
    borrower_type = if_else(idrssd %in% dw_mar9_14, "DW Borrower", "Non-Borrower")
  )

table3 <- create_summary_table_v2(table3_data, "borrower_type",
                                   group_levels = c("DW Borrower", "Non-Borrower"))

# Display
table3 %>%
  select(-Row_Type) %>%
  kable(caption = "Table 3: Pre-Crisis Bank Characteristics - DW Borrowers vs Non-Borrowers (March 9-14, 2023)") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Table 3: Pre-Crisis Bank Characteristics - DW Borrowers vs Non-Borrowers (March 9-14, 2023)
Variable DW Borrower Non-Borrower
N 124 4168
Book Equity Ratio 9.01 (8.64) 10.26 (8.85)
[-3.59]***
124 4168
MTM Loss (HTM) 0.19 (0.00) 0.20 (0.00)
[-0.25]
124 4158
MTM Loss (BTFP Elg.) 0.77 (0.52) 0.68 (0.40)
[1.30]
124 4158
MTM Loss (Total) 5.50 (5.58) 5.47 (5.31)
[0.17]
124 4158
Adjusted Equity 3.51 (2.91) 4.71 (3.64)
[-2.72]***
124 4158
Adjusted Equity < 0 20.16 (0.00) 19.24 (0.00)
[0.25]
25 800
Adj. Tier1 Equity 4.58 (3.98) 6.35 (5.07)
[-5.05]***
124 4158
Adj. Tier1 Equity < 0 3.23 (0.00) 3.32 (0.00)
[-0.06]
4 138
Adj. Common equity tier1 4.56 (3.98) 6.30 (5.06)
[-4.95]***
121 4105
Adj. Common equity tier1 < 0 3.31 (0.00) 3.26 (0.00)
[0.03]
4 134
Uninsured Leverage 31.30 (29.52) 23.38 (22.08)
[6.50]***
124 4168
MTM Insolvent 20.16 (0.00) 19.24 (0.00)
[0.25]
25 800
Solvent and Liquid 11.29 (0.00) 22.62 (0.00)
[-3.87]***
14 942
Solvent and Illiquid 33.87 (0.00) 26.38 (0.00)
[1.73]*
42 1098
Insolvent and Liquid 14.52 (0.00) 26.83 (0.00)
[-3.79]***
18 1117
Insolvent and Illiquid 40.32 (0.00) 24.00 (0.00)
[3.65]***
50 999
IDCR Insolvent (s=0.5) 5.65 (0.00) 4.17 (0.00)
[0.70]
7 172
IDCR Insolvent (s=1.0) 35.48 (0.00) 28.25 (0.00)
[1.65]
44 1166
Capital Insolvent (s=0.5) 4.84 (0.00) 2.12 (0.00)
[1.40]
6 88
Capital Insolvent (s=1.0) 15.32 (0.00) 7.38 (0.00)
[2.43]**
19 307
Available Liquidity Ratio 5.31 (3.31) 9.42 (6.00)
[-7.31]***
124 4168
Change Uninsured Deposits (Fwd Q) -7.45 (-8.04) 0.26 (-4.46)
[-2.97]***
124 4104
Change Insured Deposits (Fwd Q) 7.31 (2.63) 3.74 (1.44)
[1.62]
124 4110
Abnormal Insured Outflow (10%) 6.45 (0.00) 7.53 (0.00)
[-0.48]
8 314
Abnormal Insured Outflow (5%) 2.42 (0.00) 2.66 (0.00)
[-0.17]
3 111
Abnormal Uninsured Outflow (10%) 37.10 (0.00) 21.02 (0.00)
[3.65]***
46 876
Abnormal Uninsured Outflow (5%) 18.55 (0.00) 8.97 (0.00)
[2.71]***
23 374
# Export
export_table(
  table3, 
  "table3_dw_mar9_14",
  caption = "Pre-Crisis Bank Characteristics: DW Borrowers vs Non-Borrowers (March 9--14, 2023)",
  label = "tab:dw_mar9_14",
  note = "Bank characteristics from 2022Q4 Call Reports. Values shown as Mean (Median) with N observations below. DW borrowers identified as banks with Discount Window loans between March 9--14, 2023. Sample excludes G-SIBs and failed banks."
)
## LaTeX table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table3_dw_mar9_14.tex 
## HTML table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table3_dw_mar9_14.html 
## CSV table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table3_dw_mar9_14.csv

12 Table 4: Acute Period - BTFP, DW, Both, Non-Borrowers

# ==============================================================================
# TABLE 4: Acute Period (March 13 - May 1, 2023)
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("TABLE 4: Acute Period - BTFP, DW, Both, Non-Borrowers\n")
## TABLE 4: Acute Period - BTFP, DW, Both, Non-Borrowers
cat(strrep("=", 60), "\n")
## ============================================================
acute_start <- as.Date("2023-03-13")
acute_end <- as.Date("2023-05-01")

btfp_acute <- btfp_loans_raw %>%
  filter(btfp_loan_date >= acute_start & btfp_loan_date <= acute_end) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

dw_acute <- dw_loans_raw %>%
  filter(dw_loan_date >= acute_start & dw_loan_date <= acute_end) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

cat("BTFP borrowers (Acute):", length(btfp_acute), "\n")
## BTFP borrowers (Acute): 492
cat("DW borrowers (Acute):", length(dw_acute), "\n")
## DW borrowers (Acute): 424
cat("Both:", length(intersect(btfp_acute, dw_acute)), "\n")
## Both: 103
table4_data <- baseline_q %>%
  mutate(
    btfp_user = idrssd %in% btfp_acute,
    dw_user = idrssd %in% dw_acute,
    borrower_type = case_when(
      btfp_user & dw_user ~ "Both",
      btfp_user & !dw_user ~ "BTFP Only",
      !btfp_user & dw_user ~ "DW Only",
      TRUE ~ "Non-Borrower"
    )
  )

table4 <- create_summary_table_v2(table4_data, "borrower_type",
                                   group_levels = c("BTFP Only", "DW Only", "Both", "Non-Borrower"))

# Display
table4 %>%
  select(-Row_Type) %>%
  kable(caption = "Table 4: Pre-Crisis Bank Characteristics by Borrower Type (Acute Period: March 13 - May 1, 2023)") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Table 4: Pre-Crisis Bank Characteristics by Borrower Type (Acute Period: March 13 - May 1, 2023)
Variable BTFP Only DW Only Both Non-Borrower
N 368 299 94 3531
Book Equity Ratio 8.18 (8.08) 9.05 (8.82) 8.19 (8.23) 10.59 (8.96)
[-10.58]*** [-6.25]*** [-7.48]***
368 299 94 3531
MTM Loss (HTM) 0.21 (0.00) 0.22 (0.00) 0.32 (0.00) 0.20 (0.00)
[0.37] [0.64] [1.64]
368 299 94 3521
MTM Loss (BTFP Elg.) 0.88 (0.61) 0.74 (0.48) 0.92 (0.61) 0.65 (0.38)
[4.32]*** [1.85]* [2.68]***
368 299 94 3521
MTM Loss (Total) 6.18 (6.13) 5.75 (5.67) 5.86 (5.75) 5.36 (5.18)
[7.42]*** [3.19]*** [2.60]**
368 299 94 3521
Adjusted Equity 2.00 (2.03) 3.30 (3.01) 2.33 (2.70) 5.13 (3.89)
[-11.32]*** [-6.16]*** [-6.43]***
368 299 94 3521
Adjusted Equity < 0 30.43 (0.00) 19.06 (0.00) 21.28 (0.00) 18.06 (0.00)
[4.97]*** [0.42] [0.75]
112 57 20 636
Adj. Tier1 Equity 4.13 (3.77) 4.71 (4.15) 3.76 (3.70) 6.73 (5.31)
[-11.55]*** [-8.16]*** [-9.80]***
368 299 94 3521
Adj. Tier1 Equity < 0 4.62 (0.00) 3.34 (0.00) 5.32 (0.00) 3.12 (0.00)
[1.32] [0.20] [0.94]
17 10 5 110
Adj. Common equity tier1 4.11 (3.77) 4.71 (4.19) 3.65 (3.58) 6.67 (5.29)
[-11.42]*** [-8.03]*** [-9.79]***
361 293 88 3484
Adj. Common equity tier1 < 0 4.71 (0.00) 2.73 (0.00) 5.68 (0.00) 3.10 (0.00)
[1.39] [-0.37] [1.03]
17 8 5 108
Uninsured Leverage 26.21 (25.09) 26.85 (25.28) 32.63 (30.81) 22.83 (21.44)
[5.33]*** [5.78]*** [6.67]***
368 299 94 3531
MTM Insolvent 30.43 (0.00) 19.06 (0.00) 21.28 (0.00) 18.06 (0.00)
[4.97]*** [0.42] [0.75]
112 57 20 636
Solvent and Liquid 11.41 (0.00) 11.37 (0.00) 7.45 (0.00) 24.75 (0.00)
[-7.36]*** [-6.77]*** [-6.14]***
42 34 7 873
Solvent and Illiquid 22.01 (0.00) 29.10 (0.00) 30.85 (0.00) 26.75 (0.00)
[-2.07]** [0.86] [0.85]
81 87 29 943
Insolvent and Liquid 26.09 (0.00) 24.75 (0.00) 12.77 (0.00) 27.02 (0.00)
[-0.39] [-0.87] [-4.03]***
96 74 12 953
Insolvent and Illiquid 40.49 (0.00) 34.78 (0.00) 48.94 (0.00) 21.28 (0.00)
[7.24]*** [4.75]*** [5.29]***
149 104 46 750
IDCR Insolvent (s=0.5) 3.53 (0.00) 7.02 (0.00) 3.19 (0.00) 4.07 (0.00)
[-0.53] [1.95]* [-0.47]
13 21 3 142
IDCR Insolvent (s=1.0) 29.08 (0.00) 33.11 (0.00) 24.47 (0.00) 28.11 (0.00)
[0.39] [1.77]* [-0.81]
107 99 23 981
Capital Insolvent (s=0.5) 1.63 (0.00) 3.68 (0.00) 7.45 (0.00) 1.99 (0.00)
[-0.51] [1.52] [2.00]**
6 11 7 70
Capital Insolvent (s=1.0) 9.78 (0.00) 11.71 (0.00) 11.70 (0.00) 6.93 (0.00)
[1.77]* [2.50]** [1.42]
36 35 11 244
Available Liquidity Ratio 5.15 (3.63) 6.97 (4.15) 4.97 (2.85) 10.04 (6.53)
[-15.65]*** [-6.79]*** [-8.39]***
368 299 94 3531
Change Uninsured Deposits (Fwd Q) -6.40 (-7.40) -4.28 (-5.30) -6.38 (-6.48) 1.26 (-4.09)
[-3.01]*** [-2.15]** [-2.74]***
367 299 94 3468
Change Insured Deposits (Fwd Q) 3.58 (1.54) 4.25 (2.10) 6.92 (1.90) 3.76 (1.40)
[-0.21] [0.58] [1.12]
368 299 94 3473
Abnormal Insured Outflow (10%) 11.96 (0.00) 4.68 (0.00) 5.32 (0.00) 7.34 (0.00)
[2.64]*** [-2.04]** [-0.85]
44 14 5 259
Abnormal Insured Outflow (5%) 4.35 (0.00) 1.00 (0.00) 3.19 (0.00) 2.61 (0.00)
[1.59] [-2.52]** [0.32]
16 3 3 92
Abnormal Uninsured Outflow (10%) 26.90 (0.00) 27.76 (0.00) 34.04 (0.00) 20.05 (0.00)
[2.84]*** [2.88]*** [2.82]***
99 83 32 708
Abnormal Uninsured Outflow (5%) 12.50 (0.00) 12.37 (0.00) 14.89 (0.00) 8.50 (0.00)
[2.24]** [1.97]** [1.72]*
46 37 14 300
# Export
export_table(
  table4, 
  "table4_acute_period",
  caption = "Pre-Crisis Bank Characteristics by Borrower Type: Acute Crisis Period",
  label = "tab:acute_period",
  note = "Bank characteristics from 2022Q4 Call Reports. Acute crisis period: March 13 -- May 1, 2023. Banks classified by facility usage during this period. Sample excludes G-SIBs and failed banks."
)
## LaTeX table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table4_acute_period.tex 
## HTML table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table4_acute_period.html 
## CSV table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table4_acute_period.csv

13 Table 5A: Q1 2023 - All Facilities (10% Threshold)

# ==============================================================================
# TABLE 5A: Q1 2023 (Jan 1 - Mar 31) - BTFP, DW, FHLB (10% Threshold)
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("TABLE 5A: Q1 2023 - BTFP, DW, FHLB (10%), Combinations, Non-Borrowers\n")
## TABLE 5A: Q1 2023 - BTFP, DW, FHLB (10%), Combinations, Non-Borrowers
cat(strrep("=", 60), "\n")
## ============================================================
q1_start <- as.Date("2023-01-01")
q1_end <- as.Date("2023-03-31")

btfp_q1 <- btfp_loans_raw %>%
  filter(btfp_loan_date >= q1_start & btfp_loan_date <= q1_end) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

dw_q1 <- dw_loans_raw %>%
  filter(dw_loan_date >= q1_start & dw_loan_date <= q1_end) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

# Define FHLB borrowers using 10% threshold (banks with abnormal FHLB advances in 2023Q1)
fhlb_borrowers_10pct <- baseline_q %>%
  filter(!is.na(abnormal_fhlb_borrowing_10pct) & abnormal_fhlb_borrowing_10pct > 0) %>%
  pull(idrssd)

cat("BTFP borrowers (Q1 2023):", length(btfp_q1), "\n")
## BTFP borrowers (Q1 2023): 302
cat("DW borrowers (Q1 2023):", length(dw_q1), "\n")
## DW borrowers (Q1 2023): 479
cat("FHLB borrowers (Q1 2023, 10%):", length(fhlb_borrowers_10pct), "\n")
## FHLB borrowers (Q1 2023, 10%): 302
table5a_data <- baseline_q %>%
  mutate(
    btfp_user = idrssd %in% btfp_q1,
    dw_user = idrssd %in% dw_q1,
    fhlb_user = idrssd %in% fhlb_borrowers_10pct,
    borrower_type = case_when(
      btfp_user & dw_user & fhlb_user ~ "All Three",
      btfp_user & dw_user & !fhlb_user ~ "BTFP+DW",
      btfp_user & !dw_user & fhlb_user ~ "BTFP+FHLB",
      !btfp_user & dw_user & fhlb_user ~ "DW+FHLB",
      btfp_user & !dw_user & !fhlb_user ~ "BTFP Only",
      !btfp_user & dw_user & !fhlb_user ~ "DW Only",
      !btfp_user & !dw_user & fhlb_user ~ "FHLB Only",
      TRUE ~ "Non-Borrower"
    )
  )

table5a <- create_summary_table_v2(table5a_data, "borrower_type",
                                   group_levels = c("BTFP Only", "DW Only", "FHLB Only", 
                                                    "BTFP+DW", "BTFP+FHLB", "DW+FHLB", 
                                                    "All Three", "Non-Borrower"))

# Display
table5a %>%
  select(-Row_Type) %>%
  kable(caption = "Table 5A: Pre-Crisis Bank Characteristics by Borrower Type (Q1 2023: Jan 1 - Mar 31) - 10% FHLB Threshold") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  scroll_box(width = "100%")
Table 5A: Pre-Crisis Bank Characteristics by Borrower Type (Q1 2023: Jan 1 - Mar 31) - 10% FHLB Threshold
Variable BTFP Only DW Only FHLB Only BTFP+DW BTFP+FHLB DW+FHLB All Three Non-Borrower
N 199 346 260 60 12 21 9 3385
Book Equity Ratio 8.19 (8.06) 8.85 (8.58) 9.82 (9.28) 8.01 (8.09) 8.89 (8.36) 11.00 (10.55) 9.36 (9.47) 10.55 (8.90)
[-8.78]*** [-6.62]*** [-2.78]*** [-5.75]*** [-1.80]* [0.68] [-1.75]
199 346 260 60 12 21 9 3385
MTM Loss (HTM) 0.18 (0.00) 0.24 (0.00) 0.14 (0.00) 0.38 (0.00) 0.15 (0.00) 0.12 (0.00) 0.08 (0.00) 0.20 (0.00)
[-0.55] [0.95] [-2.33]** [1.62] [-0.81] [-1.37] [-2.33]**
199 346 260 60 12 21 9 3375
MTM Loss (BTFP Elg.) 0.81 (0.53) 0.85 (0.55) 0.53 (0.28) 0.98 (0.65) 0.77 (0.87) 0.46 (0.23) 0.54 (0.34) 0.66 (0.39)
[2.61]*** [3.53]*** [-3.19]*** [2.43]** [0.75] [-1.39] [-0.80]
199 346 260 60 12 21 9 3375
MTM Loss (Total) 6.09 (6.03) 5.66 (5.64) 5.69 (5.26) 5.94 (5.82) 6.37 (6.54) 5.13 (5.07) 6.10 (5.66) 5.38 (5.23)
[5.05]*** [2.33]** [2.13]** [2.34]** [1.96]* [-0.65] [0.79]
199 346 260 60 12 21 9 3375
Adjusted Equity 2.11 (2.08) 3.19 (2.91) 4.13 (4.12) 2.06 (2.27) 2.52 (1.53) 5.87 (6.33) 3.26 (3.04) 5.07 (3.79)
[-8.88]*** [-6.00]*** [-2.93]*** [-5.22]*** [-1.96]* [0.94] [-1.33]
199 346 260 60 12 21 9 3375
Adjusted Equity < 0 29.65 (0.00) 19.36 (0.00) 14.23 (0.00) 28.33 (0.00) 33.33 (0.00) 4.76 (0.00) 33.33 (0.00) 18.87 (0.00)
[3.25]*** [0.22] [-2.04]** [1.60] [1.02] [-2.93]*** [0.87]
59 67 37 17 4 1 3 637
Adj. Tier1 Equity 4.16 (3.82) 4.72 (4.21) 5.32 (5.01) 3.63 (3.28) 4.13 (3.49) 5.61 (5.57) 3.31 (4.04) 6.73 (5.24)
[-9.62]*** [-7.55]*** [-5.29]*** [-7.48]*** [-3.69]*** [-1.70] [-3.27]**
199 346 260 60 12 21 9 3375
Adj. Tier1 Equity < 0 4.52 (0.00) 4.62 (0.00) 5.00 (0.00) 6.67 (0.00) 0.00 (0.00) 0.00 (0.00) 22.22 (0.00) 2.90 (0.00)
[1.08] [1.47] [1.51] [1.15] [-10.04]*** [-10.04]*** [1.31]
9 16 13 4 0 0 2 98
Adj. Common equity tier1 4.13 (3.82) 4.80 (4.26) 5.31 (5.01) 3.54 (3.18) 3.83 (3.21) 5.61 (5.57) 3.31 (4.04) 6.66 (5.21)
[-9.41]*** [-6.99]*** [-5.06]*** [-7.28]*** [-4.06]*** [-1.59] [-3.20]**
193 333 258 57 11 21 9 3344
Adj. Common equity tier1 < 0 4.66 (0.00) 3.30 (0.00) 5.04 (0.00) 7.02 (0.00) 0.00 (0.00) 0.00 (0.00) 22.22 (0.00) 2.96 (0.00)
[1.10] [0.33] [1.49] [1.18] [-10.10]*** [-10.10]*** [1.31]
9 11 13 4 0 0 2 99
Uninsured Leverage 26.66 (24.86) 27.17 (25.28) 23.71 (22.82) 32.21 (29.91) 31.75 (28.72) 30.18 (30.05) 28.58 (31.00) 22.82 (21.42)
[4.82]*** [6.27]*** [1.26] [5.13]*** [2.73]** [2.62]** [1.26]
199 346 260 60 12 21 9 3385
MTM Insolvent 29.65 (0.00) 19.36 (0.00) 14.23 (0.00) 28.33 (0.00) 33.33 (0.00) 4.76 (0.00) 33.33 (0.00) 18.87 (0.00)
[3.25]*** [0.22] [-2.04]** [1.60] [1.02] [-2.93]*** [0.87]
59 67 37 17 4 1 3 637
Solvent and Liquid 10.55 (0.00) 10.98 (0.00) 19.62 (0.00) 5.00 (0.00) 0.00 (0.00) 14.29 (0.00) 0.00 (0.00) 24.84 (0.00)
[-6.20]*** [-7.53]*** [-2.03]** [-6.77]*** [-33.43]*** [-1.34] [-33.43]***
21 38 51 3 0 3 0 840
Solvent and Illiquid 23.12 (0.00) 30.92 (0.00) 30.38 (0.00) 30.00 (0.00) 25.00 (0.00) 42.86 (0.00) 44.44 (0.00) 25.87 (0.00)
[-0.89] [1.95]* [1.53] [0.69] [-0.07] [1.53] [1.06]
46 107 79 18 3 9 4 874
Insolvent and Liquid 24.12 (0.00) 26.30 (0.00) 26.92 (0.00) 11.67 (0.00) 16.67 (0.00) 14.29 (0.00) 33.33 (0.00) 26.94 (0.00)
[-0.90] [-0.26] [-0.01] [-3.60]*** [-0.91] [-1.61] [0.38]
48 91 70 7 2 3 3 911
Insolvent and Illiquid 42.21 (0.00) 31.79 (0.00) 23.08 (0.00) 53.33 (100.00) 58.33 (100.00) 28.57 (0.00) 22.22 (0.00) 22.14 (0.00)
[5.60]*** [3.70]*** [0.35] [4.77]*** [2.43]** [0.64] [0.01]
84 110 60 32 7 6 2 748
IDCR Insolvent (s=0.5) 4.02 (0.00) 5.49 (0.00) 4.62 (0.00) 3.33 (0.00) 0.00 (0.00) 4.76 (0.00) 11.11 (0.00) 4.07 (0.00)
[-0.03] [1.12] [0.41] [-0.31] [-11.90]*** [0.15] [0.63]
8 19 12 2 0 1 1 136
IDCR Insolvent (s=1.0) 28.14 (0.00) 29.77 (0.00) 27.31 (0.00) 21.67 (0.00) 8.33 (0.00) 14.29 (0.00) 33.33 (0.00) 28.71 (0.00)
[-0.17] [0.41] [-0.49] [-1.30] [-2.43]** [-1.83]* [0.28]
56 103 71 13 1 3 3 960
Capital Insolvent (s=0.5) 2.01 (0.00) 2.89 (0.00) 3.08 (0.00) 6.67 (0.00) 0.00 (0.00) 4.76 (0.00) 11.11 (0.00) 1.96 (0.00)
[0.05] [1.00] [1.02] [1.45] [-8.20]*** [0.59] [0.82]
4 10 8 4 0 1 1 66
Capital Insolvent (s=1.0) 12.06 (0.00) 11.56 (0.00) 7.31 (0.00) 8.33 (0.00) 0.00 (0.00) 4.76 (0.00) 11.11 (0.00) 6.99 (0.00)
[2.15]** [2.57]** [0.19] [0.37] [-15.93]*** [-0.47] [0.37]
24 40 19 5 0 1 1 236
Available Liquidity Ratio 5.20 (3.79) 6.47 (3.75) 5.43 (4.31) 4.02 (2.59) 4.30 (3.76) 4.95 (3.49) 2.87 (2.22) 10.28 (6.70)
[-12.76]*** [-9.19]*** [-16.41]*** [-8.54]*** [-6.25]*** [-6.11]*** [-12.18]***
199 346 260 60 12 21 9 3385
Change Uninsured Deposits (Fwd Q) -6.23 (-6.25) -5.34 (-5.75) -6.08 (-7.06) -9.13 (-8.59) -10.34 (-12.20) -3.51 (-4.59) -17.22 (-12.22) 1.71 (-3.71)
[-2.96]*** [-2.67]*** [-2.85]*** [-3.76]*** [-2.43]** [-1.54] [-2.78]**
199 344 260 60 12 21 9 3323
Change Insured Deposits (Fwd Q) 3.31 (1.97) 4.62 (2.13) 1.92 (0.96) 8.70 (2.08) 6.32 (0.94) 4.53 (3.66) 9.39 (7.84) 3.84 (1.42)
[-0.56] [0.89] [-2.27]** [1.14] [0.45] [0.44] [2.14]*
199 344 260 60 12 21 9 3329
Abnormal Insured Outflow (10%) 13.57 (0.00) 4.62 (0.00) 9.62 (0.00) 8.33 (0.00) 8.33 (0.00) 0.00 (0.00) 0.00 (0.00) 7.33 (0.00)
[2.52]** [-2.22]** [1.21] [0.28] [0.12] [-16.36]*** [-16.36]***
27 16 25 5 1 0 0 248
Abnormal Insured Outflow (5%) 5.03 (0.00) 1.45 (0.00) 2.69 (0.00) 1.67 (0.00) 0.00 (0.00) 0.00 (0.00) 0.00 (0.00) 2.69 (0.00)
[1.48] [-1.78]* [0.00] [-0.60] [-9.67]*** [-9.67]*** [-9.67]***
10 5 7 1 0 0 0 91
Abnormal Uninsured Outflow (10%) 25.13 (0.00) 29.19 (0.00) 29.23 (0.00) 43.33 (0.00) 41.67 (0.00) 38.10 (0.00) 55.56 (100.00) 19.23 (0.00)
[1.87]* [3.92]*** [3.44]*** [3.72]*** [1.51] [1.73]* [2.07]*
50 101 76 26 5 8 5 651
Abnormal Uninsured Outflow (5%) 8.54 (0.00) 11.85 (0.00) 12.69 (0.00) 25.00 (0.00) 33.33 (0.00) 9.52 (0.00) 22.22 (0.00) 8.36 (0.00)
[0.09] [1.93]* [2.04]** [2.94]*** [1.76] [0.18] [0.94]
17 41 33 15 4 2 2 283
# Export
export_table(
  table5a, 
  "table5a_q1_2023_10pct",
  caption = "Pre-Crisis Bank Characteristics by Borrower Type: Q1 2023 (10\\% FHLB Threshold)",
  label = "tab:q1_2023_10pct",
  note = "Bank characteristics from 2022Q4 Call Reports. Q1 2023: January 1 -- March 31, 2023. FHLB borrowers identified as banks with abnormal FHLB advances at the 90th percentile. Sample excludes G-SIBs and failed banks."
)
## LaTeX table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table5a_q1_2023_10pct.tex 
## HTML table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table5a_q1_2023_10pct.html 
## CSV table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table5a_q1_2023_10pct.csv

14 Table 5B: Q1 2023 - All Facilities (5% Threshold)

# ==============================================================================
# TABLE 5B: Q1 2023 (Jan 1 - Mar 31) - BTFP, DW, FHLB (5% Threshold)
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("TABLE 5B: Q1 2023 - BTFP, DW, FHLB (5%), Combinations, Non-Borrowers\n")
## TABLE 5B: Q1 2023 - BTFP, DW, FHLB (5%), Combinations, Non-Borrowers
cat(strrep("=", 60), "\n")
## ============================================================
# Define FHLB borrowers using 5% threshold (banks with abnormal FHLB advances in 2023Q1)
fhlb_borrowers_5pct <- baseline_q %>%
  filter(!is.na(abnormal_fhlb_borrowing_5pct) & abnormal_fhlb_borrowing_5pct > 0) %>%
  pull(idrssd)

cat("BTFP borrowers (Q1 2023):", length(btfp_q1), "\n")
## BTFP borrowers (Q1 2023): 302
cat("DW borrowers (Q1 2023):", length(dw_q1), "\n")
## DW borrowers (Q1 2023): 479
cat("FHLB borrowers (Q1 2023, 5%):", length(fhlb_borrowers_5pct), "\n")
## FHLB borrowers (Q1 2023, 5%): 221
table5b_data <- baseline_q %>%
  mutate(
    btfp_user = idrssd %in% btfp_q1,
    dw_user = idrssd %in% dw_q1,
    fhlb_user = idrssd %in% fhlb_borrowers_5pct,
    borrower_type = case_when(
      btfp_user & dw_user & fhlb_user ~ "All Three",
      btfp_user & dw_user & !fhlb_user ~ "BTFP+DW",
      btfp_user & !dw_user & fhlb_user ~ "BTFP+FHLB",
      !btfp_user & dw_user & fhlb_user ~ "DW+FHLB",
      btfp_user & !dw_user & !fhlb_user ~ "BTFP Only",
      !btfp_user & dw_user & !fhlb_user ~ "DW Only",
      !btfp_user & !dw_user & fhlb_user ~ "FHLB Only",
      TRUE ~ "Non-Borrower"
    )
  )

table5b <- create_summary_table_v2(table5b_data, "borrower_type",
                                   group_levels = c("BTFP Only", "DW Only", "FHLB Only", 
                                                    "BTFP+DW", "BTFP+FHLB", "DW+FHLB", 
                                                    "All Three", "Non-Borrower"))

# Display
table5b %>%
  select(-Row_Type) %>%
  kable(caption = "Table 5B: Pre-Crisis Bank Characteristics by Borrower Type (Q1 2023: Jan 1 - Mar 31) - 5% FHLB Threshold") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  scroll_box(width = "100%")
Table 5B: Pre-Crisis Bank Characteristics by Borrower Type (Q1 2023: Jan 1 - Mar 31) - 5% FHLB Threshold
Variable BTFP Only DW Only FHLB Only BTFP+DW BTFP+FHLB DW+FHLB All Three Non-Borrower
N 202 352 192 64 9 15 5 3453
Book Equity Ratio 8.18 (8.04) 8.88 (8.61) 9.80 (9.36) 8.01 (7.93) 9.42 (8.67) 11.24 (10.89) 10.44 (9.62) 10.54 (8.90)
[-8.89]*** [-6.56]*** [-2.66]*** [-6.04]*** [-1.06] [0.82] [-0.11]
202 352 192 64 9 15 5 3453
MTM Loss (HTM) 0.17 (0.00) 0.24 (0.00) 0.16 (0.00) 0.36 (0.00) 0.18 (0.01) 0.17 (0.04) 0.11 (0.00) 0.20 (0.00)
[-0.55] [0.91] [-1.29] [1.53] [-0.21] [-0.42] [-1.03]
202 352 192 64 9 15 5 3443
MTM Loss (BTFP Elg.) 0.82 (0.54) 0.84 (0.53) 0.52 (0.28) 0.96 (0.65) 0.64 (0.52) 0.57 (0.37) 0.35 (0.23) 0.66 (0.38)
[2.78]*** [3.40]*** [-2.91]*** [2.47]** [-0.12] [-0.47] [-2.27]*
202 352 192 64 9 15 5 3443
MTM Loss (Total) 6.08 (6.04) 5.66 (5.64) 5.60 (5.14) 5.93 (5.78) 6.59 (6.26) 5.00 (5.07) 6.35 (6.57) 5.39 (5.23)
[4.97]*** [2.23]** [1.27] [2.35]** [2.11]* [-1.14] [0.61]
202 352 192 64 9 15 5 3443
Adjusted Equity 2.10 (2.06) 3.22 (2.92) 4.20 (4.30) 2.07 (2.39) 2.82 (1.53) 6.24 (6.33) 4.09 (3.04) 5.04 (3.79)
[-8.92]*** [-5.92]*** [-2.42]** [-5.46]*** [-1.46] [1.19] [-0.40]
202 352 192 64 9 15 5 3443
Adjusted Equity < 0 29.70 (0.00) 19.32 (0.00) 12.50 (0.00) 28.12 (0.00) 33.33 (0.00) 0.00 (0.00) 40.00 (0.00) 18.88 (0.00)
[3.29]*** [0.20] [-2.57]** [1.62] [0.87] [-28.30]*** [0.86]
60 68 24 18 3 0 2 650
Adj. Tier1 Equity 4.16 (3.81) 4.73 (4.24) 5.25 (5.01) 3.59 (3.28) 4.12 (3.78) 5.85 (5.39) 3.59 (4.63) 6.71 (5.23)
[-9.66]*** [-7.56]*** [-5.16]*** [-7.89]*** [-3.17]** [-1.09] [-1.71]
202 352 192 64 9 15 5 3443
Adj. Tier1 Equity < 0 4.46 (0.00) 4.55 (0.00) 4.69 (0.00) 6.25 (0.00) 0.00 (0.00) 0.00 (0.00) 40.00 (0.00) 2.96 (0.00)
[1.01] [1.38] [1.11] [1.07] [-10.25]*** [-10.25]*** [1.51]
9 16 9 4 0 0 2 102
Adj. Common equity tier1 4.11 (3.80) 4.81 (4.29) 5.24 (5.00) 3.50 (3.18) 4.12 (3.78) 5.84 (5.39) 3.59 (4.63) 6.63 (5.21)
[-9.50]*** [-6.99]*** [-4.96]*** [-7.71]*** [-3.09]** [-1.01] [-1.67]
195 339 191 61 9 15 5 3411
Adj. Common equity tier1 < 0 4.62 (0.00) 3.24 (0.00) 4.71 (0.00) 6.56 (0.00) 0.00 (0.00) 0.00 (0.00) 40.00 (0.00) 3.02 (0.00)
[1.04] [0.22] [1.08] [1.10] [-10.30]*** [-10.30]*** [1.51]
9 11 9 4 0 0 2 103
Uninsured Leverage 26.81 (25.02) 27.21 (25.31) 24.65 (23.17) 32.36 (30.12) 30.11 (26.15) 30.56 (30.05) 23.81 (22.44) 22.79 (21.40)
[5.06]*** [6.43]*** [2.33]** [5.44]*** [1.95]* [2.28]** [0.18]
202 352 192 64 9 15 5 3453
MTM Insolvent 29.70 (0.00) 19.32 (0.00) 12.50 (0.00) 28.12 (0.00) 33.33 (0.00) 0.00 (0.00) 40.00 (0.00) 18.88 (0.00)
[3.29]*** [0.20] [-2.57]** [1.62] [0.87] [-28.30]*** [0.86]
60 68 24 18 3 0 2 650
Solvent and Liquid 10.40 (0.00) 10.80 (0.00) 19.27 (0.00) 4.69 (0.00) 0.00 (0.00) 20.00 (0.00) 0.00 (0.00) 24.76 (0.00)
[-6.31]*** [-7.71]*** [-1.86]* [-7.27]*** [-33.69]*** [-0.44] [-33.69]***
21 38 37 3 0 3 0 854
Solvent and Illiquid 23.27 (0.00) 31.25 (0.00) 33.33 (0.00) 31.25 (0.00) 22.22 (0.00) 40.00 (0.00) 40.00 (0.00) 25.79 (0.00)
[-0.82] [2.11]** [2.16]** [0.93] [-0.24] [1.08] [0.58]
47 110 64 20 2 6 2 889
Insolvent and Liquid 23.76 (0.00) 26.42 (0.00) 23.44 (0.00) 12.50 (0.00) 22.22 (0.00) 6.67 (0.00) 40.00 (0.00) 27.14 (0.00)
[-1.09] [-0.29] [-1.17] [-3.46]*** [-0.33] [-3.05]*** [0.52]
48 93 45 8 2 1 2 936
Insolvent and Illiquid 42.57 (0.00) 31.53 (0.00) 23.96 (0.00) 51.56 (100.00) 55.56 (100.00) 33.33 (0.00) 20.00 (0.00) 22.11 (0.00)
[5.75]*** [3.66]*** [0.58] [4.65]*** [1.90]* [0.89] [-0.11]
86 111 46 33 5 5 1 762
IDCR Insolvent (s=0.5) 3.96 (0.00) 5.68 (0.00) 3.65 (0.00) 3.12 (0.00) 0.00 (0.00) 0.00 (0.00) 20.00 (0.00) 4.13 (0.00)
[-0.12] [1.21] [-0.35] [-0.45] [-12.13]*** [-12.13]*** [0.79]
8 20 7 2 0 0 1 141
IDCR Insolvent (s=1.0) 28.22 (0.00) 29.83 (0.00) 27.60 (0.00) 21.88 (0.00) 0.00 (0.00) 6.67 (0.00) 40.00 (0.00) 28.66 (0.00)
[-0.14] [0.46] [-0.32] [-1.29] [-37.02]*** [-3.28]*** [0.46]
57 105 53 14 0 1 2 978
Capital Insolvent (s=0.5) 1.98 (0.00) 3.12 (0.00) 3.12 (0.00) 6.25 (0.00) 0.00 (0.00) 0.00 (0.00) 20.00 (0.00) 1.98 (0.00)
[0.01] [1.20] [0.90] [1.40] [-8.33]*** [-8.33]*** [0.90]
4 11 6 4 0 0 1 68
Capital Insolvent (s=1.0) 11.88 (0.00) 11.65 (0.00) 7.81 (0.00) 7.81 (0.00) 0.00 (0.00) 0.00 (0.00) 20.00 (0.00) 6.97 (0.00)
[2.11]** [2.65]*** [0.42] [0.25] [-16.06]*** [-16.06]*** [0.65]
24 41 15 5 0 0 1 240
Available Liquidity Ratio 5.20 (3.81) 6.41 (3.70) 5.35 (4.38) 3.92 (2.49) 3.95 (3.59) 5.66 (4.04) 3.24 (3.59) 10.19 (6.66)
[-12.67]*** [-9.25]*** [-15.40]*** [-9.04]*** [-6.73]*** [-3.94]*** [-9.94]***
202 352 192 64 9 15 5 3453
Change Uninsured Deposits (Fwd Q) -6.13 (-6.27) -5.29 (-5.75) -6.10 (-6.21) -10.11 (-8.59) -14.10 (-13.96) -3.95 (-4.59) -11.14 (-12.22) 1.56 (-3.89)
[-2.91]*** [-2.64]*** [-2.83]*** [-3.97]*** [-4.72]*** [-1.51] [-3.57]***
202 350 192 64 9 15 5 3391
Change Insured Deposits (Fwd Q) 3.59 (1.86) 4.62 (2.19) 1.49 (0.78) 8.98 (2.15) 1.07 (0.75) 4.47 (3.66) 6.42 (4.81) 3.82 (1.43)
[-0.24] [0.92] [-2.94]*** [1.29] [-1.49] [0.33] [0.80]
202 350 192 64 9 15 5 3397
Abnormal Insured Outflow (10%) 13.37 (0.00) 4.55 (0.00) 8.33 (0.00) 7.81 (0.00) 11.11 (0.00) 0.00 (0.00) 0.00 (0.00) 7.44 (0.00)
[2.43]** [-2.42]** [0.43] [0.11] [0.33] [-16.66]*** [-16.66]***
27 16 16 5 1 0 0 257
Abnormal Insured Outflow (5%) 4.95 (0.00) 1.42 (0.00) 2.08 (0.00) 1.56 (0.00) 0.00 (0.00) 0.00 (0.00) 0.00 (0.00) 2.72 (0.00)
[1.43] [-1.89]* [-0.60] [-0.73] [-9.83]*** [-9.83]*** [-9.83]***
10 5 4 1 0 0 0 94
Abnormal Uninsured Outflow (10%) 25.25 (0.00) 29.26 (0.00) 30.21 (0.00) 43.75 (0.00) 44.44 (0.00) 40.00 (0.00) 60.00 (100.00) 19.37 (0.00)
[1.87]* [3.92]*** [3.20]*** [3.88]*** [1.43] [1.57] [1.66]
51 103 58 28 4 6 3 669
Abnormal Uninsured Outflow (5%) 8.91 (0.00) 11.93 (0.00) 14.06 (0.00) 25.00 (0.00) 33.33 (0.00) 6.67 (0.00) 20.00 (0.00) 8.37 (0.00)
[0.26] [1.99]** [2.22]** [3.04]*** [1.50] [-0.25] [0.58]
18 42 27 16 3 1 1 289
# Export
export_table(
  table5b, 
  "table5b_q1_2023_5pct",
  caption = "Pre-Crisis Bank Characteristics by Borrower Type: Q1 2023 (5\\% FHLB Threshold)",
  label = "tab:q1_2023_5pct",
  note = "Bank characteristics from 2022Q4 Call Reports. Q1 2023: January 1 -- March 31, 2023. FHLB borrowers identified as banks with abnormal FHLB advances at the 95th percentile. Sample excludes G-SIBs and failed banks."
)
## LaTeX table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table5b_q1_2023_5pct.tex 
## HTML table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table5b_q1_2023_5pct.html 
## CSV table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table5b_q1_2023_5pct.csv

15 Table 6: Arbitrage Period - BTFP, DW, Both, Non-Borrowers

# ==============================================================================
# TABLE 6: Arbitrage Period (Nov 1, 2023 - Jan 24, 2024)
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("TABLE 6: Arbitrage Period - BTFP, DW, Both, Non-Borrowers\n")
## TABLE 6: Arbitrage Period - BTFP, DW, Both, Non-Borrowers
cat(strrep("=", 60), "\n")
## ============================================================
arb_start <- as.Date("2023-11-01")
arb_end <- as.Date("2024-01-24")

btfp_arb <- btfp_loans_raw %>%
  filter(btfp_loan_date >= arb_start & btfp_loan_date <= arb_end) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

# Note: DW data ends 2023-12-31, so only partial coverage
dw_arb <- dw_loans_raw %>%
  filter(dw_loan_date >= arb_start & dw_loan_date <= min(arb_end, DW_DATA_END)) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

cat("BTFP borrowers (Arbitrage):", length(btfp_arb), "\n")
## BTFP borrowers (Arbitrage): 801
cat("DW borrowers (Arbitrage, partial):", length(dw_arb), "\n")
## DW borrowers (Arbitrage, partial): 481
cat("Note: DW data ends", as.character(DW_DATA_END), "\n")
## Note: DW data ends 2023-12-31
table6_data <- baseline_q %>%
  mutate(
    btfp_user = idrssd %in% btfp_arb,
    dw_user = idrssd %in% dw_arb,
    borrower_type = case_when(
      btfp_user & dw_user ~ "Both",
      btfp_user & !dw_user ~ "BTFP Only",
      !btfp_user & dw_user ~ "DW Only",
      TRUE ~ "Non-Borrower"
    )
  )

table6 <- create_summary_table_v2(table6_data, "borrower_type",
                                   group_levels = c("BTFP Only", "DW Only", "Both", "Non-Borrower"))

# Display
table6 %>%
  select(-Row_Type) %>%
  kable(caption = "Table 6: Pre-Crisis Bank Characteristics by Borrower Type (Arbitrage Period: Nov 1, 2023 - Jan 24, 2024)") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Table 6: Pre-Crisis Bank Characteristics by Borrower Type (Arbitrage Period: Nov 1, 2023 - Jan 24, 2024)
Variable BTFP Only DW Only Both Non-Borrower
N 623 302 143 3224
Book Equity Ratio 8.59 (8.31) 9.27 (9.17) 8.15 (8.08) 10.72 (9.01)
[-9.58]*** [-5.74]*** [-8.93]***
623 302 143 3224
MTM Loss (HTM) 0.25 (0.00) 0.17 (0.00) 0.21 (0.00) 0.20 (0.00)
[1.37] [-1.29] [0.17]
623 302 143 3214
MTM Loss (BTFP Elg.) 0.87 (0.60) 0.69 (0.51) 0.76 (0.49) 0.64 (0.36)
[6.02]*** [1.15] [1.74]*
623 302 143 3214
MTM Loss (Total) 6.17 (5.93) 5.36 (5.22) 6.13 (6.12) 5.31 (5.16)
[9.76]*** [0.38] [4.53]***
623 302 143 3214
Adjusted Equity 2.41 (2.28) 3.91 (3.75) 2.02 (1.93) 5.30 (3.93)
[-11.47]*** [-4.44]*** [-8.39]***
623 302 143 3214
Adjusted Equity < 0 26.97 (0.00) 15.56 (0.00) 32.17 (0.00) 17.55 (0.00)
[4.95]*** [-0.90] [3.68]***
168 47 46 564
Adj. Tier1 Equity 4.48 (4.07) 5.23 (4.91) 3.71 (3.66) 6.87 (5.32)
[-11.09]*** [-6.18]*** [-10.92]***
623 302 143 3214
Adj. Tier1 Equity < 0 5.62 (0.00) 3.97 (0.00) 7.69 (0.00) 2.61 (0.00)
[3.11]*** [1.17] [2.25]**
35 12 11 84
Adj. Common equity tier1 4.46 (4.07) 5.27 (4.93) 3.66 (3.63) 6.80 (5.31)
[-10.99]*** [-5.77]*** [-10.75]***
619 290 137 3180
Adj. Common equity tier1 < 0 5.82 (0.00) 3.79 (0.00) 8.03 (0.00) 2.52 (0.00)
[3.36]*** [1.10] [2.35]**
36 11 11 80
Uninsured Leverage 25.43 (23.98) 26.41 (25.24) 28.22 (26.52) 22.79 (21.42)
[5.35]*** [4.72]*** [5.19]***
623 302 143 3224
MTM Insolvent 26.97 (0.00) 15.56 (0.00) 32.17 (0.00) 17.55 (0.00)
[4.95]*** [-0.90] [3.68]***
168 47 46 564
Solvent and Liquid 11.88 (0.00) 18.21 (0.00) 8.39 (0.00) 25.31 (0.00)
[-8.92]*** [-3.02]*** [-6.91]***
74 55 12 815
Solvent and Illiquid 22.47 (0.00) 32.78 (0.00) 31.47 (0.00) 26.60 (0.00)
[-2.24]** [2.20]** [1.22]
140 99 45 856
Insolvent and Liquid 29.70 (0.00) 22.52 (0.00) 24.48 (0.00) 26.30 (0.00)
[1.70]* [-1.50] [-0.50]
185 68 35 847
Insolvent and Illiquid 35.96 (0.00) 26.49 (0.00) 35.66 (0.00) 21.57 (0.00)
[7.00]*** [1.86]* [3.45]***
224 80 51 694
IDCR Insolvent (s=0.5) 4.82 (0.00) 3.97 (0.00) 2.80 (0.00) 4.18 (0.00)
[0.69] [-0.17] [-0.97]
30 12 4 133
IDCR Insolvent (s=1.0) 32.10 (0.00) 29.47 (0.00) 32.17 (0.00) 27.49 (0.00)
[2.27]** [0.72] [1.17]
200 89 46 875
Capital Insolvent (s=0.5) 1.77 (0.00) 4.97 (0.00) 5.59 (0.00) 1.87 (0.00)
[-0.17] [2.43]** [1.92]*
11 15 8 60
Capital Insolvent (s=1.0) 8.99 (0.00) 11.26 (0.00) 13.29 (0.00) 6.75 (0.00)
[1.82]* [2.40]** [2.27]**
56 34 19 217
Available Liquidity Ratio 5.33 (3.74) 7.07 (4.63) 4.96 (3.44) 10.47 (6.86)
[-18.84]*** [-7.13]*** [-13.84]***
623 302 143 3224
Change Uninsured Deposits (Fwd Q) -1.15 (-5.82) -5.39 (-6.07) -2.18 (-3.91) 0.88 (-4.09)
[-0.48] [-2.26]** [-1.08]
623 301 143 3161
Change Insured Deposits (Fwd Q) 3.72 (1.65) 5.93 (2.87) 4.14 (1.81) 3.66 (1.31)
[0.06] [2.16]** [0.39]
623 302 143 3166
Abnormal Insured Outflow (10%) 7.38 (0.00) 4.97 (0.00) 7.69 (0.00) 7.75 (0.00)
[-0.32] [-2.08]** [-0.03]
46 15 11 250
Abnormal Insured Outflow (5%) 2.41 (0.00) 1.99 (0.00) 2.80 (0.00) 2.76 (0.00)
[-0.52] [-0.91] [0.03]
15 6 4 89
Abnormal Uninsured Outflow (10%) 26.97 (0.00) 27.48 (0.00) 23.78 (0.00) 19.76 (0.00)
[3.77]*** [2.90]*** [1.10]
168 83 34 637
Abnormal Uninsured Outflow (5%) 12.68 (0.00) 11.59 (0.00) 9.79 (0.00) 8.34 (0.00)
[3.05]*** [1.70]* [0.57]
79 35 14 269
# Export
export_table(
  table6, 
  "table6_arbitrage_period",
  caption = "Pre-Crisis Bank Characteristics by Borrower Type: Arbitrage Period",
  label = "tab:arbitrage_period",
  note = "Bank characteristics from 2022Q4 Call Reports. Arbitrage period: November 1, 2023 -- January 24, 2024 (BTFP rate below IORB). Note: DW data available only through December 31, 2023. Sample excludes G-SIBs and failed banks."
)
## LaTeX table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table6_arbitrage_period.tex 
## HTML table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table6_arbitrage_period.html 
## CSV table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table6_arbitrage_period.csv
# ==============================================================================
# TABLE 6b: Arbitrage Period (Nov 1, 2023 - Jan 24, 2024)
# UPDATED: Uses 2023Q4 baseline instead of 2022Q4
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("TABLE 6b: Arbitrage Period - BTFP, DW, Both, Non-Borrowers\n")
## TABLE 6b: Arbitrage Period - BTFP, DW, Both, Non-Borrowers
cat("Using 2023Q4 as baseline\n")
## Using 2023Q4 as baseline
cat(strrep("=", 60), "\n")
## ============================================================
# Create 2023Q4 baseline data
baseline_q4_2023 <- call_q %>%
  filter(period == '2023Q4') %>%
  filter(
    gsib == 0 | is.na(gsib),
    failed_bank == 0 | is.na(failed_bank),
    !is.na(omo_eligible) & omo_eligible > 0
  )



# Step 3: Calculate medians for cutoffs (BEFORE adding derived variables)
medians_q4 <- baseline_q4_2023 %>%
  summarise(
    median_uninsured = median(uninsured_deposit_to_total_asset, na.rm = TRUE),
    median_mtm = median(mtm_loss_to_total_asset, na.rm = TRUE),
    q75_uninsured = quantile(uninsured_deposit_to_total_asset, 0.75, na.rm = TRUE),
    q75_mtm = quantile(mtm_loss_to_total_asset, 0.75, na.rm = TRUE)
  )

cat("Median uninsured ratio:", round(medians_q4$median_uninsured, 2), "%\n")
## Median uninsured ratio: 19.94 %
cat("Median MTM loss ratio:", round(medians_q4$median_mtm, 2), "%\n")
## Median MTM loss ratio: 5.13 %
cat("Q75 uninsured ratio:", round(medians_q4$q75_uninsured, 2), "%\n")
## Q75 uninsured ratio: 27.17 %
cat("Q75 MTM loss ratio:", round(medians_q4$q75_mtm, 2), "%\n")
## Q75 MTM loss ratio: 6.81 %
# Step 4: Add ALL derived variables to baseline
baseline_q4_2023 <- baseline_q4_2023 %>%
  mutate(
    # Market value adjustment: (Book Asset / MV Asset) - 1
    
    cet1_ratio = safe_div(cet1, total_asset) * 100,
    mv_asset = mm_asset,
    mv_adjustment = if_else(mv_asset == 0 | is.na(mv_asset), NA_real_, 
                            (total_asset / mv_asset) - 1),
    
    # IDCR: (MV_Asset - s*Uninsured - Insured) / Insured
    idcr_s50 = safe_div(mv_asset - 0.5 * uninsured_deposit - insured_deposit, insured_deposit),
    idcr_s100 = safe_div(mv_asset - 1.0 * uninsured_deposit - insured_deposit, insured_deposit),
    
    # Capital Insolvency: (Equity - s*Uninsured*MVAdj) / Assets
    cap_insolvency_s50 = safe_div((total_asset - total_liability) - 0.5 * uninsured_deposit * mv_adjustment, total_asset),
    cap_insolvency_s100 = safe_div((total_asset - total_liability) - 1.0 * uninsured_deposit * mv_adjustment, total_asset),
    
    # Adjusted Equity (book equity ratio - MTM loss ratio, both in %)
    adjusted_equity = book_equity_to_total_asset - mtm_loss_to_total_asset,
    adjusted_tier1 = tier1cap_to_total_asset - mtm_loss_to_total_asset,
    adjusted_cet1 = cet1_ratio - mtm_loss_to_total_asset,
    
    # MTM Insolvent dummy (adjusted equity < 0)
    mtm_insolvent = as.integer(adjusted_equity < 0),
    mtm_insolvent_tier1 = as.integer(adjusted_tier1 < 0),
    mtm_insolvent_cet1 = as.integer(adjusted_cet1 < 0),
    
    adjusted_book_value = mm_asset - total_liability,
    
    mv_insolvent = as.integer(adjusted_book_value < 0),
    
    # Uninsured leverage (uninsured deposit / book equity)
    uninsured_leverage = uninsured_deposit_to_total_asset,
    liquidity_available = safe_div(cash + rerepo + fed_fund_sold, total_asset) * 100,
    
   
    
    # Run risk dummies
    # a. Solvent and Liquid (both uninsured and MTM below median)
    run_risk_1 = as.integer(
      uninsured_deposit_to_total_asset < medians_q4$median_uninsured & 
        mtm_loss_to_total_asset < medians_q4$median_mtm
    ),
    # b. Solvent and Illiquid
    run_risk_2 = as.integer(
      uninsured_deposit_to_total_asset > medians_q4$median_uninsured & 
        mtm_loss_to_total_asset < medians_q4$median_mtm
    ),
   # c. Insolvent and Liquid  
        run_risk_3 = as.integer(
      uninsured_deposit_to_total_asset < medians_q4$median_uninsured & 
        mtm_loss_to_total_asset > medians_q4$median_mtm
    ),
    # d. Insolvent and ILLiquid (both uninsured and MTM above median)  
        run_risk_4 = as.integer(
      uninsured_deposit_to_total_asset > medians_q4$median_uninsured & 
        mtm_loss_to_total_asset > medians_q4$median_mtm
    ),
    
    # IDCR insolvency dummies
    idcr_insolvent_s50 = as.integer(idcr_s50 < 0),
    idcr_insolvent_s100 = as.integer(idcr_s100 < 0),
    
    # Capital insolvency dummies
    cap_insolvent_s50 = as.integer(cap_insolvency_s50 < 0),
    cap_insolvent_s100 = as.integer(cap_insolvency_s100 < 0)
  ) %>%
  filter(
    gsib == 0 | is.na(gsib),
    failed_bank == 0 | is.na(failed_bank),
    !is.na(omo_eligible) & omo_eligible > 0)

cat("2023Q4 baseline observations:", nrow(baseline_q4_2023), "\n")
## 2023Q4 baseline observations: 4197
arb_start <- as.Date("2023-11-01")
arb_end <- as.Date("2024-01-24")

btfp_arb <- btfp_loans_raw %>%
  filter(btfp_loan_date >= arb_start & btfp_loan_date <= arb_end) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

# Note: DW data ends 2023-12-31, so only partial coverage
dw_arb <- dw_loans_raw %>%
  filter(dw_loan_date >= arb_start & dw_loan_date <= min(arb_end, DW_DATA_END)) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

cat("BTFP borrowers (Arbitrage):", length(btfp_arb), "\n")
## BTFP borrowers (Arbitrage): 801
cat("DW borrowers (Arbitrage, partial):", length(dw_arb), "\n")
## DW borrowers (Arbitrage, partial): 481
cat("Note: DW data ends", as.character(DW_DATA_END), "\n")
## Note: DW data ends 2023-12-31
table6b_data <- baseline_q4_2023 %>%
  mutate(
    btfp_user = idrssd %in% btfp_arb,
    dw_user = idrssd %in% dw_arb,
    borrower_type = case_when(
      btfp_user & dw_user ~ "Both",
      btfp_user & !dw_user ~ "BTFP Only",
      !btfp_user & dw_user ~ "DW Only",
      TRUE ~ "Non-Borrower"
    )
  )

table6b <- create_summary_table_v2(table6b_data, "borrower_type",
                                   group_levels = c("BTFP Only", "DW Only", "Both", "Non-Borrower"))

# Display
table6b %>%
  select(-Row_Type) %>%
  kable(caption = "Table 6b: Bank Characteristics by Borrower Type (Arbitrage Period: Nov 1, 2023 - Jan 24, 2024) - 2023Q4 Baseline") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Table 6b: Bank Characteristics by Borrower Type (Arbitrage Period: Nov 1, 2023 - Jan 24, 2024) - 2023Q4 Baseline
Variable BTFP Only DW Only Both Non-Borrower
N 632 302 141 3122
Book Equity Ratio 9.06 (8.74) 9.84 (9.75) 8.75 (8.65) 11.46 (9.56)
[-11.05]*** [-6.57]*** [-9.96]***
632 302 141 3122
MTM Loss (HTM) 0.24 (0.00) 0.16 (0.00) 0.21 (0.00) 0.20 (0.00)
[1.25] [-1.40] [0.17]
632 302 141 3104
MTM Loss (BTFP Elg.) 0.84 (0.56) 0.66 (0.49) 0.75 (0.48) 0.63 (0.35)
[5.61]*** [0.86] [1.79]*
632 302 141 3104
MTM Loss (Total) 5.92 (5.69) 5.17 (5.06) 5.86 (5.76) 5.16 (4.99)
[8.61]*** [0.13] [3.93]***
632 302 141 3104
Adjusted Equity 3.14 (3.12) 4.66 (4.57) 2.89 (2.94) 6.11 (4.69)
[-12.19]*** [-4.75]*** [-8.64]***
632 302 141 3104
Adjusted Equity < 0 20.41 (0.00) 11.26 (0.00) 22.70 (0.00) 12.21 (0.00)
[4.80]*** [-0.50] [2.92]***
129 34 32 379
Adj. Tier1 Equity 4.71 (4.40) 5.61 (5.24) 4.12 (3.97) 7.26 (5.71)
[-12.25]*** [-6.36]*** [-10.83]***
632 302 141 3104
Adj. Tier1 Equity < 0 3.32 (0.00) 3.64 (0.00) 7.09 (0.00) 2.16 (0.00)
[1.53] [1.34] [2.26]**
21 11 10 67
Adj. Common equity tier1 4.68 (4.38) 5.59 (5.25) 4.06 (3.87) 7.19 (5.69)
[-12.15]*** [-6.17]*** [-10.63]***
627 288 135 3072
Adj. Common equity tier1 < 0 3.51 (0.00) 3.47 (0.00) 7.41 (0.00) 2.15 (0.00)
[1.74]* [1.19] [2.31]**
22 10 10 66
Uninsured Leverage 22.06 (20.68) 22.63 (21.30) 24.60 (23.23) 20.84 (19.45)
[2.71]*** [2.71]*** [3.84]***
632 302 141 3122
MTM Insolvent 20.41 (0.00) 11.26 (0.00) 22.70 (0.00) 12.21 (0.00)
[4.80]*** [-0.50] [2.92]***
129 34 32 379
Solvent and Liquid 15.82 (0.00) 21.85 (0.00) 14.18 (0.00) 25.50 (0.00)
[-5.87]*** [-1.45] [-3.71]***
100 66 20 794
Solvent and Illiquid 22.94 (0.00) 29.80 (0.00) 26.95 (0.00) 26.86 (0.00)
[-2.12]** [1.07] [0.02]
145 90 38 836
Insolvent and Liquid 31.01 (0.00) 21.85 (0.00) 26.24 (0.00) 26.04 (0.00)
[2.48]** [-1.67]* [0.05]
196 66 37 811
Insolvent and Illiquid 30.06 (0.00) 26.49 (0.00) 32.62 (0.00) 21.27 (0.00)
[4.47]*** [1.97]** [2.82]***
190 80 46 662
IDCR Insolvent (s=0.5) 10.92 (0.00) 15.56 (0.00) 10.64 (0.00) 11.64 (0.00)
[-0.53] [1.81]* [-0.38]
69 47 15 358
IDCR Insolvent (s=1.0) 34.81 (0.00) 37.75 (0.00) 41.13 (0.00) 36.36 (0.00)
[-0.74] [0.48] [1.12]
220 114 58 1118
Capital Insolvent (s=0.5) 3.80 (0.00) 5.63 (0.00) 5.67 (0.00) 3.41 (0.00)
[0.46] [1.62] [1.14]
24 17 8 106
Capital Insolvent (s=1.0) 12.03 (0.00) 12.91 (0.00) 17.73 (0.00) 10.76 (0.00)
[0.90] [1.07] [2.13]**
76 39 25 334
Available Liquidity Ratio 5.77 (4.25) 6.75 (4.95) 5.18 (4.11) 10.12 (7.25)
[-16.63]*** [-7.98]*** [-13.57]***
632 302 141 3122
Change Uninsured Deposits (Fwd Q) 0.81 (0.31) 0.62 (0.71) 2.17 (1.39) 20.41 (-0.31)
[-1.27] [-1.29] [-1.19]
629 301 141 3073
Change Insured Deposits (Fwd Q) 1.99 (1.09) 2.30 (1.74) 2.02 (1.00) 1.83 (1.23)
[0.57] [1.26] [0.37]
629 301 141 3076
Abnormal Insured Outflow (10%) 8.86 (0.00) 7.28 (0.00) 10.64 (0.00) 7.85 (0.00)
[0.82] [-0.36] [1.05]
56 22 15 245
Abnormal Insured Outflow (5%) 5.06 (0.00) 3.97 (0.00) 5.67 (0.00) 4.93 (0.00)
[0.14] [-0.81] [0.37]
32 12 8 154
Abnormal Uninsured Outflow (10%) 11.23 (0.00) 9.93 (0.00) 4.96 (0.00) 10.95 (0.00)
[0.20] [-0.56] [-3.12]***
71 30 7 342
Abnormal Uninsured Outflow (5%) 6.49 (0.00) 5.63 (0.00) 3.55 (0.00) 6.21 (0.00)
[0.26] [-0.42] [-1.65]
41 17 5 194
# Export
export_table(
  table6b, 
  "table6b_arbitrage_period_2023q4",
  caption = "Bank Characteristics by Borrower Type: Arbitrage Period (2023Q4 Baseline)",
  label = "tab:arbitrage_period_2023q4",
  note = "Bank characteristics from 2023Q4 Call Reports. Arbitrage period: November 1, 2023 -- January 24, 2024 (BTFP rate below IORB). Note: DW data available only through December 31, 2023. Sample excludes G-SIBs and failed banks."
)
## LaTeX table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table6b_arbitrage_period_2023q4.tex 
## HTML table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table6b_arbitrage_period_2023q4.html 
## CSV table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table6b_arbitrage_period_2023q4.csv

16 Table 7: FHLB Borrower Characteristics (5% Threshold)

# ==============================================================================
# TABLE 7: FHLB Borrower Characteristics - 5% Threshold (Q1 2023)
# ==============================================================================

# First, identify banks with abnormal FHLB borrowing at 5% threshold
fhlb_borrower_5pct <- baseline_q %>%
  filter(!is.na(abnormal_fhlb_borrowing_5pct) & abnormal_fhlb_borrowing_5pct > 0) %>%
  pull(idrssd)

# Create FHLB summary table function with custom variables (WITH T-STATS)
create_fhlb_summary_table <- function(data, group_var, group_levels = NULL, reference_group = "Non-Borrower") {
  
  # Define variable specifications for FHLB table
  var_specs <- tribble(
    ~var_name, ~var_label, ~is_dummy,
    # Basic fundamentals
    "book_equity_to_total_asset", "Book Equity Ratio", FALSE,
    "loss_asset_htm_only", "MTM Loss (HTM)", FALSE,
    "mtm_loss_omo_eligible_to_total_asset", "MTM Loss (BTFP Elg.)", FALSE,
    "mtm_loss_to_total_asset", "MTM Loss (Total)", FALSE,
    "adjusted_equity", "Adjusted Equity", FALSE,
    "mtm_insolvent", "Adjusted Equity < 0", TRUE,
    "adjusted_tier1", "Adj. Tier1 Equity", FALSE,
    "mtm_insolvent_tier1", "Adj. Tier1 Equity < 0", TRUE,
    "adjusted_cet1", " Adj. Common equity tier1",FALSE, 
    "mtm_insolvent_cet1", "Adj. Common equity tier1 < 0", TRUE,
    "uninsured_leverage", "Uninsured Leverage", FALSE,
    "mtm_insolvent", "MTM Insolvent", TRUE,
    "run_risk_1", "Solvent and Liquid", TRUE,
    "run_risk_2", "Solvent and Illiquid", TRUE,
    "run_risk_3", "Insolvent and Liquid", TRUE,
    "run_risk_4", "Insolvent and Illiquid", TRUE,
    "idcr_insolvent_s50", "IDCR Insolvent (s=0.5)", TRUE,
    "idcr_insolvent_s100", "IDCR Insolvent (s=1.0)", TRUE,
    "cap_insolvent_s50", "Capital Insolvent (s=0.5)", TRUE,
    "cap_insolvent_s100", "Capital Insolvent (s=1.0)", TRUE,
    "liquidity_available", "Available Liquidity Ratio", FALSE,
    "change_uninsured_fwd_q", "Change Uninsured Deposits (Fwd Q)", FALSE,
    "change_insured_deposit_fwd_q", "Change Insured Deposits (Fwd Q)", FALSE,
    "abnormal_insured_outflow_10pct", "Abnormal Insured Outflow (10%)", TRUE,
    "abnormal_insured_outflow_5pct", "Abnormal Insured Outflow (5%)", TRUE,
    "abnormal_uninsured_outflow_10pct", "Abnormal Uninsured Outflow (10%)", TRUE,
    "abnormal_uninsured_outflow_5pct", "Abnormal Uninsured Outflow (5%)", TRUE
  )
  
  # Get unique groups
  if (is.null(group_levels)) {
    group_levels <- unique(data[[group_var]])
  }
  
  # Calculate N for each group
  n_by_group <- data %>%
    group_by(.data[[group_var]]) %>%
    summarise(N = n(), .groups = "drop")
  
  # Get reference group data for T-stat calculation
  ref_data <- data %>% filter(.data[[group_var]] == reference_group)
  
  # Initialize output list
  output_rows <- list()
  
  # Add N row first
  n_row <- c(Variable = "N", Row_Type = "count")
  for (g in group_levels) {
    n_val <- n_by_group %>% filter(.data[[group_var]] == g) %>% pull(N)
    n_row[g] <- as.character(if(length(n_val) == 0) 0 else n_val)
  }
  output_rows[[1]] <- n_row
  
  row_idx <- 2
  
  # Process each variable
  for (i in seq_len(nrow(var_specs))) {
    v <- var_specs$var_name[i]
    label <- var_specs$var_label[i]
    is_dummy <- var_specs$is_dummy[i]
    
    # Stats row: Mean (Median)
    stats_row <- c(Variable = label, Row_Type = "stats")
    # T-stat row (below stats)
    tstat_row <- c(Variable = "", Row_Type = "tstat")
    # N row (below t-stat)
    obs_row <- c(Variable = "", Row_Type = "n")
    
    # Get reference group values for T-stat
    ref_vals <- if (v %in% names(ref_data)) ref_data[[v]] else numeric(0)
    ref_vals <- ref_vals[!is.na(ref_vals)]
    
    for (g in group_levels) {
      group_data <- data %>% filter(.data[[group_var]] == g)
      
      # Check if variable exists
      if (!v %in% names(group_data)) {
        stats_row[g] <- "—"
        tstat_row[g] <- ""
        obs_row[g] <- "0"
        next
      }
      
      vals <- group_data[[v]]
      vals <- vals[!is.na(vals)]
      
      if (length(vals) == 0) {
        stats_row[g] <- "—"
        tstat_row[g] <- ""
        obs_row[g] <- "0"
      } else {
        mean_val <- mean(vals, na.rm = TRUE)
        median_val <- median(vals, na.rm = TRUE)
        
        if (is_dummy) {
          # For dummies: mean is proportion, show as percentage
          # N shows count of 1s (banks with dummy = 1)
          stats_row[g] <- sprintf("%.2f (%.2f)", mean_val * 100, median_val * 100)
          n_val <- sum(vals)  # Count of banks where dummy = 1
        } else if (v == "total_asset") {
          # For total assets: show in millions
          stats_row[g] <- sprintf("%.0f (%.0f)", mean_val / 1e6, median_val / 1e6)
          n_val <- length(vals)
        } else {
          stats_row[g] <- sprintf("%.2f (%.2f)", mean_val, median_val)
          n_val <- length(vals)  # Total non-NA observations
        }
        
        # Calculate T-stat vs reference group (skip for reference group itself)
        if (g == reference_group) {
          tstat_row[g] <- ""
        } else {
          t_stat <- calc_tstat(vals, ref_vals)
          if (!is.na(t_stat) && is.finite(t_stat)) {
            tstat_row[g] <- sprintf("[%.2f]", t_stat)
          } else {
            tstat_row[g] <- ""
          }
        }
        
        obs_row[g] <- as.character(n_val)
      }
    }
    
    output_rows[[row_idx]] <- stats_row
    output_rows[[row_idx + 1]] <- tstat_row
    output_rows[[row_idx + 2]] <- obs_row
    row_idx <- row_idx + 3
  }
  
  # Convert to data frame
  result_df <- bind_rows(lapply(output_rows, function(x) as_tibble_row(x)))
  
  return(result_df)
}

# Prepare data with FHLB variables (5% threshold)
table7_data <- baseline_q %>%
  mutate(
    # Categorize by FHLB usage (5% threshold)
    fhlb_user = idrssd %in% fhlb_borrower_5pct,
    btfp_user = idrssd %in% btfp_q1,
    dw_user = idrssd %in% dw_q1,
    borrower_type = case_when(
      fhlb_user & btfp_user & dw_user ~ "FHLB+BTFP+DW",
      fhlb_user & btfp_user & !dw_user ~ "FHLB+BTFP",
      fhlb_user & !btfp_user & dw_user ~ "FHLB+DW",
      fhlb_user & !btfp_user & !dw_user ~ "FHLB Only",
      !fhlb_user & (btfp_user | dw_user) ~ "Fed Only",
      TRUE ~ "Non-Borrower"
    )
  )

# Count by category
table7_data %>%
  count(borrower_type) %>%
  arrange(desc(n)) %>%
  pander(caption = "FHLB Borrower Breakdown (5% Threshold)")
FHLB Borrower Breakdown (5% Threshold)
borrower_type n
Non-Borrower 3453
Fed Only 618
FHLB Only 192
FHLB+DW 15
FHLB+BTFP 9
FHLB+BTFP+DW 5
table7 <- create_fhlb_summary_table(table7_data, "borrower_type",
                                     group_levels = c("FHLB Only", "FHLB+BTFP", "FHLB+DW", 
                                                      "FHLB+BTFP+DW", "Fed Only", "Non-Borrower"))

# Display
table7 %>%
  select(-Row_Type) %>%
  kable(caption = "Table 7: Bank Characteristics by FHLB Borrower Type - 5% Threshold (Q1 2023)") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  scroll_box(width = "100%")
Table 7: Bank Characteristics by FHLB Borrower Type - 5% Threshold (Q1 2023)
Variable FHLB Only FHLB+BTFP FHLB+DW FHLB+BTFP+DW Fed Only Non-Borrower
N 192 9 15 5 618 3453
Book Equity Ratio 9.80 (9.36) 9.42 (8.67) 11.24 (10.89) 10.44 (9.62) 8.56 (8.36) 10.54 (8.90)
[-2.66] [-1.06] [0.82] [-0.11] [-9.28]
192 9 15 5 618 3453
MTM Loss (HTM) 0.16 (0.00) 0.18 (0.01) 0.17 (0.04) 0.11 (0.00) 0.23 (0.00) 0.20 (0.00)
[-1.29] [-0.21] [-0.42] [-1.03] [0.85]
192 9 15 5 618 3443
MTM Loss (BTFP Elg.) 0.52 (0.28) 0.64 (0.52) 0.57 (0.37) 0.35 (0.23) 0.84 (0.56) 0.66 (0.38)
[-2.91] [-0.12] [-0.47] [-2.27] [4.74]
192 9 15 5 618 3443
MTM Loss (Total) 5.60 (5.14) 6.59 (6.26) 5.00 (5.07) 6.35 (6.57) 5.83 (5.83) 5.39 (5.23)
[1.27] [2.11] [-1.14] [0.61] [4.81]
192 9 15 5 618 3443
Adjusted Equity 4.20 (4.30) 2.82 (1.53) 6.24 (6.33) 4.09 (3.04) 2.73 (2.47) 5.04 (3.79)
[-2.42] [-1.46] [1.19] [-0.40] [-9.20]
192 9 15 5 618 3443
Adjusted Equity < 0 12.50 (0.00) 33.33 (0.00) 0.00 (0.00) 40.00 (0.00) 23.62 (0.00) 18.88 (0.00)
[-2.57] [0.87] [-28.30] [0.86] [2.59]
24 3 0 2 146 650
Adj. Tier1 Equity 5.25 (5.01) 4.12 (3.78) 5.85 (5.39) 3.59 (4.63) 4.42 (3.99) 6.71 (5.23)
[-5.16] [-3.17] [-1.09] [-1.71] [-10.67]
192 9 15 5 618 3443
Adj. Tier1 Equity < 0 4.69 (0.00) 0.00 (0.00) 0.00 (0.00) 40.00 (0.00) 4.69 (0.00) 2.96 (0.00)
[1.11] [-10.25] [-10.25] [1.51] [1.92]
9 0 0 2 29 102
Adj. Common equity tier1 5.24 (5.00) 4.12 (3.78) 5.84 (5.39) 3.59 (4.63) 4.45 (4.00) 6.63 (5.21)
[-4.96] [-3.09] [-1.01] [-1.67] [-10.26]
191 9 15 5 595 3411
Adj. Common equity tier1 < 0 4.71 (0.00) 0.00 (0.00) 0.00 (0.00) 40.00 (0.00) 4.03 (0.00) 3.02 (0.00)
[1.08] [-10.30] [-10.30] [1.51] [1.18]
9 0 0 2 24 103
Uninsured Leverage 24.65 (23.17) 30.11 (26.15) 30.56 (30.05) 23.81 (22.44) 27.61 (25.53) 22.79 (21.40)
[2.33] [1.95] [2.28] [0.18] [9.10]
192 9 15 5 618 3453
MTM Insolvent 12.50 (0.00) 33.33 (0.00) 0.00 (0.00) 40.00 (0.00) 23.62 (0.00) 18.88 (0.00)
[-2.57] [0.87] [-28.30] [0.86] [2.59]
24 3 0 2 146 650
Solvent and Liquid 19.27 (0.00) 0.00 (0.00) 20.00 (0.00) 0.00 (0.00) 10.03 (0.00) 24.76 (0.00)
[-1.86] [-33.69] [-0.44] [-33.69] [-10.41]
37 0 3 0 62 854
Solvent and Illiquid 33.33 (0.00) 22.22 (0.00) 40.00 (0.00) 40.00 (0.00) 28.64 (0.00) 25.79 (0.00)
[2.16] [-0.24] [1.08] [0.58] [1.45]
64 2 6 2 177 889
Insolvent and Liquid 23.44 (0.00) 22.22 (0.00) 6.67 (0.00) 40.00 (0.00) 24.11 (0.00) 27.14 (0.00)
[-1.17] [-0.33] [-3.05] [0.52] [-1.61]
45 2 1 2 149 936
Insolvent and Illiquid 23.96 (0.00) 55.56 (100.00) 33.33 (0.00) 20.00 (0.00) 37.22 (0.00) 22.11 (0.00)
[0.58] [1.90] [0.89] [-0.11] [7.30]
46 5 5 1 230 762
IDCR Insolvent (s=0.5) 3.65 (0.00) 0.00 (0.00) 0.00 (0.00) 20.00 (0.00) 4.85 (0.00) 4.13 (0.00)
[-0.35] [-12.13] [-12.13] [0.79] [0.78]
7 0 0 1 30 141
IDCR Insolvent (s=1.0) 27.60 (0.00) 0.00 (0.00) 6.67 (0.00) 40.00 (0.00) 28.48 (0.00) 28.66 (0.00)
[-0.32] [-37.02] [-3.28] [0.46] [-0.09]
53 0 1 2 176 978
Capital Insolvent (s=0.5) 3.12 (0.00) 0.00 (0.00) 0.00 (0.00) 20.00 (0.00) 3.07 (0.00) 1.98 (0.00)
[0.90] [-8.33] [-8.33] [0.90] [1.50]
6 0 0 1 19 68
Capital Insolvent (s=1.0) 7.81 (0.00) 0.00 (0.00) 0.00 (0.00) 20.00 (0.00) 11.33 (0.00) 6.97 (0.00)
[0.42] [-16.06] [-16.06] [0.65] [3.23]
15 0 0 1 70 240
Available Liquidity Ratio 5.35 (4.38) 3.95 (3.59) 5.66 (4.04) 3.24 (3.59) 5.76 (3.57) 10.19 (6.66)
[-15.40] [-6.73] [-3.94] [-9.94] [-14.39]
192 9 15 5 618 3453
Change Uninsured Deposits (Fwd Q) -6.10 (-6.21) -14.10 (-13.96) -3.95 (-4.59) -11.14 (-12.22) -6.06 (-6.30) 1.56 (-3.89)
[-2.83] [-4.72] [-1.51] [-3.57] [-3.01]
192 9 15 5 616 3391
Change Insured Deposits (Fwd Q) 1.49 (0.78) 1.07 (0.75) 4.47 (3.66) 6.42 (4.81) 4.73 (2.05) 3.82 (1.43)
[-2.94] [-1.49] [0.33] [0.80] [1.03]
192 9 15 5 616 3397
Abnormal Insured Outflow (10%) 8.33 (0.00) 11.11 (0.00) 0.00 (0.00) 0.00 (0.00) 7.77 (0.00) 7.44 (0.00)
[0.43] [0.33] [-16.66] [-16.66] [0.28]
16 1 0 0 48 257
Abnormal Insured Outflow (5%) 2.08 (0.00) 0.00 (0.00) 0.00 (0.00) 0.00 (0.00) 2.59 (0.00) 2.72 (0.00)
[-0.60] [-9.83] [-9.83] [-9.83] [-0.19]
4 0 0 0 16 94
Abnormal Uninsured Outflow (10%) 30.21 (0.00) 44.44 (0.00) 40.00 (0.00) 60.00 (100.00) 29.45 (0.00) 19.37 (0.00)
[3.20] [1.43] [1.57] [1.66] [5.16]
58 4 6 3 182 669
Abnormal Uninsured Outflow (5%) 14.06 (0.00) 33.33 (0.00) 6.67 (0.00) 20.00 (0.00) 12.30 (0.00) 8.37 (0.00)
[2.22] [1.50] [-0.25] [0.58] [2.80]
27 3 1 1 76 289
# Export (silently)
invisible(export_table(
  table7, 
  "table7_fhlb_borrowers_5pct",
  caption = "Bank Characteristics by FHLB Borrower Type: Q1 2023 (5\\% Threshold)",
  label = "tab:fhlb_borrowers_5pct",
  note = "Bank characteristics from 2022Q4 Call Reports. FHLB borrowers identified as banks with abnormal FHLB advances at the 95th percentile in 2023Q1. Abnormal FHLB borrowing is measured using Z-scores calculated as (current quarter change $-$ mean) / std, where mean and standard deviation are computed from the prior 8 quarters (2021Q1--2022Q4). Abnormal FHLB (5\\%) indicates Z $>$ 1.65 (top 5 percentile). Fed Only = BTFP and/or DW but no abnormal FHLB increase. Sample excludes G-SIBs and failed banks."
))

LaTeX table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table7_fhlb_borrowers_5pct.tex HTML table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table7_fhlb_borrowers_5pct.html CSV table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table7_fhlb_borrowers_5pct.csv

17 Table 8: FHLB Borrower Characteristics (10% Threshold)

# ==============================================================================
# TABLE 8: FHLB Borrower Characteristics - 10% Threshold (Q1 2023)
# ==============================================================================

# Identify banks with abnormal FHLB borrowing at 10% threshold
fhlb_borrower_10pct <- baseline_q %>%
  filter(!is.na(abnormal_fhlb_borrowing_10pct) & abnormal_fhlb_borrowing_10pct > 0) %>%
  pull(idrssd)

# Prepare data with FHLB variables (10% threshold)
table8_data <- baseline_q %>%
  mutate(
    # Categorize by FHLB usage (10% threshold)
    fhlb_user = idrssd %in% fhlb_borrower_10pct,
    btfp_user = idrssd %in% btfp_q1,
    dw_user = idrssd %in% dw_q1,
    borrower_type = case_when(
      fhlb_user & btfp_user & dw_user ~ "FHLB+BTFP+DW",
      fhlb_user & btfp_user & !dw_user ~ "FHLB+BTFP",
      fhlb_user & !btfp_user & dw_user ~ "FHLB+DW",
      fhlb_user & !btfp_user & !dw_user ~ "FHLB Only",
      !fhlb_user & (btfp_user | dw_user) ~ "Fed Only",
      TRUE ~ "Non-Borrower"
    )
  )

# Count by category
table8_data %>%
  count(borrower_type) %>%
  arrange(desc(n)) %>%
  pander(caption = "FHLB Borrower Breakdown (10% Threshold)")
FHLB Borrower Breakdown (10% Threshold)
borrower_type n
Non-Borrower 3385
Fed Only 605
FHLB Only 260
FHLB+DW 21
FHLB+BTFP 12
FHLB+BTFP+DW 9
table8 <- create_fhlb_summary_table(table8_data, "borrower_type",
                                     group_levels = c("FHLB Only", "FHLB+BTFP", "FHLB+DW", 
                                                      "FHLB+BTFP+DW", "Fed Only", "Non-Borrower"))

# Display
table8 %>%
  select(-Row_Type) %>%
  kable(caption = "Table 8: Bank Characteristics by FHLB Borrower Type - 10% Threshold (Q1 2023)") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  scroll_box(width = "100%")
Table 8: Bank Characteristics by FHLB Borrower Type - 10% Threshold (Q1 2023)
Variable FHLB Only FHLB+BTFP FHLB+DW FHLB+BTFP+DW Fed Only Non-Borrower
N 260 12 21 9 605 3385
Book Equity Ratio 9.82 (9.28) 8.89 (8.36) 11.00 (10.55) 9.36 (9.47) 8.55 (8.35) 10.55 (8.90)
[-2.78] [-1.80] [0.68] [-1.75] [-9.22]
260 12 21 9 605 3385
MTM Loss (HTM) 0.14 (0.00) 0.15 (0.00) 0.12 (0.00) 0.08 (0.00) 0.23 (0.00) 0.20 (0.00)
[-2.33] [-0.81] [-1.37] [-2.33] [0.90]
260 12 21 9 605 3375
MTM Loss (BTFP Elg.) 0.53 (0.28) 0.77 (0.87) 0.46 (0.23) 0.54 (0.34) 0.85 (0.56) 0.66 (0.39)
[-3.19] [0.75] [-1.39] [-0.80] [4.74]
260 12 21 9 605 3375
MTM Loss (Total) 5.69 (5.26) 6.37 (6.54) 5.13 (5.07) 6.10 (5.66) 5.83 (5.83) 5.38 (5.23)
[2.13] [1.96] [-0.65] [0.79] [4.92]
260 12 21 9 605 3375
Adjusted Equity 4.13 (4.12) 2.52 (1.53) 5.87 (6.33) 3.26 (3.04) 2.72 (2.44) 5.07 (3.79)
[-2.93] [-1.96] [0.94] [-1.33] [-9.19]
260 12 21 9 605 3375
Adjusted Equity < 0 14.23 (0.00) 33.33 (0.00) 4.76 (0.00) 33.33 (0.00) 23.64 (0.00) 18.87 (0.00)
[-2.04] [1.02] [-2.93] [0.87] [2.57]
37 4 1 3 143 637
Adj. Tier1 Equity 5.32 (5.01) 4.13 (3.49) 5.61 (5.57) 3.31 (4.04) 4.43 (3.99) 6.73 (5.24)
[-5.29] [-3.69] [-1.70] [-3.27] [-10.58]
260 12 21 9 605 3375
Adj. Tier1 Equity < 0 5.00 (0.00) 0.00 (0.00) 0.00 (0.00) 22.22 (0.00) 4.79 (0.00) 2.90 (0.00)
[1.51] [-10.04] [-10.04] [1.31] [2.06]
13 0 0 2 29 98
Adj. Common equity tier1 5.31 (5.01) 3.83 (3.21) 5.61 (5.57) 3.31 (4.04) 4.46 (4.00) 6.66 (5.21)
[-5.06] [-4.06] [-1.59] [-3.20] [-10.15]
258 11 21 9 583 3344
Adj. Common equity tier1 < 0 5.04 (0.00) 0.00 (0.00) 0.00 (0.00) 22.22 (0.00) 4.12 (0.00) 2.96 (0.00)
[1.49] [-10.10] [-10.10] [1.31] [1.32]
13 0 0 2 24 99
Uninsured Leverage 23.71 (22.82) 31.75 (28.72) 30.18 (30.05) 28.58 (31.00) 27.51 (25.38) 22.82 (21.42)
[1.26] [2.73] [2.62] [1.26] [8.75]
260 12 21 9 605 3385
MTM Insolvent 14.23 (0.00) 33.33 (0.00) 4.76 (0.00) 33.33 (0.00) 23.64 (0.00) 18.87 (0.00)
[-2.04] [1.02] [-2.93] [0.87] [2.57]
37 4 1 3 143 637
Solvent and Liquid 19.62 (0.00) 0.00 (0.00) 14.29 (0.00) 0.00 (0.00) 10.25 (0.00) 24.84 (0.00)
[-2.03] [-33.43] [-1.34] [-33.43] [-10.13]
51 0 3 0 62 840
Solvent and Illiquid 30.38 (0.00) 25.00 (0.00) 42.86 (0.00) 44.44 (0.00) 28.26 (0.00) 25.87 (0.00)
[1.53] [-0.07] [1.53] [1.06] [1.21]
79 3 9 4 171 874
Insolvent and Liquid 26.92 (0.00) 16.67 (0.00) 14.29 (0.00) 33.33 (0.00) 24.13 (0.00) 26.94 (0.00)
[-0.01] [-0.91] [-1.61] [0.38] [-1.48]
70 2 3 3 146 911
Insolvent and Illiquid 23.08 (0.00) 58.33 (100.00) 28.57 (0.00) 22.22 (0.00) 37.36 (0.00) 22.14 (0.00)
[0.35] [2.43] [0.64] [0.01] [7.27]
60 7 6 2 226 748
IDCR Insolvent (s=0.5) 4.62 (0.00) 0.00 (0.00) 4.76 (0.00) 11.11 (0.00) 4.79 (0.00) 4.07 (0.00)
[0.41] [-11.90] [0.15] [0.63] [0.78]
12 0 1 1 29 136
IDCR Insolvent (s=1.0) 27.31 (0.00) 8.33 (0.00) 14.29 (0.00) 33.33 (0.00) 28.43 (0.00) 28.71 (0.00)
[-0.49] [-2.43] [-1.83] [0.28] [-0.14]
71 1 3 3 172 960
Capital Insolvent (s=0.5) 3.08 (0.00) 0.00 (0.00) 4.76 (0.00) 11.11 (0.00) 2.98 (0.00) 1.96 (0.00)
[1.02] [-8.20] [0.59] [0.82] [1.39]
8 0 1 1 18 66
Capital Insolvent (s=1.0) 7.31 (0.00) 0.00 (0.00) 4.76 (0.00) 11.11 (0.00) 11.40 (0.00) 6.99 (0.00)
[0.19] [-15.93] [-0.47] [0.37] [3.23]
19 0 1 1 69 236
Available Liquidity Ratio 5.43 (4.31) 4.30 (3.76) 4.95 (3.49) 2.87 (2.22) 5.81 (3.57) 10.28 (6.70)
[-16.41] [-6.25] [-6.11] [-12.18] [-14.28]
260 12 21 9 605 3385
Change Uninsured Deposits (Fwd Q) -6.08 (-7.06) -10.34 (-12.20) -3.51 (-4.59) -17.22 (-12.22) -6.01 (-6.29) 1.71 (-3.71)
[-2.85] [-2.43] [-1.54] [-2.78] [-3.00]
260 12 21 9 603 3323
Change Insured Deposits (Fwd Q) 1.92 (0.96) 6.32 (0.94) 4.53 (3.66) 9.39 (7.84) 4.59 (2.02) 3.84 (1.42)
[-2.27] [0.45] [0.44] [2.14] [0.84]
260 12 21 9 603 3329
Abnormal Insured Outflow (10%) 9.62 (0.00) 8.33 (0.00) 0.00 (0.00) 0.00 (0.00) 7.93 (0.00) 7.33 (0.00)
[1.21] [0.12] [-16.36] [-16.36] [0.51]
25 1 0 0 48 248
Abnormal Insured Outflow (5%) 2.69 (0.00) 0.00 (0.00) 0.00 (0.00) 0.00 (0.00) 2.64 (0.00) 2.69 (0.00)
[0.00] [-9.67] [-9.67] [-9.67] [-0.06]
7 0 0 0 16 91
Abnormal Uninsured Outflow (10%) 29.23 (0.00) 41.67 (0.00) 38.10 (0.00) 55.56 (100.00) 29.26 (0.00) 19.23 (0.00)
[3.44] [1.51] [1.73] [2.07] [5.09]
76 5 8 5 177 651
Abnormal Uninsured Outflow (5%) 12.69 (0.00) 33.33 (0.00) 9.52 (0.00) 22.22 (0.00) 12.07 (0.00) 8.36 (0.00)
[2.04] [1.76] [0.18] [0.94] [2.63]
33 4 2 2 73 283
# Export (silently)
invisible(export_table(
  table8, 
  "table8_fhlb_borrowers_10pct",
  caption = "Bank Characteristics by FHLB Borrower Type: Q1 2023 (10\\% Threshold)",
  label = "tab:fhlb_borrowers_10pct",
  note = "Bank characteristics from 2022Q4 Call Reports. FHLB borrowers identified as banks with abnormal FHLB advances at the 90th percentile in 2023Q1. Abnormal FHLB borrowing is measured using Z-scores calculated as (current quarter change $-$ mean) / std, where mean and standard deviation are computed from the prior 8 quarters (2021Q1--2022Q4). Abnormal FHLB (10\\%) indicates Z $>$ 1.28 (top 10 percentile). Fed Only = BTFP and/or DW but no abnormal FHLB increase. Sample excludes G-SIBs and failed banks."
))

LaTeX table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table8_fhlb_borrowers_10pct.tex HTML table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table8_fhlb_borrowers_10pct.html CSV table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table8_fhlb_borrowers_10pct.csv

18 Summary Statistics

# ==============================================================================
# SUMMARY OF BORROWER COUNTS
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("SUMMARY OF BORROWER COUNTS\n")
## SUMMARY OF BORROWER COUNTS
cat(strrep("=", 60), "\n")
## ============================================================
summary_counts <- tribble(
  ~Table, ~Period, ~Baseline, ~Description, ~N_Borrowers, ~N_Total,
  "Table 1", "March 10, 2023", "2022Q4", "DW only", 
    sum(baseline_q$idrssd %in% dw_mar10), nrow(baseline_q),
  "Table 2", "March 10-13, 2023", "2022Q4", "DW only", 
    sum(baseline_q$idrssd %in% dw_mar10_13), nrow(baseline_q),
  "Table 3", "March 9-14, 2023", "2022Q4", "DW only", 
    sum(baseline_q$idrssd %in% dw_mar9_14), nrow(baseline_q),
  "Table 4", "Acute (Mar 13 - May 1)", "2022Q4", "BTFP + DW", 
    sum(baseline_q$idrssd %in% union(btfp_acute, dw_acute)), nrow(baseline_q),
  "Table 5A", "Q1 2023 (Jan-Mar)", "2022Q4", "BTFP + DW + FHLB (10%)", 
    sum(baseline_q$idrssd %in% union(union(btfp_q1, dw_q1), fhlb_borrowers_10pct)), nrow(baseline_q),
  "Table 5B", "Q1 2023 (Jan-Mar)", "2022Q4", "BTFP + DW + FHLB (5%)", 
    sum(baseline_q$idrssd %in% union(union(btfp_q1, dw_q1), fhlb_borrowers_5pct)), nrow(baseline_q),
  "Table 6", "Arbitrage (Nov 1 - Jan 24)", "2022Q4", "BTFP + DW", 
    sum(baseline_q$idrssd %in% union(btfp_arb, dw_arb)), nrow(baseline_q),
  "Table 6b", "Arbitrage (Nov 1 - Jan 24)", "2023Q4", "BTFP + DW", 
    sum(baseline_q4_2023$idrssd %in% union(btfp_arb, dw_arb)), nrow(baseline_q4_2023),
  "Table 7", "Q1 2023", "2022Q4", "FHLB focus (5%)", 
    sum(baseline_q$idrssd %in% fhlb_borrower_5pct), nrow(baseline_q),
  "Table 8", "Q1 2023", "2022Q4", "FHLB focus (10%)", 
    sum(baseline_q$idrssd %in% fhlb_borrower_10pct), nrow(baseline_q)
)

summary_counts %>%
  kable(caption = "Summary of Borrower Counts Across Tables") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Summary of Borrower Counts Across Tables
Table Period Baseline Description N_Borrowers N_Total
Table 1 March 10, 2023 2022Q4 DW only 47 4292
Table 2 March 10-13, 2023 2022Q4 DW only 90 4292
Table 3 March 9-14, 2023 2022Q4 DW only 124 4292
Table 4 Acute (Mar 13 - May 1) 2022Q4 BTFP + DW 761 4292
Table 5A Q1 2023 (Jan-Mar) 2022Q4 BTFP + DW + FHLB (10%) 907 4292
Table 5B Q1 2023 (Jan-Mar) 2022Q4 BTFP + DW + FHLB (5%) 839 4292
Table 6 Arbitrage (Nov 1 - Jan 24) 2022Q4 BTFP + DW 1068 4292
Table 6b Arbitrage (Nov 1 - Jan 24) 2023Q4 BTFP + DW 1075 4197
Table 7 Q1 2023 2022Q4 FHLB focus (5%) 221 4292
Table 8 Q1 2023 2022Q4 FHLB focus (10%) 302 4292
# Save summary
write_csv(summary_counts, file.path(TABLE_PATH, "summary_borrower_counts.csv"))

cat("\n=== ALL TABLES EXPORTED ===\n")
## 
## === ALL TABLES EXPORTED ===
cat("Output directory:", TABLE_PATH, "\n")
## Output directory: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables
cat("Files created:\n")
## Files created:
list.files(TABLE_PATH, pattern = "\\.(tex|html|csv)$") %>%
  paste("  -", .) %>%
  cat(sep = "\n")
##   - borrower_size_insolvency_2024q1.tex
##   - borrower_size_insolvency_acute.tex
##   - insolvency_size_2024q1.tex
##   - insolvency_size_acute.tex
##   - summary_borrower_counts.csv
##   - table_beta1_dw_mar10.csv
##   - table_beta1_dw_mar10.html
##   - table_beta1_dw_mar10.tex
##   - table_beta2_dw_mar10_13.csv
##   - table_beta2_dw_mar10_13.html
##   - table_beta2_dw_mar10_13.tex
##   - table_beta3_acute.csv
##   - table_beta3_acute.html
##   - table_beta3_acute.tex
##   - table_beta4_q1_2023.csv
##   - table_beta4_q1_2023.html
##   - table_beta4_q1_2023.tex
##   - table_beta5_arbitrage.csv
##   - table_beta5_arbitrage.html
##   - table_beta5_arbitrage.tex
##   - table1_dw_mar10.csv
##   - table1_dw_mar10.html
##   - table1_dw_mar10.tex
##   - table2_dw_mar10_13.csv
##   - table2_dw_mar10_13.html
##   - table2_dw_mar10_13.tex
##   - table3_dw_mar9_14.csv
##   - table3_dw_mar9_14.html
##   - table3_dw_mar9_14.tex
##   - table4_acute_period.csv
##   - table4_acute_period.html
##   - table4_acute_period.tex
##   - table5a_q1_2023_10pct.csv
##   - table5a_q1_2023_10pct.html
##   - table5a_q1_2023_10pct.tex
##   - table5b_q1_2023_5pct.csv
##   - table5b_q1_2023_5pct.html
##   - table5b_q1_2023_5pct.tex
##   - table6_arbitrage_period.csv
##   - table6_arbitrage_period.html
##   - table6_arbitrage_period.tex
##   - table6b_arbitrage_period_2023q4.csv
##   - table6b_arbitrage_period_2023q4.html
##   - table6b_arbitrage_period_2023q4.tex
##   - table7_fhlb_borrowers_5pct.csv
##   - table7_fhlb_borrowers_5pct.html
##   - table7_fhlb_borrowers_5pct.tex
##   - table8_fhlb_borrowers_10pct.csv
##   - table8_fhlb_borrowers_10pct.html
##   - table8_fhlb_borrowers_10pct.tex
##   - variable_definitions.csv
##   - variable_definitions.tex
# ==============================================================================
# DEPOSIT BETA ANALYSIS
# ==============================================================================

# Load deposit beta data
deposit_beta <- read_csv(file.path(DATA_PROC, "deposit_beta_yearly.csv"), show_col_types = FALSE) %>%
  mutate(rssd_id = as.character(rssd_id))

cat("Deposit beta observations:", nrow(deposit_beta), "\n")
## Deposit beta observations: 4781
# Merge with baseline data
baseline_q <- baseline_q %>%
  left_join(deposit_beta, by = c("idrssd" = "rssd_id"))

cat("Banks with deposit beta data:", sum(!is.na(baseline_q$beta_2022)), "\n")
## Banks with deposit beta data: 4221
# ==============================================================================
# DEPOSIT BETA SUMMARY TABLE FUNCTION
# ==============================================================================

create_deposit_beta_table <- function(data, group_var, group_levels = NULL, reference_group = "Non-Borrower") {
  
  # Define variable specifications for deposit beta
  var_specs <- tribble(
    ~var_name, ~var_label, ~is_dummy,
    # 2022 Betas (Pre-Crisis)
    "beta_2022", "Deposit Beta (2022)", FALSE,
    "rsquared_2022", "R-squared (2022)", FALSE,
    
    
    # 2023 Betas (Crisis Year)
    "beta_2023", "Deposit Beta (2023)", FALSE,
    "rsquared_2023", "R-squared (2023)", FALSE,
    
    
    # 2024 Betas (Post-Crisis)
    "beta_2024", "Deposit Beta (2024)", FALSE,
    "rsquared_2024", "R-squared (2024)", FALSE,
   
    
    # Beta Changes
    "beta_change_2022_2023", "Δ Beta (2022→2023)", FALSE,
    "beta_change_2023_2024", "Δ Beta (2023→2024)", FALSE,
    "beta_change_2022_2024", "Δ Beta (2022→2024)", FALSE
  )
  
  # Get unique groups
  if (is.null(group_levels)) {
    group_levels <- unique(data[[group_var]])
  }
  
  # Calculate N for each group (with beta data)
  n_by_group <- data %>%
    filter(!is.na(beta_2022)) %>%
    group_by(.data[[group_var]]) %>%
    summarise(N = n(), .groups = "drop")
  
  # Get reference group data for T-stat calculation
  ref_data <- data %>% filter(.data[[group_var]] == reference_group)
  
  # Initialize output list
  output_rows <- list()
  
  # Add N row first
  n_row <- c(Variable = "N (with beta data)", Row_Type = "count")
  for (g in group_levels) {
    n_val <- n_by_group %>% filter(.data[[group_var]] == g) %>% pull(N)
    n_row[g] <- as.character(if(length(n_val) == 0) 0 else n_val)
  }
  output_rows[[1]] <- n_row
  
  row_idx <- 2
  
  # Process each variable
  for (i in seq_len(nrow(var_specs))) {
    v <- var_specs$var_name[i]
    label <- var_specs$var_label[i]
    is_dummy <- var_specs$is_dummy[i]
    
    # Stats row: Mean (Median)
    stats_row <- c(Variable = label, Row_Type = "stats")
    # T-stat row
    tstat_row <- c(Variable = "", Row_Type = "tstat")
    # N row
    obs_row <- c(Variable = "", Row_Type = "n")
    
    # Get reference group values
    ref_vals <- if (v %in% names(ref_data)) ref_data[[v]] else numeric(0)
    ref_vals <- ref_vals[!is.na(ref_vals)]
    
    for (g in group_levels) {
      group_data <- data %>% filter(.data[[group_var]] == g)
      
      if (!v %in% names(group_data)) {
        stats_row[g] <- "—"
        tstat_row[g] <- ""
        obs_row[g] <- "0"
        next
      }
      
      vals <- group_data[[v]]
      vals <- vals[!is.na(vals)]
      
      if (length(vals) == 0) {
        stats_row[g] <- "—"
        tstat_row[g] <- ""
        obs_row[g] <- "0"
      } else {
        mean_val <- mean(vals, na.rm = TRUE)
        median_val <- median(vals, na.rm = TRUE)
        n_val <- length(vals)
        
        stats_row[g] <- sprintf("%.3f (%.3f)", mean_val, median_val)
        
        if (g == reference_group) {
          tstat_row[g] <- ""
        } else {
          tstat_result <- calc_tstat_with_stars(vals, ref_vals)
          if (!is.na(tstat_result$tstat) && is.finite(tstat_result$tstat)) {
            tstat_row[g] <- sprintf("[%.2f]%s", tstat_result$tstat, tstat_result$stars)
          } else {
            tstat_row[g] <- ""
          }
        }
        
        obs_row[g] <- as.character(n_val)
      }
    }
    
    output_rows[[row_idx]] <- stats_row
    output_rows[[row_idx + 1]] <- tstat_row
    output_rows[[row_idx + 2]] <- obs_row
    row_idx <- row_idx + 3
  }
  
  result_df <- bind_rows(lapply(output_rows, function(x) as_tibble_row(x)))
  return(result_df)
}
# ==============================================================================
# CREATE BETA CHANGE VARIABLES
# ==============================================================================

baseline_q <- baseline_q %>%
  mutate(
    beta_change_2022_2023 = beta_2023 - beta_2022,
    beta_change_2023_2024 = beta_2024 - beta_2023,
    beta_change_2022_2024 = beta_2024 - beta_2022
  )
# ==============================================================================
# TABLE B1: Deposit Beta - March 10, 2023 DW Borrowers
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("TABLE B1: Deposit Beta - March 10, 2023 DW Borrowers\n")
## TABLE B1: Deposit Beta - March 10, 2023 DW Borrowers
cat(strrep("=", 60), "\n")
## ============================================================
table_beta1_data <- baseline_q %>%
  mutate(
    borrower_type = if_else(idrssd %in% dw_mar10, "DW Borrower", "Non-Borrower")
  )

table_beta1 <- create_deposit_beta_table(table_beta1_data, "borrower_type",
                                          group_levels = c("DW Borrower", "Non-Borrower"))

table_beta1 %>%
  select(-Row_Type) %>%
  kable(caption = "Table B1: Deposit Beta - DW Borrowers vs Non-Borrowers (March 10, 2023)") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Table B1: Deposit Beta - DW Borrowers vs Non-Borrowers (March 10, 2023)
Variable DW Borrower Non-Borrower
N (with beta data) 47 4174
Deposit Beta (2022) 0.314 (0.246) 0.213 (0.170)
[2.38]**
47 4174
R-squared (2022) 0.676 (0.746) 0.609 (0.619)
[1.75]*
47 4174
Deposit Beta (2023) 0.251 (0.232) 0.132 (0.103)
[2.60]**
47 4109
R-squared (2023) 0.462 (0.462) 0.430 (0.403)
[0.64]
47 4109
Deposit Beta (2024) 0.336 (0.315) 0.277 (0.265)
[1.34]
46 4025
R-squared (2024) 0.534 (0.651) 0.542 (0.592)
[-0.16]
46 4025
Δ Beta (2022→2023) -0.063 (-0.056) -0.081 (-0.077)
[0.45]
47 4085
Δ Beta (2023→2024) 0.093 (0.117) 0.147 (0.153)
[-0.91]
46 4010
Δ Beta (2022→2024) 0.022 (0.025) 0.066 (0.072)
[-0.81]
46 3994
export_table(
  table_beta1,
  "table_beta1_dw_mar10",
  caption = "Deposit Beta: DW Borrowers vs Non-Borrowers (March 10, 2023)",
  label = "tab:beta_dw_mar10",
  note = "Deposit beta measures interest rate sensitivity of deposits. Higher beta indicates more rate-sensitive deposits. Beta estimated from quarterly deposit growth regressed on Fed Funds rate changes."
)
## LaTeX table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table_beta1_dw_mar10.tex 
## HTML table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table_beta1_dw_mar10.html 
## CSV table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table_beta1_dw_mar10.csv
# ==============================================================================
# TABLE B2: Deposit Beta - March 10-13, 2023 DW Borrowers
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("TABLE B2: Deposit Beta - March 10-13, 2023 DW Borrowers\n")
## TABLE B2: Deposit Beta - March 10-13, 2023 DW Borrowers
cat(strrep("=", 60), "\n")
## ============================================================
table_beta2_data <- baseline_q %>%
  mutate(
    borrower_type = if_else(idrssd %in% dw_mar10_13, "DW Borrower", "Non-Borrower")
  )

table_beta2 <- create_deposit_beta_table(table_beta2_data, "borrower_type",
                                          group_levels = c("DW Borrower", "Non-Borrower"))

table_beta2 %>%
  select(-Row_Type) %>%
  kable(caption = "Table B2: Deposit Beta - DW Borrowers vs Non-Borrowers (March 10-13, 2023)") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Table B2: Deposit Beta - DW Borrowers vs Non-Borrowers (March 10-13, 2023)
Variable DW Borrower Non-Borrower
N (with beta data) 90 4131
Deposit Beta (2022) 0.309 (0.271) 0.212 (0.169)
[3.85]***
90 4131
R-squared (2022) 0.686 (0.720) 0.608 (0.617)
[3.10]***
90 4131
Deposit Beta (2023) 0.267 (0.218) 0.131 (0.102)
[4.34]***
90 4066
R-squared (2023) 0.457 (0.460) 0.429 (0.402)
[0.75]
90 4066
Deposit Beta (2024) 0.356 (0.348) 0.276 (0.264)
[2.38]**
87 3984
R-squared (2024) 0.560 (0.686) 0.542 (0.591)
[0.49]
87 3984
Δ Beta (2022→2023) -0.043 (-0.059) -0.081 (-0.077)
[1.47]
90 4042
Δ Beta (2023→2024) 0.093 (0.109) 0.148 (0.153)
[-1.37]
87 3969
Δ Beta (2022→2024) 0.045 (0.044) 0.066 (0.072)
[-0.54]
87 3953
export_table(
  table_beta2,
  "table_beta2_dw_mar10_13",
  caption = "Deposit Beta: DW Borrowers vs Non-Borrowers (March 10--13, 2023)",
  label = "tab:beta_dw_mar10_13",
  note = "Deposit beta measures interest rate sensitivity of deposits. Higher beta indicates more rate-sensitive deposits."
)
## LaTeX table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table_beta2_dw_mar10_13.tex 
## HTML table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table_beta2_dw_mar10_13.html 
## CSV table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table_beta2_dw_mar10_13.csv
# ==============================================================================
# TABLE B3: Deposit Beta - Acute Period by Facility Choice
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("TABLE B3: Deposit Beta - Acute Period by Facility Choice\n")
## TABLE B3: Deposit Beta - Acute Period by Facility Choice
cat(strrep("=", 60), "\n")
## ============================================================
table_beta3_data <- baseline_q %>%
  mutate(
    btfp_user = idrssd %in% btfp_acute,
    dw_user = idrssd %in% dw_acute,
    borrower_type = case_when(
      btfp_user & dw_user ~ "Both",
      btfp_user & !dw_user ~ "BTFP Only",
      !btfp_user & dw_user ~ "DW Only",
      TRUE ~ "Non-Borrower"
    )
  )

table_beta3 <- create_deposit_beta_table(table_beta3_data, "borrower_type",
                                          group_levels = c("BTFP Only", "DW Only", "Both", "Non-Borrower"))

table_beta3 %>%
  select(-Row_Type) %>%
  kable(caption = "Table B3: Deposit Beta by Facility Choice (Acute Period: March 13 - May 1, 2023)") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Table B3: Deposit Beta by Facility Choice (Acute Period: March 13 - May 1, 2023)
Variable BTFP Only DW Only Both Non-Borrower
N (with beta data) 365 298 92 3466
Deposit Beta (2022) 0.241 (0.212) 0.243 (0.212) 0.313 (0.269) 0.206 (0.163)
[3.51]*** [3.16]*** [4.27]***
365 298 92 3466
R-squared (2022) 0.612 (0.617) 0.647 (0.642) 0.691 (0.719) 0.604 (0.615)
[0.65] [3.00]*** [3.75]***
365 298 92 3466
Deposit Beta (2023) 0.144 (0.130) 0.172 (0.142) 0.220 (0.172) 0.127 (0.095)
[1.05] [2.49]** [2.98]***
366 294 93 3403
R-squared (2023) 0.417 (0.387) 0.421 (0.373) 0.446 (0.452) 0.432 (0.406)
[-0.89] [-0.55] [0.41]
366 294 93 3403
Deposit Beta (2024) 0.284 (0.280) 0.311 (0.302) 0.334 (0.293) 0.272 (0.259)
[0.68] [1.77]* [1.82]*
361 284 92 3334
R-squared (2024) 0.553 (0.580) 0.552 (0.665) 0.609 (0.700) 0.539 (0.588)
[0.81] [0.63] [2.00]**
361 284 92 3334
Δ Beta (2022→2023) -0.093 (-0.086) -0.073 (-0.071) -0.093 (-0.104) -0.079 (-0.075)
[-0.92] [0.38] [-0.44]
364 294 92 3382
Δ Beta (2023→2024) 0.143 (0.152) 0.148 (0.161) 0.123 (0.159) 0.147 (0.152)
[-0.18] [0.03] [-0.65]
360 283 91 3322
Δ Beta (2022→2024) 0.046 (0.061) 0.073 (0.073) 0.028 (0.025) 0.068 (0.074)
[-1.16] [0.26] [-1.20]
358 283 90 3309
export_table(
  table_beta3,
  "table_beta3_acute",
  caption = "Deposit Beta by Facility Choice: Acute Crisis Period",
  label = "tab:beta_acute",
  note = "Deposit beta measures interest rate sensitivity of deposits. Acute crisis period: March 13 -- May 1, 2023. Banks classified by facility usage during this period."
)
## LaTeX table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table_beta3_acute.tex 
## HTML table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table_beta3_acute.html 
## CSV table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table_beta3_acute.csv
# ==============================================================================
# TABLE B4: Deposit Beta - Q1 2023 All Facilities
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("TABLE B4: Deposit Beta - Q1 2023 All Facilities\n")
## TABLE B4: Deposit Beta - Q1 2023 All Facilities
cat(strrep("=", 60), "\n")
## ============================================================
table_beta4_data <- baseline_q %>%
  mutate(
    btfp_user = idrssd %in% btfp_q1,
    dw_user = idrssd %in% dw_q1,
    fhlb_user = idrssd %in% fhlb_borrowers_10pct,
    borrower_type = case_when(
      btfp_user & dw_user & fhlb_user ~ "All Three",
      btfp_user & dw_user & !fhlb_user ~ "BTFP+DW",
      btfp_user & !dw_user & fhlb_user ~ "BTFP+FHLB",
      !btfp_user & dw_user & fhlb_user ~ "DW+FHLB",
      btfp_user & !dw_user & !fhlb_user ~ "BTFP Only",
      !btfp_user & dw_user & !fhlb_user ~ "DW Only",
      !btfp_user & !dw_user & fhlb_user ~ "FHLB Only",
      TRUE ~ "Non-Borrower"
    )
  )

table_beta4 <- create_deposit_beta_table(table_beta4_data, "borrower_type",
                                          group_levels = c("BTFP Only", "DW Only", "FHLB Only",
                                                           "BTFP+DW", "BTFP+FHLB", "DW+FHLB",
                                                           "All Three", "Non-Borrower"))

table_beta4 %>%
  select(-Row_Type) %>%
  kable(caption = "Table B4: Deposit Beta by Facility Choice (Q1 2023)") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  scroll_box(width = "100%")
Table B4: Deposit Beta by Facility Choice (Q1 2023)
Variable BTFP Only DW Only FHLB Only BTFP+DW BTFP+FHLB DW+FHLB All Three Non-Borrower
N (with beta data) 198 344 258 59 12 21 9 3320
Deposit Beta (2022) 0.267 (0.237) 0.248 (0.219) 0.265 (0.225) 0.291 (0.272) 0.277 (0.273) 0.322 (0.269) 0.422 (0.334) 0.201 (0.158)
[4.76]*** [4.16]*** [4.94]*** [3.48]*** [1.74] [3.23]*** [2.02]*
198 344 258 59 12 21 9 3320
R-squared (2022) 0.624 (0.624) 0.649 (0.669) 0.644 (0.653) 0.678 (0.672) 0.696 (0.679) 0.717 (0.742) 0.808 (0.794) 0.599 (0.606)
[1.46] [3.65]*** [2.81]*** [2.61]** [1.59] [2.50]** [3.92]***
198 344 258 59 12 21 9 3320
Deposit Beta (2023) 0.184 (0.182) 0.190 (0.182) 0.134 (0.118) 0.197 (0.167) 0.073 (0.057) 0.304 (0.220) 0.365 (0.318) 0.122 (0.089)
[2.57]** [4.30]*** [0.66] [2.23]** [-0.82] [2.14]** [1.75]
198 335 254 59 12 21 9 3268
R-squared (2023) 0.458 (0.447) 0.436 (0.412) 0.407 (0.387) 0.405 (0.373) 0.312 (0.202) 0.559 (0.482) 0.597 (0.553) 0.429 (0.399)
[1.31] [0.38] [-1.09] [-0.53] [-1.43] [2.05]* [2.23]*
198 335 254 59 12 21 9 3268
Deposit Beta (2024) 0.294 (0.298) 0.302 (0.280) 0.302 (0.295) 0.273 (0.258) 0.406 (0.414) 0.396 (0.414) 0.466 (0.481) 0.270 (0.257)
[1.06] [1.75]* [1.54] [0.05] [2.09]* [2.57]** [2.44]**
194 326 249 59 12 20 9 3202
R-squared (2024) 0.549 (0.599) 0.545 (0.639) 0.547 (0.590) 0.557 (0.653) 0.721 (0.775) 0.710 (0.793) 0.653 (0.763) 0.539 (0.584)
[0.41] [0.29] [0.35] [0.41] [2.20]* [2.69]** [1.18]
194 326 249 59 12 20 9 3202
Δ Beta (2022→2023) -0.082 (-0.053) -0.062 (-0.062) -0.128 (-0.107) -0.094 (-0.107) -0.204 (-0.164) -0.018 (-0.034) -0.057 (-0.045) -0.078 (-0.077)
[-0.16] [1.19] [-2.69]*** [-0.49] [-2.09]* [0.71] [0.17]
197 335 254 59 12 21 9 3245
Δ Beta (2023→2024) 0.105 (0.131) 0.122 (0.133) 0.168 (0.172) 0.112 (0.120) 0.333 (0.348) 0.083 (0.141) 0.101 (0.025) 0.150 (0.153)
[-1.53] [-1.48] [0.72] [-0.89] [2.32]** [-0.82] [-0.34]
194 324 249 58 12 20 9 3190
Δ Beta (2022→2024) 0.024 (0.060) 0.060 (0.061) 0.042 (0.057) 0.017 (0.013) 0.129 (0.145) 0.072 (0.094) 0.044 (0.018) 0.071 (0.074)
[-1.82]* [-0.65] [-1.32] [-1.31] [0.86] [0.02] [-0.26]
193 324 249 58 12 20 9 3175
export_table(
  table_beta4,
  "table_beta4_q1_2023",
  caption = "Deposit Beta by Facility Choice: Q1 2023",
  label = "tab:beta_q1_2023",
  note = "Deposit beta measures interest rate sensitivity of deposits. Q1 2023: January 1 -- March 31, 2023. FHLB borrowers identified at 10\\% threshold."
)
## LaTeX table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table_beta4_q1_2023.tex 
## HTML table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table_beta4_q1_2023.html 
## CSV table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table_beta4_q1_2023.csv
# ==============================================================================
# TABLE B5: Deposit Beta - Arbitrage Period
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("TABLE B5: Deposit Beta - Arbitrage Period\n")
## TABLE B5: Deposit Beta - Arbitrage Period
cat(strrep("=", 60), "\n")
## ============================================================
table_beta5_data <- baseline_q %>%
  mutate(
    btfp_user = idrssd %in% btfp_arb,
    dw_user = idrssd %in% dw_arb,
    borrower_type = case_when(
      btfp_user & dw_user ~ "Both",
      btfp_user & !dw_user ~ "BTFP Only",
      !btfp_user & dw_user ~ "DW Only",
      TRUE ~ "Non-Borrower"
    )
  )

table_beta5 <- create_deposit_beta_table(table_beta5_data, "borrower_type",
                                          group_levels = c("BTFP Only", "DW Only", "Both", "Non-Borrower"))

table_beta5 %>%
  select(-Row_Type) %>%
  kable(caption = "Table B5: Deposit Beta by Facility Choice (Arbitrage Period: Nov 1, 2023 - Jan 24, 2024)") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Table B5: Deposit Beta by Facility Choice (Arbitrage Period: Nov 1, 2023 - Jan 24, 2024)
Variable BTFP Only DW Only Both Non-Borrower
N (with beta data) 619 300 141 3161
Deposit Beta (2022) 0.225 (0.193) 0.259 (0.209) 0.247 (0.224) 0.206 (0.162)
[2.48]** [3.84]*** [2.67]***
619 300 141 3161
R-squared (2022) 0.621 (0.626) 0.624 (0.645) 0.665 (0.681) 0.603 (0.613)
[1.74]* [1.41] [3.25]***
619 300 141 3161
Deposit Beta (2023) 0.145 (0.117) 0.174 (0.134) 0.165 (0.130) 0.126 (0.097)
[1.46] [2.56]** [1.67]*
618 301 141 3096
R-squared (2023) 0.439 (0.413) 0.427 (0.388) 0.462 (0.481) 0.427 (0.400)
[0.81] [-0.03] [1.19]
618 301 141 3096
Deposit Beta (2024) 0.259 (0.267) 0.303 (0.314) 0.265 (0.258) 0.279 (0.260)
[-1.29] [1.06] [-0.55]
617 296 141 3017
R-squared (2024) 0.554 (0.607) 0.586 (0.682) 0.526 (0.569) 0.536 (0.582)
[1.23] [2.48]** [-0.36]
617 296 141 3017
Δ Beta (2022→2023) -0.081 (-0.080) -0.085 (-0.087) -0.079 (-0.091) -0.080 (-0.074)
[-0.10] [-0.27] [0.03]
617 300 140 3075
Δ Beta (2023→2024) 0.128 (0.156) 0.134 (0.131) 0.109 (0.125) 0.153 (0.157)
[-1.51] [-0.68] [-1.43]
612 295 140 3009
Δ Beta (2022→2024) 0.042 (0.057) 0.052 (0.074) 0.023 (0.043) 0.074 (0.074)
[-2.10]** [-0.90] [-1.97]*
613 294 139 2994
export_table(
  table_beta5,
  "table_beta5_arbitrage",
  caption = "Deposit Beta by Facility Choice: Arbitrage Period",
  label = "tab:beta_arbitrage",
  note = "Deposit beta measures interest rate sensitivity of deposits. Arbitrage period: November 1, 2023 -- January 24, 2024 (BTFP rate below IORB)."
)
## LaTeX table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table_beta5_arbitrage.tex 
## HTML table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table_beta5_arbitrage.html 
## CSV table saved: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/table_beta5_arbitrage.csv
# ==============================================================================
# DEPOSIT BETA SUMMARY
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("DEPOSIT BETA SUMMARY\n")
## DEPOSIT BETA SUMMARY
cat(strrep("=", 60), "\n")
## ============================================================
# Summary by acute period facility choice
cat("\n--- Deposit Beta by Facility Choice (Acute Period) ---\n")
## 
## --- Deposit Beta by Facility Choice (Acute Period) ---
table_beta3_data %>%
  filter(!is.na(beta_2022)) %>%
  group_by(borrower_type) %>%
  summarise(
    N = n(),
    Beta_2022_Mean = round(mean(beta_2022, na.rm = TRUE), 3),
    Beta_2023_Mean = round(mean(beta_2023, na.rm = TRUE), 3),
    Beta_2024_Mean = round(mean(beta_2024, na.rm = TRUE), 3),
    Delta_22_23 = round(mean(beta_change_2022_2023, na.rm = TRUE), 3),
    Delta_23_24 = round(mean(beta_change_2023_2024, na.rm = TRUE), 3),
    .groups = "drop"
  ) %>%
  pander(caption = "Deposit Beta Evolution by Facility Choice")
Deposit Beta Evolution by Facility Choice (continued below)
borrower_type N Beta_2022_Mean Beta_2023_Mean Beta_2024_Mean
BTFP Only 365 0.241 0.148 0.289
Both 92 0.313 0.22 0.342
DW Only 298 0.243 0.172 0.318
Non-Borrower 3466 0.206 0.126 0.274
Delta_22_23 Delta_23_24
-0.093 0.139
-0.093 0.12
-0.073 0.148
-0.079 0.147
# T-test: BTFP Only vs DW Only
cat("\n--- T-Tests: BTFP Only vs DW Only ---\n")
## 
## --- T-Tests: BTFP Only vs DW Only ---
btfp_data <- table_beta3_data %>% filter(borrower_type == "BTFP Only")
dw_data <- table_beta3_data %>% filter(borrower_type == "DW Only")

for (v in c("beta_2022", "beta_2023", "beta_2024", "beta_change_2022_2023")) {
  result <- calc_tstat_with_stars(btfp_data[[v]], dw_data[[v]])
  cat(sprintf("%s: t = %.3f%s (p = %.4f)\n", v, result$tstat, result$stars, result$pval))
}
## beta_2022: t = -0.110 (p = 0.9121)
## beta_2023: t = -1.198 (p = 0.2314)
## beta_2024: t = -1.008 (p = 0.3141)
## beta_change_2022_2023: t = -0.947 (p = 0.3439)

19 Variable Definitions

# ==============================================================================
# VARIABLE DEFINITIONS TABLE
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("VARIABLE DEFINITIONS\n")
## VARIABLE DEFINITIONS
cat(strrep("=", 60), "\n")
## ============================================================
variable_definitions <- tribble(
  ~Category, ~Variable, ~Definition, ~Source,
  
  # Solvency Measures
  "Solvency", "Book Equity Ratio", "Total equity / Total assets (×100)", "Call Report",
  "Solvency", "MTM Loss (HTM)", "Mark-to-market loss on held-to-maturity securities / Total assets (×100)", "Call Report",
  "Solvency", "MTM Loss (BTFP Elg.)", "Mark-to-market loss on BTFP-eligible securities (Treasury, Agency, MBS) / Total assets (×100)", "Call Report",
  "Solvency", "MTM Loss (Total)", "Total mark-to-market loss on all securities / Total assets (×100)", "Call Report",
  "Solvency", "Adjusted Equity", "Book equity ratio − MTM loss ratio (percentage points)", "Derived",
  "Solvency", "Adjusted Equity < 0", "Indicator = 1 if adjusted equity < 0", "Derived",
  "Solvency", "Adj. Tier1 Equity", "Tier 1 capital ratio − MTM loss ratio (percentage points)", "Derived",
  "Solvency", "Adj. Tier1 Equity < 0", "Indicator = 1 if adjusted Tier 1 equity < 0", "Derived",
  "Solvency", "Adj. CET1", "Common Equity Tier 1 ratio − MTM loss ratio (percentage points)", "Derived",
  "Solvency", "Adj. CET1 < 0", "Indicator = 1 if adjusted CET1 < 0", "Derived",
  
  # Liquidity Measures
  "Liquidity", "Uninsured Leverage", "Uninsured deposits / Total assets (×100)", "Call Report",
  "Liquidity", "Available Liquidity Ratio", "(Cash + Reverse repo + Fed funds sold) / Total assets (×100)", "Call Report",
  
  # Run Risk Categories
  "Run Risk", "Solvent and Liquid", "Indicator = 1 if uninsured ratio < median AND MTM loss < median", "Derived",
  "Run Risk", "Solvent and Illiquid", "Indicator = 1 if uninsured ratio > median AND MTM loss < median", "Derived",
  "Run Risk", "Insolvent and Liquid", "Indicator = 1 if uninsured ratio < median AND MTM loss > median", "Derived",
  "Run Risk", "Insolvent and Illiquid", "Indicator = 1 if uninsured ratio > median AND MTM loss > median", "Derived",
  
  # IDCR Measures
  "IDCR", "IDCR Insolvent (s=0.5)", "Indicator = 1 if (MV_Asset − 0.5×Uninsured − Insured)/Insured < 0", "Derived",
  "IDCR", "IDCR Insolvent (s=1.0)", "Indicator = 1 if (MV_Asset − Uninsured − Insured)/Insured < 0", "Derived",
  
  # Capital Insolvency
  "Capital", "Capital Insolvent (s=0.5)", "Indicator = 1 if (Equity − 0.5×Uninsured×MV_Adj)/Assets < 0", "Derived",
  "Capital", "Capital Insolvent (s=1.0)", "Indicator = 1 if (Equity − Uninsured×MV_Adj)/Assets < 0", "Derived",
  
  # Deposit Flow Measures
  "Deposit Flows", "Change Uninsured Deposits (Fwd Q)", "Percentage change in uninsured deposits from baseline to next quarter", "Call Report",
  "Deposit Flows", "Change Insured Deposits (Fwd Q)", "Percentage change in insured deposits from baseline to next quarter", "Call Report",
  "Deposit Flows", "Abnormal Insured Outflow (10%)", "Indicator = 1 if insured deposit outflow Z-score > 1.28 (top 10%)", "Derived",
  "Deposit Flows", "Abnormal Insured Outflow (5%)", "Indicator = 1 if insured deposit outflow Z-score > 1.65 (top 5%)", "Derived",
  "Deposit Flows", "Abnormal Uninsured Outflow (10%)", "Indicator = 1 if uninsured deposit outflow Z-score > 1.28 (top 10%)", "Derived",
  "Deposit Flows", "Abnormal Uninsured Outflow (5%)", "Indicator = 1 if uninsured deposit outflow Z-score > 1.65 (top 5%)", "Derived",
  
  # Deposit Beta Measures
  "Deposit Beta", "Deposit Beta (2022)", "Interest rate sensitivity of deposits estimated from 2022 data", "Estimated",
  "Deposit Beta", "Deposit Beta (2023)", "Interest rate sensitivity of deposits estimated from 2023 data", "Estimated",
  "Deposit Beta", "Deposit Beta (2024)", "Interest rate sensitivity of deposits estimated from 2024 data", "Estimated",
  "Deposit Beta", "R-squared", "Goodness of fit from deposit beta regression", "Estimated",
  "Deposit Beta", "Δ Beta (2022→2023)", "Change in deposit beta from 2022 to 2023", "Derived",
  "Deposit Beta", "Δ Beta (2023→2024)", "Change in deposit beta from 2023 to 2024", "Derived",
  "Deposit Beta", "Δ Beta (2022→2024)", "Change in deposit beta from 2022 to 2024", "Derived",
  
  # FHLB Measures
  "FHLB", "Abnormal FHLB (10%)", "Indicator = 1 if FHLB borrowing Z-score > 1.28 (top 10%)", "Derived",
  "FHLB", "Abnormal FHLB (5%)", "Indicator = 1 if FHLB borrowing Z-score > 1.65 (top 5%)", "Derived",
  
  # Borrower Classifications
  "Classification", "BTFP Borrower", "Bank that borrowed from Bank Term Funding Program during specified period", "BTFP Data",
  "Classification", "DW Borrower", "Bank that borrowed from Discount Window during specified period", "DW Data",
  "Classification", "FHLB Borrower", "Bank with abnormal FHLB advances above specified threshold", "Call Report",
  "Classification", "Non-Borrower", "Bank that did not borrow from any emergency facility during specified period", "Derived"
)

# Display variable definitions
variable_definitions %>%
  kable(caption = "Table: Variable Definitions",
        col.names = c("Category", "Variable", "Definition", "Source")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = TRUE) %>%
  collapse_rows(columns = 1, valign = "top")
Table: Variable Definitions
Category Variable Definition Source
Solvency Book Equity Ratio Total equity / Total assets (×100) Call Report
MTM Loss (HTM) Mark-to-market loss on held-to-maturity securities / Total assets (×100) Call Report
MTM Loss (BTFP Elg.) Mark-to-market loss on BTFP-eligible securities (Treasury, Agency, MBS) / Total assets (×100) Call Report
MTM Loss (Total) Total mark-to-market loss on all securities / Total assets (×100) Call Report
Adjusted Equity Book equity ratio − MTM loss ratio (percentage points) Derived
Adjusted Equity < 0 Indicator = 1 if adjusted equity < 0 Derived
Adj. Tier1 Equity Tier 1 capital ratio − MTM loss ratio (percentage points) Derived
Adj. Tier1 Equity < 0 Indicator = 1 if adjusted Tier 1 equity < 0 Derived
Adj. CET1 Common Equity Tier 1 ratio − MTM loss ratio (percentage points) Derived
Adj. CET1 < 0 Indicator = 1 if adjusted CET1 < 0 Derived
Liquidity Uninsured Leverage Uninsured deposits / Total assets (×100) Call Report
Available Liquidity Ratio (Cash + Reverse repo + Fed funds sold) / Total assets (×100) Call Report
Run Risk Solvent and Liquid Indicator = 1 if uninsured ratio < median AND MTM loss < median Derived
Solvent and Illiquid Indicator = 1 if uninsured ratio > median AND MTM loss < median Derived
Insolvent and Liquid Indicator = 1 if uninsured ratio < median AND MTM loss > median Derived
Insolvent and Illiquid Indicator = 1 if uninsured ratio > median AND MTM loss > median Derived
IDCR IDCR Insolvent (s=0.5) Indicator = 1 if (MV_Asset − 0.5×Uninsured − Insured)/Insured < 0 Derived
IDCR Insolvent (s=1.0) Indicator = 1 if (MV_Asset − Uninsured − Insured)/Insured < 0 Derived
Capital Capital Insolvent (s=0.5) Indicator = 1 if (Equity − 0.5×Uninsured×MV_Adj)/Assets < 0 Derived
Capital Insolvent (s=1.0) Indicator = 1 if (Equity − Uninsured×MV_Adj)/Assets < 0 Derived
Deposit Flows Change Uninsured Deposits (Fwd Q) Percentage change in uninsured deposits from baseline to next quarter Call Report
Change Insured Deposits (Fwd Q) Percentage change in insured deposits from baseline to next quarter Call Report
Abnormal Insured Outflow (10%) Indicator = 1 if insured deposit outflow Z-score > 1.28 (top 10%) Derived
Abnormal Insured Outflow (5%) Indicator = 1 if insured deposit outflow Z-score > 1.65 (top 5%) Derived
Abnormal Uninsured Outflow (10%) Indicator = 1 if uninsured deposit outflow Z-score > 1.28 (top 10%) Derived
Abnormal Uninsured Outflow (5%) Indicator = 1 if uninsured deposit outflow Z-score > 1.65 (top 5%) Derived
Deposit Beta Deposit Beta (2022) Interest rate sensitivity of deposits estimated from 2022 data Estimated
Deposit Beta (2023) Interest rate sensitivity of deposits estimated from 2023 data Estimated
Deposit Beta (2024) Interest rate sensitivity of deposits estimated from 2024 data Estimated
R-squared Goodness of fit from deposit beta regression Estimated
Δ Beta (2022→2023) Change in deposit beta from 2022 to 2023 Derived
Δ Beta (2023→2024) Change in deposit beta from 2023 to 2024 Derived
Δ Beta (2022→2024) Change in deposit beta from 2022 to 2024 Derived
FHLB Abnormal FHLB (10%) Indicator = 1 if FHLB borrowing Z-score > 1.28 (top 10%) Derived
Abnormal FHLB (5%) Indicator = 1 if FHLB borrowing Z-score > 1.65 (top 5%) Derived
Classification BTFP Borrower Bank that borrowed from Bank Term Funding Program during specified period BTFP Data
DW Borrower Bank that borrowed from Discount Window during specified period DW Data
FHLB Borrower Bank with abnormal FHLB advances above specified threshold Call Report
Non-Borrower Bank that did not borrow from any emergency facility during specified period Derived
# Export to LaTeX
var_def_latex <- c(
  "\\begin{table}[htbp]",
  "\\centering",
  "\\caption{Variable Definitions}",
  "\\label{tab:variable_definitions}",
  "\\footnotesize",
  "\\begin{tabular}{p{2cm}p{3.5cm}p{7.5cm}p{2cm}}",
  "\\toprule",
  "Category & Variable & Definition & Source \\\\",
  "\\midrule"
)

current_category <- ""
for (i in seq_len(nrow(variable_definitions))) {
  row <- variable_definitions[i, ]
  cat_display <- if (row$Category != current_category) row$Category else ""
  current_category <- row$Category
  
  # Escape special LaTeX characters
  def_escaped <- gsub("%", "\\\\%", row$Definition)
  def_escaped <- gsub("×", "$\\\\times$", def_escaped)
  def_escaped <- gsub("−", "$-$", def_escaped)
  
  var_def_latex <- c(var_def_latex,
                     sprintf("%s & %s & %s & %s \\\\",
                             cat_display, row$Variable, def_escaped, row$Source))
  
  # Add midrule between categories
  if (i < nrow(variable_definitions) && variable_definitions$Category[i+1] != current_category) {
    var_def_latex <- c(var_def_latex, "\\midrule")
  }
}

var_def_latex <- c(var_def_latex,
                   "\\bottomrule",
                   "\\end{tabular}",
                   "\\vspace{0.3em}",
                   "\\begin{minipage}{0.95\\textwidth}",
                   "\\scriptsize",
                   "\\textit{Notes:} All ratios expressed as percentages unless otherwise noted. MTM = Mark-to-market. MV = Market value. IDCR = Implied Deposit Coverage Ratio following Jiang et al. (2023). Z-scores calculated as (current value $-$ historical mean) / historical standard deviation using prior 8 quarters (2021Q1--2022Q4). Deposit beta estimated from quarterly deposit growth regressed on Fed Funds rate changes.",
                   "\\end{minipage}",
                   "\\end{table}")

writeLines(var_def_latex, file.path(TABLE_PATH, "variable_definitions.tex"))
cat("\nVariable definitions table saved to:", file.path(TABLE_PATH, "variable_definitions.tex"), "\n")
## 
## Variable definitions table saved to: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/variable_definitions.tex
# Also save as CSV
write_csv(variable_definitions, file.path(TABLE_PATH, "variable_definitions.csv"))
cat("Variable definitions CSV saved to:", file.path(TABLE_PATH, "variable_definitions.csv"), "\n")
## Variable definitions CSV saved to: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/variable_definitions.csv

20 Statistical Notes

# ==============================================================================
# STATISTICAL NOTES
# ==============================================================================

cat("\n", strrep("=", 60), "\n")
## 
##  ============================================================
cat("STATISTICAL NOTES\n")
## STATISTICAL NOTES
cat(strrep("=", 60), "\n")
## ============================================================
statistical_notes <- tribble(
  ~Item, ~Description,
  "T-statistics", "Calculated using Welch's t-test (unequal variances) comparing each borrower group to Non-Borrowers",
  "Significance levels", "*** p<0.01, ** p<0.05, * p<0.10 (two-tailed tests)",
  "Table format", "Mean (Median) with [T-statistic]significance stars and N observations",
  "Dummy variables", "Shown as percentage of banks with indicator = 1; N shows count of such banks",
  "Continuous variables", "Shown as percentage points; N shows total non-missing observations",
  "Baseline period", "2022Q4 unless otherwise noted (Table 6b uses 2023Q4)",
  "Sample", "Excludes G-SIBs and failed banks; includes only banks with BTFP-eligible securities"
)

statistical_notes %>%
  kable(caption = "Statistical Notes",
        col.names = c("Item", "Description")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = TRUE)
Statistical Notes
Item Description
T-statistics Calculated using Welch’s t-test (unequal variances) comparing each borrower group to Non-Borrowers
Significance levels *** p<0.01, ** p<0.05, * p<0.10 (two-tailed tests)
Table format Mean (Median) with [T-statistic]significance stars and N observations
Dummy variables Shown as percentage of banks with indicator = 1; N shows count of such banks
Continuous variables Shown as percentage points; N shows total non-missing observations
Baseline period 2022Q4 unless otherwise noted (Table 6b uses 2023Q4)
Sample Excludes G-SIBs and failed banks; includes only banks with BTFP-eligible securities
# ==============================================================================
# INSOLVENCY BY SIZE CATEGORY - TWO PERIODS
# ==============================================================================

cat("\n", strrep("=", 70), "\n")
## 
##  ======================================================================
cat("PREPARING INSOLVENCY DATA BY SIZE CATEGORY\n")
## PREPARING INSOLVENCY DATA BY SIZE CATEGORY
cat(strrep("=", 70), "\n\n")
## ======================================================================
# --------------------------------------------------------------------------
# SIZE CATEGORY DEFINITIONS (from LaTeX table)
# --------------------------------------------------------------------------

create_size_category <- function(assets_thousands) {
  # Convert thousands to millions for comparison
  assets_millions <- assets_thousands / 1000
  
  case_when(
    assets_millions >= 700000 ~ "$700B and Above",
    assets_millions >= 250000 ~ "$250B-$700B",
    assets_millions >= 100000 ~ "$100B-$250B",
    assets_millions >= 50000  ~ "$50B-$100B",
    assets_millions >= 20000  ~ "$20B-$50B",
    assets_millions >= 10000  ~ "$10B-$20B",
    assets_millions >= 5000   ~ "$5B-$10B",
    assets_millions >= 3000   ~ "$3B-$5B",
    assets_millions >= 1000   ~ "$1B-$3B",
    assets_millions >= 500    ~ "$500M-$1B",
    TRUE                      ~ "Below $500M"
  )
}

# Define factor levels to ensure proper ordering
size_levels <- c(
  "$700B and Above",
  "$250B-$700B",
  "$100B-$250B",
  "$50B-$100B",
  "$20B-$50B",
  "$10B-$20B",
  "$5B-$10B",
  "$3B-$5B",
  "$1B-$3B",
  "$500M-$1B",
  "Below $500M"
)

# --------------------------------------------------------------------------
# CALCULATE INSOLVENCY MEASURES FOR BASELINE (2022Q4)
# --------------------------------------------------------------------------

baseline_insolvency <- call_q %>%
  filter(period == '2022Q4') %>%
  filter(
    gsib == 0 | is.na(gsib),
    failed_bank == 0 | is.na(failed_bank),
    !is.na(omo_eligible) & omo_eligible > 0
  ) %>%
  mutate(
    # Size category (total_asset is in thousands)
    size_category = create_size_category(total_asset),
    size_category = factor(size_category, levels = size_levels),
    
    # All assets liquidated at market value
    adjusted_book_value = mm_asset - total_liability,
    mv_insolvent = as.integer(adjusted_book_value < 0),
    
    # Deposit run scenarios
    idcr_s50 = safe_div(mm_asset - 0.5 * uninsured_deposit - insured_deposit, insured_deposit),
    idcr_s100 = safe_div(mm_asset - 1.0 * uninsured_deposit - insured_deposit, insured_deposit),
    
    idcr_insolvent_s50 = as.integer(idcr_s50 < 0),
    idcr_insolvent_s100 = as.integer(idcr_s100 < 0)
  ) %>%
  select(idrssd, size_category, total_asset, 
         mv_insolvent, idcr_insolvent_s50, idcr_insolvent_s100)

cat("Baseline insolvency data prepared:\n")
## Baseline insolvency data prepared:
cat(sprintf("  Total banks: %d\n", nrow(baseline_insolvency)))
##   Total banks: 4292
cat(sprintf("  MV Insolvent: %d\n", sum(baseline_insolvency$mv_insolvent, na.rm = TRUE)))
##   MV Insolvent: 2015
cat(sprintf("  IDCR Insolvent (s=1.0): %d\n", sum(baseline_insolvency$idcr_insolvent_s100, na.rm = TRUE)))
##   IDCR Insolvent (s=1.0): 1210
cat(sprintf("  IDCR Insolvent (s=0.5): %d\n", sum(baseline_insolvency$idcr_insolvent_s50, na.rm = TRUE)))
##   IDCR Insolvent (s=0.5): 179
# --------------------------------------------------------------------------
# TABLE 1: INSOLVENCY BY SIZE - ACUTE PERIOD (March 13 - May 1, 2023)
# --------------------------------------------------------------------------

cat("\n", strrep("=", 70), "\n")
## 
##  ======================================================================
cat("TABLE 1: INSOLVENT BANKS BY SIZE - ACUTE PERIOD (March 13 - May 1, 2023)\n")
## TABLE 1: INSOLVENT BANKS BY SIZE - ACUTE PERIOD (March 13 - May 1, 2023)
cat(strrep("=", 70), "\n\n")
## ======================================================================
# Define acute period
acute_start <- as.Date("2023-03-13")
acute_end <- as.Date("2023-05-01")

# Identify BTFP borrowers in acute period
btfp_acute <- btfp_loans_raw %>%
  filter(btfp_loan_date >= acute_start & btfp_loan_date <= acute_end) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

# Identify DW borrowers in acute period
dw_acute <- dw_loans_raw %>%
  filter(dw_loan_date >= acute_start & dw_loan_date <= acute_end) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

cat(sprintf("BTFP borrowers in acute period: %d\n", length(btfp_acute)))
## BTFP borrowers in acute period: 492
cat(sprintf("DW borrowers in acute period: %d\n", length(dw_acute)))
## DW borrowers in acute period: 424
# Create summary table by size
table_acute <- baseline_insolvency %>%
  group_by(size_category) %>%
  summarise(
    total_banks = n(),
    mv_insolvent = sum(mv_insolvent, na.rm = TRUE),
    idcr_insolvent_s100 = sum(idcr_insolvent_s100, na.rm = TRUE),
    idcr_insolvent_s50 = sum(idcr_insolvent_s50, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  arrange(size_category)

# Calculate percentage (handle case where sum is 0)
total_s50 <- sum(table_acute$idcr_insolvent_s50)
if (total_s50 > 0) {
  table_acute <- table_acute %>%
    mutate(pct_s50 = 100 * idcr_insolvent_s50 / total_s50)
} else {
  table_acute <- table_acute %>%
    mutate(pct_s50 = 0)
}

# Display table
print(table_acute)
## # A tibble: 10 × 6
##    size_category total_banks mv_insolvent idcr_insolvent_s100 idcr_insolvent_s50
##    <fct>               <int>        <int>               <int>              <int>
##  1 $250B-$700B             5            2                   1                  0
##  2 $100B-$250B            13            8                   4                  1
##  3 $50B-$100B             15            8                   4                  1
##  4 $20B-$50B              45           18                   9                  3
##  5 $10B-$20B              57           26                  15                  4
##  6 $5B-$10B              112           62                  33                  9
##  7 $3B-$5B               114           66                  32                  5
##  8 $1B-$3B               562          328                 166                 28
##  9 $500M-$1B             717          384                 237                 31
## 10 Below $500M          2652         1113                 709                 97
## # ℹ 1 more variable: pct_s50 <dbl>
# Calculate totals row
totals_acute <- table_acute %>%
  summarise(
    size_category = "Total",
    total_banks = sum(total_banks),
    mv_insolvent = sum(mv_insolvent),
    idcr_insolvent_s100 = sum(idcr_insolvent_s100),
    idcr_insolvent_s50 = sum(idcr_insolvent_s50),
    pct_s50 = 100
  )

table_acute_with_totals <- bind_rows(table_acute, totals_acute)

# Format and display with kable
table_acute_with_totals %>%
  mutate(pct_s50 = sprintf("%.1f%%", pct_s50)) %>%
  kable(
    caption = "Table 1: Insolvent Banks by Size - Acute Period (March 13 - May 1, 2023)",
    col.names = c("Asset Size", "Total Banks", "All Assets Liquidated", 
                  "100% Uninsured Run", "50% Uninsured Run", "Percentage"),
    align = c("l", rep("r", 5)),
    format.args = list(big.mark = ",")
  ) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  row_spec(nrow(table_acute_with_totals), bold = TRUE)
Table 1: Insolvent Banks by Size - Acute Period (March 13 - May 1, 2023)
Asset Size Total Banks All Assets Liquidated 100% Uninsured Run 50% Uninsured Run Percentage
$250B-$700B 5 2 1 0 0.0%
$100B-$250B 13 8 4 1 0.6%
$50B-$100B 15 8 4 1 0.6%
$20B-$50B 45 18 9 3 1.7%
$10B-$20B 57 26 15 4 2.2%
$5B-$10B 112 62 33 9 5.0%
$3B-$5B 114 66 32 5 2.8%
$1B-$3B 562 328 166 28 15.6%
$500M-$1B 717 384 237 31 17.3%
Below $500M 2,652 1,113 709 97 54.2%
Total 4,292 2,015 1,210 179 100.0%
# Export to LaTeX
latex_acute <- c(
  "\\begin{table}[htbp]",
  "\\centering",
  "\\caption{Insolvent Banks by Asset Size: Acute Period (March 13--May 1, 2023)}",
  "\\label{tab:insolvency_size_acute}",
  "\\footnotesize",
  "",
  "\\begin{minipage}{0.95\\textwidth}",
  "\\smallskip",
  "This table reports the distribution of insolvent banks across asset size categories during",
  "the acute crisis period (March 13--May 1, 2023). Column (1) shows the total number of banks in each size bin.",
  "Columns (2)--(4) report the number of insolvent banks under three scenarios: (i) full liquidation of all",
  "assets at mark-to-market values, (ii) 100\\% uninsured depositor run, and",
  "(iii) 50\\% uninsured depositor run. Column (5) reports the percentage of insolvent banks",
  "under the 50\\% uninsured depositor run scenario relative to the total number of insolvent",
  "banks in that scenario.",
  "\\end{minipage}",
  "",
  "\\medskip",
  "\\begin{tabular}{l*{5}{c}}",
  "\\hline\\hline",
  "& (1) & (2) & (3) & (4) & (5) \\\\",
  "Asset Size ",
  "& Total Banks ",
  "& All Assets ",
  "& 100\\% Uninsured",
  "& 50\\% Uninsured ",
  "& Percentage \\\\",
  "",
  "& Banks ",
  "& Liquidated ",
  "&Deposit Run ",
  "& Deposit Run ",
  "& 50\\% Uninsured run \\\\",
  "\\hline",
  ""
)

for (i in 1:nrow(table_acute)) {
  row <- table_acute[i, ]
  latex_acute <- c(
    latex_acute,
    sprintf("%s & %d & %d & %d & %d & %.1f\\%% \\\\",
            row$size_category,
            row$total_banks,
            row$mv_insolvent,
            row$idcr_insolvent_s100,
            row$idcr_insolvent_s50,
            row$pct_s50)
  )
}

latex_acute <- c(
  latex_acute,
  "\\hline",
  "",
  sprintf("Number of Banks & %d & %d & %d & %d & 100\\%% \\\\",
          totals_acute$total_banks,
          totals_acute$mv_insolvent,
          totals_acute$idcr_insolvent_s100,
          totals_acute$idcr_insolvent_s50),
  "\\hline\\hline",
  "\\end{tabular}",
  "",
  "\\begin{minipage}{0.95\\textwidth}",
  "\\smallskip",
  "\\footnotesize",
  "\\textit{Note:} Insolvency in Column (2) is defined as mark-to-market (MTM) asset values being",
  "insufficient to cover total non-equity liabilities. In Column (3), the assumption is that all",
  "Uninsured depositors run; insolvency occurs if remaining insured deposits cannot be repaid from",
  "MTM asset values. In Column (4), only 50\\% of uninsured deposits run. The final column shows the",
  "distribution of insolvent banks in Column (4) as a percentage of all insolvent banks under that",
  "scenario. All insolvency measures are based on 2022Q4 balance sheet data. Sample excludes G-SIBs,",
  "failed banks, and banks without BTFP-eligible securities.",
  "\\end{minipage}",
  "",
  "\\end{table}"
)

writeLines(latex_acute, file.path(TABLE_PATH, "insolvency_size_acute.tex"))
cat("\nAcute period table saved to:", file.path(TABLE_PATH, "insolvency_size_acute.tex"), "\n")
## 
## Acute period table saved to: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/insolvency_size_acute.tex
# --------------------------------------------------------------------------
# TABLE 2: INSOLVENCY BY SIZE - JANUARY 1 - MARCH 31, 2024
# Includes BTFP, DW, and FHLB (10% threshold) borrowers
# --------------------------------------------------------------------------

cat("\n", strrep("=", 70), "\n")
## 
##  ======================================================================
cat("TABLE 2: INSOLVENT BANKS BY SIZE - JAN 1 - MARCH 31, 2024\n")
## TABLE 2: INSOLVENT BANKS BY SIZE - JAN 1 - MARCH 31, 2024
cat("Includes BTFP, DW, and FHLB (10% threshold) borrowers\n")
## Includes BTFP, DW, and FHLB (10% threshold) borrowers
cat(strrep("=", 70), "\n\n")
## ======================================================================
# Define period
period_2024_start <- as.Date("2024-01-01")
period_2024_end <- as.Date("2024-03-31")

# Identify BTFP borrowers in 2024 period
btfp_2024 <- btfp_loans_raw %>%
  filter(btfp_loan_date >= period_2024_start & btfp_loan_date <= period_2024_end) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

# Identify DW borrowers in 2024 period (if data exists)
dw_2024 <- dw_loans_raw %>%
  filter(dw_loan_date >= period_2024_start & dw_loan_date <= period_2024_end) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

# Identify FHLB borrowers using 10% threshold from 2022Q4 baseline
# Note: FHLB status is from baseline_q, not from date-specific loans
fhlb_borrowers_10pct <- call_q %>%
  filter(period == '2022Q4') %>%
  filter(
    gsib == 0 | is.na(gsib),
    failed_bank == 0 | is.na(failed_bank),
    !is.na(omo_eligible) & omo_eligible > 0,
    !is.na(abnormal_fhlb_borrowing_10pct) & abnormal_fhlb_borrowing_10pct > 0
  ) %>%
  pull(idrssd)

cat(sprintf("BTFP borrowers in 2024 period: %d\n", length(btfp_2024)))
## BTFP borrowers in 2024 period: 717
cat(sprintf("DW borrowers in 2024 period: %d\n", length(dw_2024)))
## DW borrowers in 2024 period: 0
cat(sprintf("FHLB borrowers (10%% threshold): %d\n", length(fhlb_borrowers_10pct)))
## FHLB borrowers (10% threshold): 302
# Create summary table by size (same insolvency measures as acute period)
table_2024 <- baseline_insolvency %>%
  group_by(size_category) %>%
  summarise(
    total_banks = n(),
    mv_insolvent = sum(mv_insolvent, na.rm = TRUE),
    idcr_insolvent_s100 = sum(idcr_insolvent_s100, na.rm = TRUE),
    idcr_insolvent_s50 = sum(idcr_insolvent_s50, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  arrange(size_category)

# Calculate percentage (handle case where sum is 0)
total_s50_2024 <- sum(table_2024$idcr_insolvent_s50)
if (total_s50_2024 > 0) {
  table_2024 <- table_2024 %>%
    mutate(pct_s50 = 100 * idcr_insolvent_s50 / total_s50_2024)
} else {
  table_2024 <- table_2024 %>%
    mutate(pct_s50 = 0)
}

# Display table
print(table_2024)
## # A tibble: 10 × 6
##    size_category total_banks mv_insolvent idcr_insolvent_s100 idcr_insolvent_s50
##    <fct>               <int>        <int>               <int>              <int>
##  1 $250B-$700B             5            2                   1                  0
##  2 $100B-$250B            13            8                   4                  1
##  3 $50B-$100B             15            8                   4                  1
##  4 $20B-$50B              45           18                   9                  3
##  5 $10B-$20B              57           26                  15                  4
##  6 $5B-$10B              112           62                  33                  9
##  7 $3B-$5B               114           66                  32                  5
##  8 $1B-$3B               562          328                 166                 28
##  9 $500M-$1B             717          384                 237                 31
## 10 Below $500M          2652         1113                 709                 97
## # ℹ 1 more variable: pct_s50 <dbl>
# Calculate totals row
totals_2024 <- table_2024 %>%
  summarise(
    size_category = "Total",
    total_banks = sum(total_banks),
    mv_insolvent = sum(mv_insolvent),
    idcr_insolvent_s100 = sum(idcr_insolvent_s100),
    idcr_insolvent_s50 = sum(idcr_insolvent_s50),
    pct_s50 = 100
  )

table_2024_with_totals <- bind_rows(table_2024, totals_2024)

# Format and display with kable
table_2024_with_totals %>%
  mutate(pct_s50 = sprintf("%.1f%%", pct_s50)) %>%
  kable(
    caption = "Table 2: Insolvent Banks by Size - January 1 - March 31, 2024",
    col.names = c("Asset Size", "Total Banks", "All Assets Liquidated", 
                  "100% Uninsured Run", "50% Uninsured Run", "Percentage"),
    align = c("l", rep("r", 5)),
    format.args = list(big.mark = ",")
  ) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  row_spec(nrow(table_2024_with_totals), bold = TRUE)
Table 2: Insolvent Banks by Size - January 1 - March 31, 2024
Asset Size Total Banks All Assets Liquidated 100% Uninsured Run 50% Uninsured Run Percentage
$250B-$700B 5 2 1 0 0.0%
$100B-$250B 13 8 4 1 0.6%
$50B-$100B 15 8 4 1 0.6%
$20B-$50B 45 18 9 3 1.7%
$10B-$20B 57 26 15 4 2.2%
$5B-$10B 112 62 33 9 5.0%
$3B-$5B 114 66 32 5 2.8%
$1B-$3B 562 328 166 28 15.6%
$500M-$1B 717 384 237 31 17.3%
Below $500M 2,652 1,113 709 97 54.2%
Total 4,292 2,015 1,210 179 100.0%
# Export to LaTeX
latex_2024 <- c(
  "\\begin{table}[htbp]",
  "\\centering",
  "\\caption{Insolvent Banks by Asset Size: January 1--March 31, 2024}",
  "\\label{tab:insolvency_size_2024q1}",
  "\\footnotesize",
  "",
  "\\begin{minipage}{0.95\\textwidth}",
  "\\smallskip",
  "This table reports the distribution of insolvent banks across asset size categories during",
  "January 1--March 31, 2024. Column (1) shows the total number of banks in each size bin.",
  "Columns (2)--(4) report the number of insolvent banks under three scenarios: (i) full liquidation of all",
  "assets at mark-to-market values, (ii) 100\\% uninsured depositor run, and",
  "(iii) 50\\% uninsured depositor run. Column (5) reports the percentage of insolvent banks",
  "under the 50\\% uninsured depositor run scenario relative to the total number of insolvent",
  "banks in that scenario.",
  "\\end{minipage}",
  "",
  "\\medskip",
  "\\begin{tabular}{l*{5}{c}}",
  "\\hline\\hline",
  "& (1) & (2) & (3) & (4) & (5) \\\\",
  "Asset Size ",
  "& Total Banks ",
  "& All Assets ",
  "& 100\\% Uninsured",
  "& 50\\% Uninsured ",
  "& Percentage \\\\",
  "",
  "& Banks ",
  "& Liquidated ",
  "&Deposit Run ",
  "& Deposit Run ",
  "& 50\\% Uninsured run \\\\",
  "\\hline",
  ""
)

for (i in 1:nrow(table_2024)) {
  row <- table_2024[i, ]
  latex_2024 <- c(
    latex_2024,
    sprintf("%s & %d & %d & %d & %d & %.1f\\%% \\\\",
            row$size_category,
            row$total_banks,
            row$mv_insolvent,
            row$idcr_insolvent_s100,
            row$idcr_insolvent_s50,
            row$pct_s50)
  )
}

latex_2024 <- c(
  latex_2024,
  "\\hline",
  "",
  sprintf("Number of Banks & %d & %d & %d & %d & 100\\%% \\\\",
          totals_2024$total_banks,
          totals_2024$mv_insolvent,
          totals_2024$idcr_insolvent_s100,
          totals_2024$idcr_insolvent_s50),
  "\\hline\\hline",
  "\\end{tabular}",
  "",
  "\\begin{minipage}{0.95\\textwidth}",
  "\\smallskip",
  "\\footnotesize",
  "\\textit{Note:} Insolvency in Column (2) is defined as mark-to-market (MTM) asset values being",
  "insufficient to cover total non-equity liabilities. In Column (3), the assumption is that all",
  "Uninsured depositors run; insolvency occurs if remaining insured deposits cannot be repaid from",
  "MTM asset values. In Column (4), only 50\\% of uninsured deposits run. The final column shows the",
  "distribution of insolvent banks in Column (4) as a percentage of all insolvent banks under that",
  "scenario. All insolvency measures are based on 2022Q4 balance sheet data. Sample excludes G-SIBs,",
  "failed banks, and banks without BTFP-eligible securities. This period includes both",
  "the Arbitrage period (through January 24) and Wind-down period (January 25 onwards).",
  "Borrower identification includes BTFP, DW, and FHLB users (10\\% threshold).",
  "\\end{minipage}",
  "",
  "\\end{table}"
)

writeLines(latex_2024, file.path(TABLE_PATH, "insolvency_size_2024q1.tex"))
cat("\n2024 period table saved to:", file.path(TABLE_PATH, "insolvency_size_2024q1.tex"), "\n")
## 
## 2024 period table saved to: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/insolvency_size_2024q1.tex
# --------------------------------------------------------------------------
# SUMMARY STATISTICS
# --------------------------------------------------------------------------

cat("\n", strrep("=", 70), "\n")
## 
##  ======================================================================
cat("SUMMARY STATISTICS\n")
## SUMMARY STATISTICS
cat(strrep("=", 70), "\n\n")
## ======================================================================
cat("--- Acute Period (March 13 - May 1, 2023) ---\n")
## --- Acute Period (March 13 - May 1, 2023) ---
cat(sprintf("Total banks: %d\n", totals_acute$total_banks))
## Total banks: 4292
cat(sprintf("MV Insolvent (All Assets Liquidated): %d (%.1f%%)\n", 
            totals_acute$mv_insolvent, 
            100 * totals_acute$mv_insolvent / totals_acute$total_banks))
## MV Insolvent (All Assets Liquidated): 2015 (46.9%)
cat(sprintf("IDCR Insolvent (100%% Uninsured Run): %d (%.1f%%)\n", 
            totals_acute$idcr_insolvent_s100, 
            100 * totals_acute$idcr_insolvent_s100 / totals_acute$total_banks))
## IDCR Insolvent (100% Uninsured Run): 1210 (28.2%)
cat(sprintf("IDCR Insolvent (50%% Uninsured Run): %d (%.1f%%)\n\n", 
            totals_acute$idcr_insolvent_s50, 
            100 * totals_acute$idcr_insolvent_s50 / totals_acute$total_banks))
## IDCR Insolvent (50% Uninsured Run): 179 (4.2%)
cat("--- January 1 - March 31, 2024 ---\n")
## --- January 1 - March 31, 2024 ---
cat(sprintf("Total banks: %d\n", totals_2024$total_banks))
## Total banks: 4292
cat(sprintf("MV Insolvent (All Assets Liquidated): %d (%.1f%%)\n", 
            totals_2024$mv_insolvent, 
            100 * totals_2024$mv_insolvent / totals_2024$total_banks))
## MV Insolvent (All Assets Liquidated): 2015 (46.9%)
cat(sprintf("IDCR Insolvent (100%% Uninsured Run): %d (%.1f%%)\n", 
            totals_2024$idcr_insolvent_s100, 
            100 * totals_2024$idcr_insolvent_s100 / totals_2024$total_banks))
## IDCR Insolvent (100% Uninsured Run): 1210 (28.2%)
cat(sprintf("IDCR Insolvent (50%% Uninsured Run): %d (%.1f%%)\n", 
            totals_2024$idcr_insolvent_s50, 
            100 * totals_2024$idcr_insolvent_s50 / totals_2024$total_banks))
## IDCR Insolvent (50% Uninsured Run): 179 (4.2%)
cat("\n=== TABLES GENERATED SUCCESSFULLY ===\n")
## 
## === TABLES GENERATED SUCCESSFULLY ===
# ==============================================================================
# BORROWERS BY SIZE AND INSOLVENCY CATEGORY - TWO PERIODS
# ==============================================================================

cat("\n", strrep("=", 70), "\n")
## 
##  ======================================================================
cat("BORROWERS BY SIZE AND INSOLVENCY CATEGORY\n")
## BORROWERS BY SIZE AND INSOLVENCY CATEGORY
cat(strrep("=", 70), "\n\n")
## ======================================================================
# --------------------------------------------------------------------------
# SIZE CATEGORY DEFINITIONS (from LaTeX table)
# --------------------------------------------------------------------------

create_size_category <- function(assets_thousands) {
  # Convert thousands to millions for comparison
  assets_millions <- assets_thousands / 1000
  
  case_when(
    assets_millions >= 700000 ~ "$700B and Above",
    assets_millions >= 250000 ~ "$250B-$700B",
    assets_millions >= 100000 ~ "$100B-$250B",
    assets_millions >= 50000  ~ "$50B-$100B",
    assets_millions >= 20000  ~ "$20B-$50B",
    assets_millions >= 10000  ~ "$10B-$20B",
    assets_millions >= 5000   ~ "$5B-$10B",
    assets_millions >= 3000   ~ "$3B-$5B",
    assets_millions >= 1000   ~ "$1B-$3B",
    assets_millions >= 500    ~ "$500M-$1B",
    TRUE                      ~ "Below $500M"
  )
}

# Define factor levels to ensure proper ordering
size_levels <- c(
  "$700B and Above",
  "$250B-$700B",
  "$100B-$250B",
  "$50B-$100B",
  "$20B-$50B",
  "$10B-$20B",
  "$5B-$10B",
  "$3B-$5B",
  "$1B-$3B",
  "$500M-$1B",
  "Below $500M"
)

# --------------------------------------------------------------------------
# PREPARE BASELINE WITH INSOLVENCY MEASURES (2022Q4)
# --------------------------------------------------------------------------

baseline_insolvency <- call_q %>%
  filter(period == '2022Q4') %>%
  filter(
    gsib == 0 | is.na(gsib),
    failed_bank == 0 | is.na(failed_bank),
    !is.na(omo_eligible) & omo_eligible > 0
  ) %>%
  mutate(
    # Size category
    size_category = create_size_category(total_asset),
    size_category = factor(size_category, levels = size_levels),
    
    # Insolvency measures
    adjusted_book_value = mm_asset - total_liability,
    mv_insolvent = as.integer(adjusted_book_value < 0),
    
    idcr_s50 = safe_div(mm_asset - 0.5 * uninsured_deposit - insured_deposit, insured_deposit),
    idcr_s100 = safe_div(mm_asset - 1.0 * uninsured_deposit - insured_deposit, insured_deposit),
    
    idcr_insolvent_s50 = as.integer(idcr_s50 < 0),
    idcr_insolvent_s100 = as.integer(idcr_s100 < 0)
  )

cat("Baseline data prepared:\n")
## Baseline data prepared:
cat(sprintf("  Total banks: %d\n", nrow(baseline_insolvency)))
##   Total banks: 4292
cat(sprintf("  MV Insolvent: %d\n", sum(baseline_insolvency$mv_insolvent, na.rm = TRUE)))
##   MV Insolvent: 2015
cat(sprintf("  IDCR Insolvent (s=1.0): %d\n", sum(baseline_insolvency$idcr_insolvent_s100, na.rm = TRUE)))
##   IDCR Insolvent (s=1.0): 1210
cat(sprintf("  IDCR Insolvent (s=0.5): %d\n", sum(baseline_insolvency$idcr_insolvent_s50, na.rm = TRUE)))
##   IDCR Insolvent (s=0.5): 179
# --------------------------------------------------------------------------
# TABLE 1: ACUTE PERIOD (March 13 - May 1, 2023)
# --------------------------------------------------------------------------

cat("\n", strrep("=", 70), "\n")
## 
##  ======================================================================
cat("TABLE 1: BORROWERS BY SIZE AND INSOLVENCY - ACUTE PERIOD\n")
## TABLE 1: BORROWERS BY SIZE AND INSOLVENCY - ACUTE PERIOD
cat(strrep("=", 70), "\n\n")
## ======================================================================
# Define acute period
acute_start <- as.Date("2023-03-13")
acute_end <- as.Date("2023-05-01")

# Identify borrowers
btfp_acute <- btfp_loans_raw %>%
  filter(btfp_loan_date >= acute_start & btfp_loan_date <= acute_end) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

dw_acute <- dw_loans_raw %>%
  filter(dw_loan_date >= acute_start & dw_loan_date <= acute_end) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

cat(sprintf("BTFP borrowers: %d\n", length(btfp_acute)))
## BTFP borrowers: 492
cat(sprintf("DW borrowers: %d\n", length(dw_acute)))
## DW borrowers: 424
# Add borrower classification
acute_data <- baseline_insolvency %>%
  mutate(
    btfp_user = idrssd %in% btfp_acute,
    dw_user = idrssd %in% dw_acute,
    borrower_type = case_when(
      btfp_user & dw_user ~ "Both",
      btfp_user & !dw_user ~ "BTFP Only",
      !btfp_user & dw_user ~ "DW Only",
      TRUE ~ "Non-Borrower"
    ),
    borrower_type = factor(borrower_type, levels = c("BTFP Only", "DW Only", "Both", "Non-Borrower"))
  )

# Create summary tables by size, borrower type, and insolvency status

# Panel A: All Assets Liquidated (MV Insolvent)
table1a <- acute_data %>%
  group_by(size_category, borrower_type) %>%
  summarise(
    total = n(),
    insolvent = sum(mv_insolvent, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  pivot_wider(
    names_from = borrower_type,
    values_from = c(total, insolvent),
    values_fill = 0
  ) %>%
  arrange(size_category)

cat("\n--- Panel A: All Assets Liquidated (MV Insolvent) ---\n")
## 
## --- Panel A: All Assets Liquidated (MV Insolvent) ---
print(table1a)
## # A tibble: 10 × 9
##    size_category `total_BTFP Only` `total_DW Only` `total_Non-Borrower`
##    <fct>                     <int>           <int>                <int>
##  1 $250B-$700B                   1               1                    3
##  2 $100B-$250B                   2               2                    7
##  3 $50B-$100B                    4               1                    8
##  4 $20B-$50B                     7               4                   27
##  5 $10B-$20B                     6              16                   26
##  6 $5B-$10B                     14              17                   74
##  7 $3B-$5B                      13              25                   73
##  8 $1B-$3B                      78              70                  387
##  9 $500M-$1B                    81              59                  563
## 10 Below $500M                 162             104                 2363
## # ℹ 5 more variables: total_Both <int>, `insolvent_BTFP Only` <int>,
## #   `insolvent_DW Only` <int>, `insolvent_Non-Borrower` <int>,
## #   insolvent_Both <int>
# Panel B: 100% Uninsured Run (IDCR s=1.0)
table1b <- acute_data %>%
  group_by(size_category, borrower_type) %>%
  summarise(
    total = n(),
    insolvent = sum(idcr_insolvent_s100, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  pivot_wider(
    names_from = borrower_type,
    values_from = c(total, insolvent),
    values_fill = 0
  ) %>%
  arrange(size_category)

cat("\n--- Panel B: 100% Uninsured Run (IDCR s=1.0) ---\n")
## 
## --- Panel B: 100% Uninsured Run (IDCR s=1.0) ---
print(table1b)
## # A tibble: 10 × 9
##    size_category `total_BTFP Only` `total_DW Only` `total_Non-Borrower`
##    <fct>                     <int>           <int>                <int>
##  1 $250B-$700B                   1               1                    3
##  2 $100B-$250B                   2               2                    7
##  3 $50B-$100B                    4               1                    8
##  4 $20B-$50B                     7               4                   27
##  5 $10B-$20B                     6              16                   26
##  6 $5B-$10B                     14              17                   74
##  7 $3B-$5B                      13              25                   73
##  8 $1B-$3B                      78              70                  387
##  9 $500M-$1B                    81              59                  563
## 10 Below $500M                 162             104                 2363
## # ℹ 5 more variables: total_Both <int>, `insolvent_BTFP Only` <int>,
## #   `insolvent_DW Only` <int>, `insolvent_Non-Borrower` <int>,
## #   insolvent_Both <int>
# Panel C: 50% Uninsured Run (IDCR s=0.5)
table1c <- acute_data %>%
  group_by(size_category, borrower_type) %>%
  summarise(
    total = n(),
    insolvent = sum(idcr_insolvent_s50, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  pivot_wider(
    names_from = borrower_type,
    values_from = c(total, insolvent),
    values_fill = 0
  ) %>%
  arrange(size_category)

cat("\n--- Panel C: 50% Uninsured Run (IDCR s=0.5) ---\n")
## 
## --- Panel C: 50% Uninsured Run (IDCR s=0.5) ---
print(table1c)
## # A tibble: 10 × 9
##    size_category `total_BTFP Only` `total_DW Only` `total_Non-Borrower`
##    <fct>                     <int>           <int>                <int>
##  1 $250B-$700B                   1               1                    3
##  2 $100B-$250B                   2               2                    7
##  3 $50B-$100B                    4               1                    8
##  4 $20B-$50B                     7               4                   27
##  5 $10B-$20B                     6              16                   26
##  6 $5B-$10B                     14              17                   74
##  7 $3B-$5B                      13              25                   73
##  8 $1B-$3B                      78              70                  387
##  9 $500M-$1B                    81              59                  563
## 10 Below $500M                 162             104                 2363
## # ℹ 5 more variables: total_Both <int>, `insolvent_BTFP Only` <int>,
## #   `insolvent_DW Only` <int>, `insolvent_Non-Borrower` <int>,
## #   insolvent_Both <int>
# Create comprehensive table for export
table1_comprehensive <- acute_data %>%
  group_by(size_category, borrower_type) %>%
  summarise(
    N = n(),
    MV_Insolvent = sum(mv_insolvent, na.rm = TRUE),
    IDCR_s100_Insolvent = sum(idcr_insolvent_s100, na.rm = TRUE),
    IDCR_s50_Insolvent = sum(idcr_insolvent_s50, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  arrange(size_category, borrower_type)

# Display comprehensive table
cat("\n--- Comprehensive Table: All Insolvency Measures ---\n")
## 
## --- Comprehensive Table: All Insolvency Measures ---
table1_comprehensive %>%
  kable(
    caption = "Table 1: Borrowers by Size and Insolvency Status - Acute Period (March 13 - May 1, 2023)",
    col.names = c("Asset Size", "Borrower Type", "N", "MV Insolvent", "IDCR s=1.0", "IDCR s=0.5"),
    align = c("l", "l", rep("r", 4))
  ) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  collapse_rows(columns = 1, valign = "top")
Table 1: Borrowers by Size and Insolvency Status - Acute Period (March 13 - May 1, 2023)
Asset Size Borrower Type N MV Insolvent IDCR s=1.0 IDCR s=0.5
$250B-$700B BTFP Only 1 1 0 0
DW Only 1 0 0 0
Non-Borrower 3 1 1 0
$100B-$250B BTFP Only 2 0 0 0
DW Only 2 2 1 0
Both 2 1 0 0
Non-Borrower 7 5 3 1
$50B-$100B BTFP Only 4 1 0 0
DW Only 1 0 0 0
Both 2 1 1 0
Non-Borrower 8 6 3 1
$20B-$50B BTFP Only 7 5 1 1
DW Only 4 2 1 0
Both 7 3 2 1
Non-Borrower 27 8 5 1
$10B-$20B BTFP Only 6 4 1 0
DW Only 16 7 4 1
Both 9 4 2 0
Non-Borrower 26 11 8 3
$5B-$10B BTFP Only 14 10 6 2
DW Only 17 11 8 2
Both 7 7 2 1
Non-Borrower 74 34 17 4
$3B-$5B BTFP Only 13 7 2 0
DW Only 25 14 8 3
Both 3 2 1 0
Non-Borrower 73 43 21 2
$1B-$3B BTFP Only 78 54 26 3
DW Only 70 39 22 7
Both 27 18 6 1
Non-Borrower 387 217 112 17
$500M-$1B BTFP Only 81 48 24 3
DW Only 59 36 21 4
Both 14 9 3 0
Non-Borrower 563 291 189 24
Below $500M BTFP Only 162 94 47 4
DW Only 104 56 34 4
Both 23 14 6 0
Non-Borrower 2363 949 622 89
# Export to LaTeX
latex_acute <- c(
  "\\begin{table}[htbp]",
  "\\centering",
  "\\caption{Borrowers by Asset Size and Insolvency Status: Acute Period (March 13--May 1, 2023)}",
  "\\label{tab:borrower_size_insolvency_acute}",
  "\\footnotesize",
  "\\begin{tabular}{llrrrr}",
  "\\hline\\hline",
  "Asset Size & Borrower Type & N & MV Insol. & IDCR s=1.0 & IDCR s=0.5 \\\\",
  "\\hline"
)

current_size <- ""
for (i in 1:nrow(table1_comprehensive)) {
  row <- table1_comprehensive[i, ]
  size_display <- if (row$size_category != current_size) as.character(row$size_category) else ""
  current_size <- row$size_category
  
  latex_acute <- c(
    latex_acute,
    sprintf("%s & %s & %d & %d & %d & %d \\\\",
            size_display,
            row$borrower_type,
            row$N,
            row$MV_Insolvent,
            row$IDCR_s100_Insolvent,
            row$IDCR_s50_Insolvent)
  )
  
  # Add midrule between size categories
  if (i < nrow(table1_comprehensive) && 
      table1_comprehensive$size_category[i+1] != current_size) {
    latex_acute <- c(latex_acute, "\\midrule")
  }
}

latex_acute <- c(
  latex_acute,
  "\\hline\\hline",
  "\\end{tabular}",
  "\\begin{minipage}{0.95\\textwidth}",
  "\\smallskip",
  "\\footnotesize",
  "\\textit{Note:} This table reports the number of banks by asset size, borrower type, and insolvency status",
  "during the acute crisis period (March 13--May 1, 2023). MV Insol. = Mark-to-market insolvency",
  "(adjusted book value < 0). IDCR s=1.0 = Insolvent under 100\\% uninsured depositor run.",
  "IDCR s=0.5 = Insolvent under 50\\% uninsured depositor run. All insolvency measures based on 2022Q4",
  "balance sheet data. Sample excludes G-SIBs, failed banks, and banks without BTFP-eligible securities.",
  "\\end{minipage}",
  "\\end{table}"
)

writeLines(latex_acute, file.path(TABLE_PATH, "borrower_size_insolvency_acute.tex"))
cat("\nAcute period table saved to:", file.path(TABLE_PATH, "borrower_size_insolvency_acute.tex"), "\n")
## 
## Acute period table saved to: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/borrower_size_insolvency_acute.tex
# --------------------------------------------------------------------------
# TABLE 2: JANUARY 1 - MARCH 31, 2024
# Includes BTFP, DW, and FHLB (10% threshold)
# --------------------------------------------------------------------------

cat("\n", strrep("=", 70), "\n")
## 
##  ======================================================================
cat("TABLE 2: BORROWERS BY SIZE AND INSOLVENCY - JAN 1 - MARCH 31, 2024\n")
## TABLE 2: BORROWERS BY SIZE AND INSOLVENCY - JAN 1 - MARCH 31, 2024
cat(strrep("=", 70), "\n\n")
## ======================================================================
# Define period
period_2024_start <- as.Date("2024-01-01")
period_2024_end <- as.Date("2024-03-31")

# Identify borrowers
btfp_2024 <- btfp_loans_raw %>%
  filter(btfp_loan_date >= period_2024_start & btfp_loan_date <= period_2024_end) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

dw_2024 <- dw_loans_raw %>%
  filter(dw_loan_date >= period_2024_start & dw_loan_date <= period_2024_end) %>%
  distinct(rssd_id) %>%
  pull(rssd_id)

fhlb_borrowers_10pct <- call_q %>%
  filter(period == '2022Q4') %>%
  filter(
    gsib == 0 | is.na(gsib),
    failed_bank == 0 | is.na(failed_bank),
    !is.na(omo_eligible) & omo_eligible > 0,
    !is.na(abnormal_fhlb_borrowing_10pct) & abnormal_fhlb_borrowing_10pct > 0
  ) %>%
  pull(idrssd)

cat(sprintf("BTFP borrowers: %d\n", length(btfp_2024)))
## BTFP borrowers: 717
cat(sprintf("DW borrowers: %d\n", length(dw_2024)))
## DW borrowers: 0
cat(sprintf("FHLB borrowers (10%% threshold): %d\n", length(fhlb_borrowers_10pct)))
## FHLB borrowers (10% threshold): 302
# Add borrower classification
data_2024 <- baseline_insolvency %>%
  mutate(
    btfp_user = idrssd %in% btfp_2024,
    dw_user = idrssd %in% dw_2024,
    fhlb_user = idrssd %in% fhlb_borrowers_10pct,
    borrower_type = case_when(
      btfp_user & dw_user & fhlb_user ~ "All Three",
      btfp_user & dw_user & !fhlb_user ~ "BTFP+DW",
      btfp_user & !dw_user & fhlb_user ~ "BTFP+FHLB",
      !btfp_user & dw_user & fhlb_user ~ "DW+FHLB",
      btfp_user & !dw_user & !fhlb_user ~ "BTFP Only",
      !btfp_user & dw_user & !fhlb_user ~ "DW Only",
      !btfp_user & !dw_user & fhlb_user ~ "FHLB Only",
      TRUE ~ "Non-Borrower"
    ),
    borrower_type = factor(borrower_type, 
                          levels = c("BTFP Only", "DW Only", "FHLB Only",
                                   "BTFP+DW", "BTFP+FHLB", "DW+FHLB",
                                   "All Three", "Non-Borrower"))
  )

# Create comprehensive table
table2_comprehensive <- data_2024 %>%
  group_by(size_category, borrower_type) %>%
  summarise(
    N = n(),
    MV_Insolvent = sum(mv_insolvent, na.rm = TRUE),
    IDCR_s100_Insolvent = sum(idcr_insolvent_s100, na.rm = TRUE),
    IDCR_s50_Insolvent = sum(idcr_insolvent_s50, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  arrange(size_category, borrower_type)

# Display comprehensive table
cat("\n--- Comprehensive Table: All Insolvency Measures ---\n")
## 
## --- Comprehensive Table: All Insolvency Measures ---
table2_comprehensive %>%
  kable(
    caption = "Table 2: Borrowers by Size and Insolvency Status - January 1 - March 31, 2024",
    col.names = c("Asset Size", "Borrower Type", "N", "MV Insolvent", "IDCR s=1.0", "IDCR s=0.5"),
    align = c("l", "l", rep("r", 4))
  ) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  collapse_rows(columns = 1, valign = "top") %>%
  scroll_box(width = "100%")
Table 2: Borrowers by Size and Insolvency Status - January 1 - March 31, 2024
Asset Size Borrower Type N MV Insolvent IDCR s=1.0 IDCR s=0.5
$250B-$700B BTFP Only 1 0 0 0
Non-Borrower 4 2 1 0
$100B-$250B FHLB Only 1 0 0 0
Non-Borrower 12 8 4 1
$50B-$100B BTFP Only 1 0 0 0
FHLB Only 2 1 1 0
Non-Borrower 12 7 3 1
$20B-$50B BTFP Only 10 5 3 1
FHLB Only 7 4 1 0
BTFP+FHLB 1 0 0 0
Non-Borrower 27 9 5 2
$10B-$20B BTFP Only 13 6 4 0
FHLB Only 7 2 2 0
BTFP+FHLB 2 1 0 0
Non-Borrower 35 17 9 4
$5B-$10B BTFP Only 29 15 7 2
FHLB Only 11 4 4 1
BTFP+FHLB 3 1 0 0
Non-Borrower 69 42 22 6
$3B-$5B BTFP Only 24 14 2 0
FHLB Only 8 3 3 0
BTFP+FHLB 2 1 0 0
Non-Borrower 80 48 27 5
$1B-$3B BTFP Only 124 77 37 4
FHLB Only 31 14 9 3
BTFP+FHLB 19 10 5 0
Non-Borrower 388 227 115 21
$500M-$1B BTFP Only 137 86 51 7
FHLB Only 40 23 11 1
BTFP+FHLB 17 8 6 2
Non-Borrower 523 267 169 21
Below $500M BTFP Only 281 157 92 11
FHLB Only 131 49 30 5
BTFP+FHLB 20 12 6 2
Non-Borrower 2220 895 581 79
# Export to LaTeX
latex_2024 <- c(
  "\\begin{table}[htbp]",
  "\\centering",
  "\\caption{Borrowers by Asset Size and Insolvency Status: January 1--March 31, 2024}",
  "\\label{tab:borrower_size_insolvency_2024q1}",
  "\\footnotesize",
  "\\begin{tabular}{llrrrr}",
  "\\hline\\hline",
  "Asset Size & Borrower Type & N & MV Insol. & IDCR s=1.0 & IDCR s=0.5 \\\\",
  "\\hline"
)

current_size <- ""
for (i in 1:nrow(table2_comprehensive)) {
  row <- table2_comprehensive[i, ]
  size_display <- if (row$size_category != current_size) as.character(row$size_category) else ""
  current_size <- row$size_category
  
  latex_2024 <- c(
    latex_2024,
    sprintf("%s & %s & %d & %d & %d & %d \\\\",
            size_display,
            row$borrower_type,
            row$N,
            row$MV_Insolvent,
            row$IDCR_s100_Insolvent,
            row$IDCR_s50_Insolvent)
  )
  
  # Add midrule between size categories
  if (i < nrow(table2_comprehensive) && 
      table2_comprehensive$size_category[i+1] != current_size) {
    latex_2024 <- c(latex_2024, "\\midrule")
  }
}

latex_2024 <- c(
  latex_2024,
  "\\hline\\hline",
  "\\end{tabular}",
  "\\begin{minipage}{0.95\\textwidth}",
  "\\smallskip",
  "\\footnotesize",
  "\\textit{Note:} This table reports the number of banks by asset size, borrower type, and insolvency status",
  "during January 1--March 31, 2024. MV Insol. = Mark-to-market insolvency (adjusted book value < 0).",
  "IDCR s=1.0 = Insolvent under 100\\% uninsured depositor run. IDCR s=0.5 = Insolvent under 50\\% uninsured",
  "depositor run. All insolvency measures based on 2022Q4 balance sheet data. FHLB borrowers identified",
  "using 10\\% threshold (90th percentile). Sample excludes G-SIBs, failed banks, and banks without",
  "BTFP-eligible securities.",
  "\\end{minipage}",
  "\\end{table}"
)

writeLines(latex_2024, file.path(TABLE_PATH, "borrower_size_insolvency_2024q1.tex"))
cat("\n2024 period table saved to:", file.path(TABLE_PATH, "borrower_size_insolvency_2024q1.tex"), "\n")
## 
## 2024 period table saved to: C:/Users/mferdo2/OneDrive - Louisiana State University/Finance_PhD/DW_Stigma_paper/Liquidity_project_2025/03_documentation/borrowing_t_stat/tables/borrower_size_insolvency_2024q1.tex
# --------------------------------------------------------------------------
# SUMMARY STATISTICS
# --------------------------------------------------------------------------

cat("\n", strrep("=", 70), "\n")
## 
##  ======================================================================
cat("SUMMARY STATISTICS BY BORROWER TYPE AND INSOLVENCY\n")
## SUMMARY STATISTICS BY BORROWER TYPE AND INSOLVENCY
cat(strrep("=", 70), "\n\n")
## ======================================================================
cat("--- Acute Period ---\n")
## --- Acute Period ---
acute_summary <- table1_comprehensive %>%
  group_by(borrower_type) %>%
  summarise(
    Total = sum(N),
    MV_Insol = sum(MV_Insolvent),
    MV_Pct = 100 * MV_Insol / Total,
    IDCR_100 = sum(IDCR_s100_Insolvent),
    IDCR_100_Pct = 100 * IDCR_100 / Total,
    IDCR_50 = sum(IDCR_s50_Insolvent),
    IDCR_50_Pct = 100 * IDCR_50 / Total,
    .groups = "drop"
  )
print(acute_summary)
## # A tibble: 4 × 8
##   borrower_type Total MV_Insol MV_Pct IDCR_100 IDCR_100_Pct IDCR_50 IDCR_50_Pct
##   <fct>         <int>    <int>  <dbl>    <int>        <dbl>   <int>       <dbl>
## 1 BTFP Only       368      224   60.9      107         29.1      13        3.53
## 2 DW Only         299      167   55.9       99         33.1      21        7.02
## 3 Both             94       59   62.8       23         24.5       3        3.19
## 4 Non-Borrower   3531     1565   44.3      981         27.8     142        4.02
cat("\n--- January 1 - March 31, 2024 ---\n")
## 
## --- January 1 - March 31, 2024 ---
summary_2024 <- table2_comprehensive %>%
  group_by(borrower_type) %>%
  summarise(
    Total = sum(N),
    MV_Insol = sum(MV_Insolvent),
    MV_Pct = 100 * MV_Insol / Total,
    IDCR_100 = sum(IDCR_s100_Insolvent),
    IDCR_100_Pct = 100 * IDCR_100 / Total,
    IDCR_50 = sum(IDCR_s50_Insolvent),
    IDCR_50_Pct = 100 * IDCR_50 / Total,
    .groups = "drop"
  )
print(summary_2024)
## # A tibble: 4 × 8
##   borrower_type Total MV_Insol MV_Pct IDCR_100 IDCR_100_Pct IDCR_50 IDCR_50_Pct
##   <fct>         <int>    <int>  <dbl>    <int>        <dbl>   <int>       <dbl>
## 1 BTFP Only       620      360   58.1      196         31.6      25        4.03
## 2 FHLB Only       238      100   42.0       61         25.6      10        4.20
## 3 BTFP+FHLB        64       33   51.6       17         26.6       4        6.25
## 4 Non-Borrower   3370     1522   45.2      936         27.8     140        4.15
cat("\n=== TABLES GENERATED SUCCESSFULLY ===\n")
## 
## === TABLES GENERATED SUCCESSFULLY ===