Exploratory Data Analysis

library(data.table)
library(ggplot2)
library(stargazer)
library(patchwork)



# Load data


OUTPUT_DIR <- "/Users/amalianimeskern/Library/CloudStorage/OneDrive-ErasmusUniversityRotterdam/Freddie Mac Data"

panel <- readRDS(file.path(OUTPUT_DIR, "freddie_mac_panel.rds"))

# Dataset is restricted to properties in the 50 U.S. states and DC
# Loans in U.S. territories (PR, GU, VI) are excluded

# Number of unique loans
panel[, uniqueN(loan_sequence_number)]
## [1] 240565
# --- Geography Analysis ---

setdiff(unique(panel$property_state),
        c("AL","AK","AZ","AR","CA","CO","CT","DE","FL","GA",
          "HI","ID","IL","IN","IA","KS","KY","LA","ME","MD",
          "MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ",
          "NM","NY","NC","ND","OH","OK","OR","PA","RI","SC",
          "SD","TN","TX","UT","VT","VA","WA","WV","WI","WY","DC"))
## character(0)
# Expected output: character(0)

# --- Missingness ---

missingness <- data.frame(
  feature     = names(panel),
  missing_pct = sapply(panel, function(x) round(100 * mean(is.na(x)), 2))
)
missingness <- missingness[order(-missingness$missing_pct), ]
print(missingness)
##                                               feature missing_pct
## zero_balance_code                   zero_balance_code       98.64
## first_default_index               first_default_index       94.65
## orig_dti                                     orig_dti        6.19
## orig_loan_term                         orig_loan_term        0.09
## credit_score                             credit_score        0.07
## num_borrowers                           num_borrowers        0.03
## first_time_homebuyer             first_time_homebuyer        0.02
## orig_cltv                                   orig_cltv        0.01
## orig_ltv                                     orig_ltv        0.01
## property_state                         property_state        0.00
## monthly_reporting_period     monthly_reporting_period        0.00
## loan_sequence_number             loan_sequence_number        0.00
## current_upb                               current_upb        0.00
## current_delinquency_status current_delinquency_status        0.00
## loan_age                                     loan_age        0.00
## current_deferred_upb             current_deferred_upb        0.00
## delta_interest_rate               delta_interest_rate        0.00
## mod_flag_12m                             mod_flag_12m        0.00
## month_index                               month_index        0.00
## default_next_12m                     default_next_12m        0.00
## first_payment_date                 first_payment_date        0.00
## mi_pct                                         mi_pct        0.00
## occupancy_status                     occupancy_status        0.00
## orig_upb                                     orig_upb        0.00
## orig_interest_rate                 orig_interest_rate        0.00
## channel                                       channel        0.00
## amortization_type                   amortization_type        0.00
## property_type                           property_type        0.00
## loan_purpose                             loan_purpose        0.00
## io_indicator                             io_indicator        0.00
## orig_year                                   orig_year        0.00
## orig_month                                 orig_month        0.00
## orig_quarter                             orig_quarter        0.00
## unemployment_rate_lag1         unemployment_rate_lag1        0.00
## unemployment_rate_lag2         unemployment_rate_lag2        0.00
## unemployment_rate_lag3         unemployment_rate_lag3        0.00
## unemployment_rate_lag4         unemployment_rate_lag4        0.00
## hpi_qoq_qlag1                           hpi_qoq_qlag1        0.00
## hpi_qoq_qlag2                           hpi_qoq_qlag2        0.00
## hpi_qoq_qlag3                           hpi_qoq_qlag3        0.00
## hpi_qoq_qlag4                           hpi_qoq_qlag4        0.00
key_vars <- c("credit_score", "orig_ltv", "orig_cltv", "orig_dti",
              "orig_interest_rate", "current_upb", "current_deferred_upb",
              "delta_interest_rate", "mod_flag_12m",
              paste0("unemployment_rate_lag", 1:4),
              paste0("hpi_qoq_qlag", 1:4))
miss_key <- missingness[missingness$feature %in% key_vars, ]
print(miss_key)
##                                       feature missing_pct
## orig_dti                             orig_dti        6.19
## credit_score                     credit_score        0.07
## orig_cltv                           orig_cltv        0.01
## orig_ltv                             orig_ltv        0.01
## current_upb                       current_upb        0.00
## current_deferred_upb     current_deferred_upb        0.00
## delta_interest_rate       delta_interest_rate        0.00
## mod_flag_12m                     mod_flag_12m        0.00
## orig_interest_rate         orig_interest_rate        0.00
## unemployment_rate_lag1 unemployment_rate_lag1        0.00
## unemployment_rate_lag2 unemployment_rate_lag2        0.00
## unemployment_rate_lag3 unemployment_rate_lag3        0.00
## unemployment_rate_lag4 unemployment_rate_lag4        0.00
## hpi_qoq_qlag1                   hpi_qoq_qlag1        0.00
## hpi_qoq_qlag2                   hpi_qoq_qlag2        0.00
## hpi_qoq_qlag3                   hpi_qoq_qlag3        0.00
## hpi_qoq_qlag4                   hpi_qoq_qlag4        0.00
# --- Class imbalance ---

# Observation level
table(panel$default_next_12m)
## 
##       0       1 
## 7295197   17768
prop.table(table(panel$default_next_12m)) * 100
## 
##          0          1 
## 99.7570343  0.2429657
# Loan level
panel[, .(ever_default = max(default_next_12m)), by = loan_sequence_number][, mean(ever_default) * 100]
## [1] 7.385946
# Average months
panel[, .N, by = loan_sequence_number][, summary(N)]
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##     1.0    18.0    28.0    30.4    41.0    72.0
# --- Default rate by origination year at the loan level ---
setorder(panel, loan_sequence_number, monthly_reporting_period)
cols_to_keep <- c("orig_year", "credit_score", "orig_ltv", "orig_cltv",
                  "orig_dti", "orig_interest_rate", "orig_upb", "orig_loan_term",
                  "num_borrowers", "mi_pct", "occupancy_status", "amortization_type",
                  "loan_purpose", "channel", "property_type",
                  "first_time_homebuyer", "io_indicator")
loan_level <- panel[, .(ever_default_12m = max(default_next_12m, na.rm = TRUE)),
                    by = loan_sequence_number]
first_obs <- panel[panel[, .I[1], by = loan_sequence_number]$V1,
                   c("loan_sequence_number", cols_to_keep), with = FALSE]
loan_level <- merge(loan_level, first_obs, by = "loan_sequence_number")

default_by_year <- loan_level[, .(
  n_loans      = .N,
  default_rate = round(100 * mean(ever_default_12m), 2)
), by = orig_year][order(orig_year)]
print(default_by_year)
##    orig_year n_loans default_rate
##        <int>   <int>        <num>
## 1:      2006   41258        12.12
## 2:      2007   49688        13.74
## 3:      2008   49999         9.02
## 4:      2009   49638         1.82
## 5:      2010   49982         1.05
ggplot(default_by_year, aes(x = orig_year, y = default_rate)) +
  geom_line() +
  geom_point() +
  labs(title = "Default Rate by Origination Year",
       x     = "Origination Year",
       y     = "Default Rate (%)") +
  theme_classic()

# --- Feature distributions by default status ---

# Origination variables, loan level
continuous_orig <- c("credit_score", "orig_ltv", "orig_dti", "orig_interest_rate")
feature_stats_orig <- rbindlist(lapply(continuous_orig, function(var) {
  loan_level[, .(
    variable        = var,
    mean_default    = round(mean(get(var)[ever_default_12m == 1], na.rm = TRUE), 2),
    mean_no_default = round(mean(get(var)[ever_default_12m == 0], na.rm = TRUE), 2),
    sd_default      = round(sd(get(var)[ever_default_12m == 1],   na.rm = TRUE), 2),
    sd_no_default   = round(sd(get(var)[ever_default_12m == 0],   na.rm = TRUE), 2)
  )]
}))
print(feature_stats_orig)
##              variable mean_default mean_no_default sd_default sd_no_default
##                <char>        <num>           <num>      <num>         <num>
## 1:       credit_score       690.72          745.61      55.62         51.54
## 2:           orig_ltv        77.99           68.54      13.42         18.08
## 3:           orig_dti        40.96           34.37      11.40         12.14
## 4: orig_interest_rate         6.41            5.70       0.55          0.81
# Behavioural and macro variables at the observation level
continuous_behav <- c("current_delinquency_status", "current_upb",
                      "delta_interest_rate", "mod_flag_12m",
                      "current_deferred_upb",
                      "unemployment_rate_lag1", "hpi_qoq_qlag1")
feature_stats_behav <- rbindlist(lapply(continuous_behav, function(var) {
  panel[, .(
    variable        = var,
    mean_default    = round(mean(get(var)[default_next_12m == 1], na.rm = TRUE), 2),
    mean_no_default = round(mean(get(var)[default_next_12m == 0], na.rm = TRUE), 2),
    sd_default      = round(sd(get(var)[default_next_12m == 1],   na.rm = TRUE), 2),
    sd_no_default   = round(sd(get(var)[default_next_12m == 0],   na.rm = TRUE), 2)
  )]
}))
print(feature_stats_behav)
##                      variable mean_default mean_no_default sd_default
##                        <char>        <num>           <num>      <num>
## 1: current_delinquency_status         0.12            0.01       0.37
## 2:                current_upb    198189.42       176828.25   98538.34
## 3:        delta_interest_rate        -0.01            0.00       0.15
## 4:               mod_flag_12m         0.00            0.00       0.02
## 5:       current_deferred_upb         4.57            3.91     537.48
## 6:     unemployment_rate_lag1         7.77            7.96       2.53
## 7:              hpi_qoq_qlag1        -1.76           -0.98       2.40
##    sd_no_default
##            <num>
## 1:          0.12
## 2:     102407.95
## 3:          0.09
## 4:          0.01
## 5:        653.89
## 6:          2.52
## 7:          1.87
# --- DTI distribution ---

ggplot(panel[!is.na(orig_dti)],
       aes(x = orig_dti)) +
  geom_histogram(binwidth = 2, fill = "orange", color = "white") +
  labs(title = "DTI Distribution", x = "DTI", y = "Count") +
  theme_classic()

# --- Delinquency status distribution ---

ggplot(panel[!is.na(current_delinquency_status)],
       aes(x = factor(current_delinquency_status),
           fill = factor(default_next_12m))) +
  geom_bar(position = "fill") +
  scale_fill_manual(values = c("steelblue", "orange"),
                    labels = c("No Default", "Default")) +
  labs(title = "12-Month Default Rate by Current Delinquency Status",
       x     = "Current Delinquency Status (months past due)",
       y     = "Proportion",
       fill  = "") +
  theme_classic()

# --- Macro controls over time ---

# Average lagged unemployment and HPI by month across all loans

macro_time <- panel[, .(
  unemp_lag1 = mean(unemployment_rate_lag1, na.rm = TRUE),
  unemp_lag2 = mean(unemployment_rate_lag2, na.rm = TRUE),
  unemp_lag3 = mean(unemployment_rate_lag3, na.rm = TRUE),
  unemp_lag4 = mean(unemployment_rate_lag4, na.rm = TRUE),
  hpi_lag1   = mean(hpi_qoq_qlag1, na.rm = TRUE),
  hpi_lag2   = mean(hpi_qoq_qlag2, na.rm = TRUE),
  hpi_lag3   = mean(hpi_qoq_qlag3, na.rm = TRUE),
  hpi_lag4   = mean(hpi_qoq_qlag4, na.rm = TRUE)
), by = monthly_reporting_period][order(monthly_reporting_period)]

macro_time[, date := as.Date(paste0(
  substr(as.character(monthly_reporting_period), 1, 4), "-",
  substr(as.character(monthly_reporting_period), 5, 6), "-01"
))]

# Reshaping to long format
unemp_long <- melt(macro_time, id.vars = "date",
                   measure.vars = paste0("unemp_lag", 1:4),
                   variable.name = "lag", value.name = "unemployment_rate")
unemp_long[, lag := factor(lag,
                           levels = paste0("unemp_lag", 1:4),
                           labels = paste0("Lag ", 1:4))]

hpi_long <- melt(macro_time, id.vars = "date",
                 measure.vars = paste0("hpi_lag", 1:4),
                 variable.name = "lag", value.name = "hpi_qoq")
hpi_long[, lag := factor(lag,
                         levels = paste0("hpi_lag", 1:4),
                         labels = paste0("Lag ", 1:4))]

p1 <- ggplot(unemp_long, aes(x = date, y = unemployment_rate)) +
  geom_line(color = "steelblue") +
  facet_wrap(~lag, ncol = 2) +
  labs(title = "Average State Unemployment Rate Over Time",
       x = "", y = "Unemployment Rate (%)") +
  theme_classic()

p2 <- ggplot(hpi_long, aes(x = date, y = hpi_qoq)) +
  geom_line(color = "darkorange") +
  geom_hline(yintercept = 0, linetype = "dashed", color = "grey50") +
  facet_wrap(~lag, ncol = 2) +
  labs(title = "Average State HPI QoQ Change Over Time",
       x = "", y = "HPI QoQ Change (%)") +
  theme_classic()

p1 / p2

# --- Variable dictionary ---

variable_dict <- data.frame(
  variable = c(
    "loan_sequence_number",
    "monthly_reporting_period",
    "month_index",
    "first_default_index",
    "first_payment_date",
    "orig_year",
    "orig_month",
    "orig_quarter",
    "credit_score", "orig_ltv", "orig_cltv", "orig_dti",
    "orig_interest_rate", "orig_upb", "orig_loan_term",
    "num_borrowers", "mi_pct", "occupancy_status",
    "amortization_type", "loan_purpose", "channel",
    "property_type", "property_state", "first_time_homebuyer",
    "io_indicator",
    "current_delinquency_status", "loan_age", "mod_flag_12m",
    "delta_interest_rate", "current_upb", "current_deferred_upb",
    "zero_balance_code",
    paste0("unemployment_rate_lag", 1:4),
    paste0("hpi_qoq_qlag", 1:4),
    "default_next_12m"
  ),
  type = c(
    rep("Identifier", 2),
    rep("Temporal", 6),
    rep("Origination", 17),
    rep("Behavioural", 7),
    rep("Macro", 8),
    "Outcome"
  ),
  description = c(
    "Unique loan identifier linking origination and performance records",
    "Year-month of the performance observation (YYYYMM)",
    "Linear month index from monthly_reporting_period; used to compute the forward default horizon",
    "Month index of the first default event (90+ DPD or zero balance code 03/09); NA if none observed",
    "Date of first scheduled payment (YYYYMM); source for orig_year, orig_month, orig_quarter",
    "Origination year, from first_payment_date",
    "Origination month, from first_payment_date",
    "Origination quarter (ordered factor, e.g. 2007Q3)",
    "Borrower FICO credit score at origination",
    "Original loan-to-value ratio (%)",
    "Original combined loan-to-value ratio incl. all liens (%); values > 200 recoded to NA",
    "Original debt-to-income ratio (%)",
    "Note rate at origination (%)",
    "Original unpaid principal balance (USD)",
    "Original loan term in months (360 = 30-year); values > 360 recoded to NA",
    "Number of borrowers (01 = 1, 02 = more than 1)",
    "Mortgage insurance coverage (%)",
    "Occupancy: P = primary residence, S = second home, I = investment property",
    "Amortization: FRM = fixed-rate, ARM = adjustable-rate",
    "Loan purpose: P = purchase, C = cash-out refi, N = no-cash-out refi",
    "Channel: R = retail, B = broker, C = correspondent, T = TPO not specified",
    "Property type: SF = single-family, PU = PUD, CO = condo, CP = co-op, MH = manufactured housing",
    "Two-letter US state code (50 states + DC; PR/GU/VI excluded)",
    "First-time homebuyer flag (Y/N)",
    "Interest-only indicator (Y/N)",
    "Delinquency status at month t (MBA method): 0 = current/<30d, 1 = 30-59d, 2 = 60-89d",
    "Loan age in months at month t, relative to the first payment date",
    "1 if the loan was modified at least once in the 12 months up to and including month t (first 11 months assume no prior modification)",
    "Current minus original interest rate at month t (%)",
    "Outstanding unpaid principal balance at month t (USD)",
    "Deferred principal balance at month t (USD)",
    "Termination code: 01 = prepaid/matured, 02 = third-party sale, 03 = short sale/charge-off, 09 = REO disposition, 15 = whole loan sale, 16 = RPL securitization, 96 = defect; NA if active",
    paste0("State-level monthly unemployment rate (%), lag ", 1:4, " month(s); FRED [STATE]UR"),
    paste0("State-level HPI quarter-over-quarter % change, lag ", 1:4, " quarter(s); FRED [STATE]STHPI"),
    "1 if the loan first reaches 90+ DPD (status >= 3) or a foreclosure-related termination (zero balance code 03/09) within 12 months of month t, else 0. Each defaulting loan is flagged once, at the earliest such month; the panel ends December 2011 to ensure a full 12-month outcome window"
  ),
  source = c(
    "Origination and Performance files",
    "Performance file (time-varying)",
    "Derived from monthly_reporting_period",
    "Derived from performance file",
    "Origination file",
    "Derived from origination file",
    "Derived from origination file",
    "Derived from origination file",
    rep("Origination file", 17),
    rep("Performance file (time-varying)", 7),
    rep("FRED (BLS LAUS)", 4),
    rep("FRED (FHFA)", 4),
    "Derived from performance file"
  )
)

write.csv(variable_dict,
          file.path(OUTPUT_DIR, "variable_dictionary.csv"),
          row.names = FALSE)

# --- Summary statistics and categorical variables distribution ---

orig_vars <- c("credit_score", "orig_ltv", "orig_cltv", "orig_dti",
               "orig_interest_rate", "orig_upb", "orig_loan_term",
               "num_borrowers", "mi_pct")

stargazer(as.data.frame(loan_level[, ..orig_vars]),
          type         = "html",
          title        = "Panel A: Origination Variables (loan level)",
          digits       = 2,
          summary.stat = c("n", "mean", "sd", "min", "p25", "median", "p75", "max"),
          out          = file.path(OUTPUT_DIR, "summary_origination.html"))
## 
## <table style="text-align:center"><caption><strong>Panel A: Origination Variables (loan level)</strong></caption>
## <tr><td colspan="9" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left">Statistic</td><td>N</td><td>Mean</td><td>St. Dev.</td><td>Min</td><td>Pctl(25)</td><td>Median</td><td>Pctl(75)</td><td>Max</td></tr>
## <tr><td colspan="9" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left">credit_score</td><td>240,443</td><td>741.56</td><td>53.80</td><td>300</td><td>706</td><td>754</td><td>785</td><td>850</td></tr>
## <tr><td style="text-align:left">orig_ltv</td><td>240,552</td><td>69.24</td><td>17.95</td><td>6</td><td>59</td><td>75</td><td>80</td><td>125</td></tr>
## <tr><td style="text-align:left">orig_cltv</td><td>240,546</td><td>71.34</td><td>18.80</td><td>6</td><td>60</td><td>75</td><td>80</td><td>193</td></tr>
## <tr><td style="text-align:left">orig_dti</td><td>220,093</td><td>34.87</td><td>12.21</td><td>1</td><td>26</td><td>35</td><td>44</td><td>65</td></tr>
## <tr><td style="text-align:left">orig_interest_rate</td><td>240,565</td><td>5.75</td><td>0.82</td><td>3.25</td><td>5.00</td><td>5.88</td><td>6.38</td><td>9.79</td></tr>
## <tr><td style="text-align:left">orig_upb</td><td>240,565</td><td>196,477.30</td><td>107,205.80</td><td>9,000</td><td>114,000</td><td>173,000</td><td>260,000</td><td>1,095,000</td></tr>
## <tr><td style="text-align:left">orig_loan_term</td><td>240,357</td><td>326.92</td><td>68.19</td><td>60</td><td>360</td><td>360</td><td>360</td><td>360</td></tr>
## <tr><td style="text-align:left">num_borrowers</td><td>240,491</td><td>1.56</td><td>0.50</td><td>1</td><td>1</td><td>2</td><td>2</td><td>2</td></tr>
## <tr><td style="text-align:left">mi_pct</td><td>240,562</td><td>3.17</td><td>8.59</td><td>0</td><td>0</td><td>0</td><td>0</td><td>40</td></tr>
## <tr><td colspan="9" style="border-bottom: 1px solid black"></td></tr></table>
behav_vars <- c("current_delinquency_status", "loan_age", "current_upb",
                "delta_interest_rate", "mod_flag_12m", "current_deferred_upb")

stargazer(as.data.frame(panel[, ..behav_vars]),
          type         = "html",
          title        = "Panel B: Behavioural Variables (observation level)",
          digits       = 2,
          summary.stat = c("n", "mean", "sd", "min", "p25", "median", "p75", "max"),
          out          = file.path(OUTPUT_DIR, "summary_behavioural.html"))
## 
## <table style="text-align:center"><caption><strong>Panel B: Behavioural Variables (observation level)</strong></caption>
## <tr><td colspan="9" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left">Statistic</td><td>N</td><td>Mean</td><td>St. Dev.</td><td>Min</td><td>Pctl(25)</td><td>Median</td><td>Pctl(75)</td><td>Max</td></tr>
## <tr><td colspan="9" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left">current_delinquency_status</td><td>7,312,948</td><td>0.01</td><td>0.12</td><td>0</td><td>0</td><td>0</td><td>0</td><td>2</td></tr>
## <tr><td style="text-align:left">loan_age</td><td>7,312,965</td><td>19.41</td><td>14.83</td><td>0</td><td>8</td><td>16</td><td>28</td><td>71</td></tr>
## <tr><td style="text-align:left">current_upb</td><td>7,312,965</td><td>176,880.10</td><td>102,404.10</td><td>0.00</td><td>100,522.90</td><td>154,118.70</td><td>234,667.40</td><td>1,094,000.00</td></tr>
## <tr><td style="text-align:left">delta_interest_rate</td><td>7,312,965</td><td>-0.002</td><td>0.09</td><td>-5.75</td><td>0.00</td><td>0.00</td><td>0.00</td><td>2.25</td></tr>
## <tr><td style="text-align:left">mod_flag_12m</td><td>7,312,965</td><td>0.0000</td><td>0.01</td><td>0</td><td>0</td><td>0</td><td>0</td><td>1</td></tr>
## <tr><td style="text-align:left">current_deferred_upb</td><td>7,312,965</td><td>3.91</td><td>653.63</td><td>0.00</td><td>0.00</td><td>0.00</td><td>0.00</td><td>251,900.00</td></tr>
## <tr><td colspan="9" style="border-bottom: 1px solid black"></td></tr></table>
macro_vars <- c(paste0("unemployment_rate_lag", 1:4),
                paste0("hpi_qoq_qlag", 1:4))

stargazer(as.data.frame(panel[, ..macro_vars]),
          type         = "html",
          title        = "Panel C: Macro Controls (observation level, lagged)",
          digits       = 2,
          summary.stat = c("n", "mean", "sd", "min", "p25", "median", "p75", "max"),
          out          = file.path(OUTPUT_DIR, "summary_macro.html"))
## 
## <table style="text-align:center"><caption><strong>Panel C: Macro Controls (observation level, lagged)</strong></caption>
## <tr><td colspan="9" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left">Statistic</td><td>N</td><td>Mean</td><td>St. Dev.</td><td>Min</td><td>Pctl(25)</td><td>Median</td><td>Pctl(75)</td><td>Max</td></tr>
## <tr><td colspan="9" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left">unemployment_rate_lag1</td><td>7,312,965</td><td>7.95</td><td>2.52</td><td>2.30</td><td>5.70</td><td>8.20</td><td>10.00</td><td>14.30</td></tr>
## <tr><td style="text-align:left">unemployment_rate_lag2</td><td>7,312,965</td><td>7.89</td><td>2.55</td><td>2.30</td><td>5.60</td><td>8.10</td><td>9.90</td><td>14.30</td></tr>
## <tr><td style="text-align:left">unemployment_rate_lag3</td><td>7,312,965</td><td>7.83</td><td>2.57</td><td>2.30</td><td>5.50</td><td>8.00</td><td>9.90</td><td>14.30</td></tr>
## <tr><td style="text-align:left">unemployment_rate_lag4</td><td>7,312,965</td><td>7.76</td><td>2.59</td><td>2.30</td><td>5.40</td><td>7.90</td><td>9.90</td><td>14.30</td></tr>
## <tr><td style="text-align:left">hpi_qoq_qlag1</td><td>7,312,965</td><td>-0.98</td><td>1.87</td><td>-10.02</td><td>-1.87</td><td>-0.67</td><td>0.35</td><td>6.94</td></tr>
## <tr><td style="text-align:left">hpi_qoq_qlag2</td><td>7,312,965</td><td>-1.01</td><td>1.91</td><td>-10.02</td><td>-1.92</td><td>-0.74</td><td>0.31</td><td>8.48</td></tr>
## <tr><td style="text-align:left">hpi_qoq_qlag3</td><td>7,312,965</td><td>-0.88</td><td>1.99</td><td>-10.02</td><td>-1.80</td><td>-0.62</td><td>0.42</td><td>10.33</td></tr>
## <tr><td style="text-align:left">hpi_qoq_qlag4</td><td>7,312,965</td><td>-0.69</td><td>2.04</td><td>-10.02</td><td>-1.64</td><td>-0.47</td><td>0.55</td><td>10.33</td></tr>
## <tr><td colspan="9" style="border-bottom: 1px solid black"></td></tr></table>
cat_vars <- c("occupancy_status", "amortization_type", "loan_purpose",
              "channel", "property_type", "first_time_homebuyer", "io_indicator")

cat_table <- rbindlist(lapply(cat_vars, function(v) {
  dt <- loan_level[, .(N = .N,
                       Default_Rate = round(100 * mean(ever_default_12m), 2)),
                   by = v]
  setnames(dt, v, "Category")
  dt[, Variable := v]
  dt[, Pct := round(100 * N / nrow(loan_level), 2)]
  dt[, .(Variable, Category, N, Pct, Default_Rate)]
}))[order(Variable, -N)]

stargazer(cat_table,
          type    = "html",
          title   = "Panel D: Categorical Variables (loan level)",
          summary = FALSE,
          rownames = FALSE,
          digits  = 2,
          out     = file.path(OUTPUT_DIR, "summary_categorical.html"))
## 
## <table style="text-align:center"><caption><strong>Panel D: Categorical Variables (loan level)</strong></caption>
## <tr><td colspan="5" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left">Variable</td><td>Category</td><td>N</td><td>Pct</td><td>Default_Rate</td></tr>
## <tr><td colspan="5" style="border-bottom: 1px solid black"></td></tr><tr><td style="text-align:left">amortization_type</td><td>FRM</td><td>240,565</td><td>100</td><td>7.39</td></tr>
## <tr><td style="text-align:left">channel</td><td>R</td><td>122,719</td><td>51.01</td><td>5.48</td></tr>
## <tr><td style="text-align:left">channel</td><td>T</td><td>65,749</td><td>27.33</td><td>14.29</td></tr>
## <tr><td style="text-align:left">channel</td><td>C</td><td>34,499</td><td>14.34</td><td>2.47</td></tr>
## <tr><td style="text-align:left">channel</td><td>B</td><td>17,598</td><td>7.32</td><td>4.54</td></tr>
## <tr><td style="text-align:left">first_time_homebuyer</td><td>N</td><td>217,299</td><td>90.33</td><td>7.26</td></tr>
## <tr><td style="text-align:left">first_time_homebuyer</td><td>Y</td><td>23,223</td><td>9.65</td><td>8.59</td></tr>
## <tr><td style="text-align:left">first_time_homebuyer</td><td></td><td>43</td><td>0.02</td><td>0</td></tr>
## <tr><td style="text-align:left">io_indicator</td><td>N</td><td>240,565</td><td>100</td><td>7.39</td></tr>
## <tr><td style="text-align:left">loan_purpose</td><td>P</td><td>86,133</td><td>35.80</td><td>7.23</td></tr>
## <tr><td style="text-align:left">loan_purpose</td><td>N</td><td>79,366</td><td>32.99</td><td>5.33</td></tr>
## <tr><td style="text-align:left">loan_purpose</td><td>C</td><td>75,066</td><td>31.20</td><td>9.74</td></tr>
## <tr><td style="text-align:left">occupancy_status</td><td>P</td><td>215,465</td><td>89.57</td><td>7.36</td></tr>
## <tr><td style="text-align:left">occupancy_status</td><td>I</td><td>13,288</td><td>5.52</td><td>9.20</td></tr>
## <tr><td style="text-align:left">occupancy_status</td><td>S</td><td>11,812</td><td>4.91</td><td>5.85</td></tr>
## <tr><td style="text-align:left">property_type</td><td>SF</td><td>179,667</td><td>74.69</td><td>7.40</td></tr>
## <tr><td style="text-align:left">property_type</td><td>PU</td><td>40,845</td><td>16.98</td><td>6.39</td></tr>
## <tr><td style="text-align:left">property_type</td><td>CO</td><td>17,495</td><td>7.27</td><td>9.08</td></tr>
## <tr><td style="text-align:left">property_type</td><td>MH</td><td>1,805</td><td>0.75</td><td>14.57</td></tr>
## <tr><td style="text-align:left">property_type</td><td>CP</td><td>753</td><td>0.31</td><td>2.52</td></tr>
## <tr><td colspan="5" style="border-bottom: 1px solid black"></td></tr></table>
# --- Correlation ---

panel_cor <- panel[!is.na(default_next_12m)]

all_vars <- c("current_delinquency_status", "loan_age", "current_upb",
              "delta_interest_rate", "mod_flag_12m", "current_deferred_upb",
              paste0("unemployment_rate_lag", 1:4),
              paste0("hpi_qoq_qlag", 1:4),
              "credit_score", "orig_ltv", "orig_cltv", "orig_dti",
              "orig_interest_rate", "orig_upb", "orig_loan_term",
              "num_borrowers", "mi_pct", "default_next_12m")

cor_matrix <- cor(panel_cor[, ..all_vars],
                  use = "pairwise.complete.obs")
cor_matrix <- round(cor_matrix, 2)

write.table(cor_matrix,
            file.path(OUTPUT_DIR, "correlation_matrix.txt"),
            sep       = "\t",
            row.names = TRUE,
            quote     = FALSE)

print(sort(cor_matrix[, "default_next_12m"], decreasing = TRUE))
##           default_next_12m current_delinquency_status 
##                       1.00                       0.05 
##         orig_interest_rate                   orig_ltv 
##                       0.03                       0.02 
##                  orig_cltv                   orig_dti 
##                       0.02                       0.02 
##             orig_loan_term                     mi_pct 
##                       0.02                       0.02 
##                   loan_age                current_upb 
##                       0.01                       0.01 
##                   orig_upb        delta_interest_rate 
##                       0.01                       0.00 
##               mod_flag_12m       current_deferred_upb 
##                       0.00                       0.00 
##     unemployment_rate_lag1     unemployment_rate_lag2 
##                       0.00                       0.00 
##     unemployment_rate_lag3     unemployment_rate_lag4 
##                      -0.01                      -0.01 
##              hpi_qoq_qlag3              hpi_qoq_qlag4 
##                      -0.01                      -0.01 
##              hpi_qoq_qlag1              hpi_qoq_qlag2 
##                      -0.02                      -0.02 
##              num_borrowers               credit_score 
##                      -0.02                      -0.04
pred_vars <- setdiff(all_vars, "default_next_12m")
cor_predictors <- cor(panel_cor[, ..pred_vars],
                      use = "pairwise.complete.obs")
round(cor_predictors, 2)
##                            current_delinquency_status loan_age current_upb
## current_delinquency_status                       1.00     0.06       -0.01
## loan_age                                         0.06     1.00       -0.15
## current_upb                                     -0.01    -0.15        1.00
## delta_interest_rate                             -0.01     0.01       -0.01
## mod_flag_12m                                     0.00     0.00        0.00
## current_deferred_upb                             0.00     0.00        0.00
## unemployment_rate_lag1                           0.02     0.31        0.05
## unemployment_rate_lag2                           0.02     0.32        0.04
## unemployment_rate_lag3                           0.02     0.33        0.04
## unemployment_rate_lag4                           0.02     0.33        0.04
## hpi_qoq_qlag1                                   -0.01    -0.07       -0.09
## hpi_qoq_qlag2                                   -0.01    -0.15       -0.08
## hpi_qoq_qlag3                                   -0.01    -0.16       -0.08
## hpi_qoq_qlag4                                   -0.01    -0.14       -0.09
## credit_score                                    -0.11    -0.11        0.06
## orig_ltv                                         0.02     0.03        0.12
## orig_cltv                                        0.02     0.03        0.13
## orig_dti                                         0.03     0.04        0.11
## orig_interest_rate                               0.06     0.27       -0.19
## orig_upb                                        -0.01    -0.11        0.96
## orig_loan_term                                   0.02     0.04        0.20
## num_borrowers                                   -0.02    -0.04        0.15
## mi_pct                                           0.02     0.04       -0.04
##                            delta_interest_rate mod_flag_12m
## current_delinquency_status               -0.01         0.00
## loan_age                                  0.01         0.00
## current_upb                              -0.01         0.00
## delta_interest_rate                       1.00        -0.18
## mod_flag_12m                             -0.18         1.00
## current_deferred_upb                     -0.29         0.04
## unemployment_rate_lag1                   -0.02         0.00
## unemployment_rate_lag2                   -0.02         0.00
## unemployment_rate_lag3                   -0.02         0.00
## unemployment_rate_lag4                   -0.02         0.00
## hpi_qoq_qlag1                             0.00         0.00
## hpi_qoq_qlag2                             0.01         0.00
## hpi_qoq_qlag3                             0.01         0.00
## hpi_qoq_qlag4                             0.01         0.00
## credit_score                              0.02        -0.01
## orig_ltv                                 -0.01         0.00
## orig_cltv                                -0.01         0.00
## orig_dti                                 -0.02         0.00
## orig_interest_rate                       -0.02         0.00
## orig_upb                                 -0.01         0.00
## orig_loan_term                           -0.01         0.00
## num_borrowers                             0.00         0.00
## mi_pct                                   -0.01         0.00
##                            current_deferred_upb unemployment_rate_lag1
## current_delinquency_status                 0.00                   0.02
## loan_age                                   0.00                   0.31
## current_upb                                0.00                   0.05
## delta_interest_rate                       -0.29                  -0.02
## mod_flag_12m                               0.04                   0.00
## current_deferred_upb                       1.00                   0.01
## unemployment_rate_lag1                     0.01                   1.00
## unemployment_rate_lag2                     0.01                   1.00
## unemployment_rate_lag3                     0.01                   0.99
## unemployment_rate_lag4                     0.01                   0.98
## hpi_qoq_qlag1                              0.00                  -0.25
## hpi_qoq_qlag2                              0.00                  -0.37
## hpi_qoq_qlag3                              0.00                  -0.45
## hpi_qoq_qlag4                              0.00                  -0.52
## credit_score                               0.00                   0.12
## orig_ltv                                   0.00                  -0.06
## orig_cltv                                  0.00                  -0.07
## orig_dti                                   0.00                  -0.04
## orig_interest_rate                         0.01                  -0.30
## orig_upb                                   0.00                   0.07
## orig_loan_term                             0.00                  -0.03
## num_borrowers                              0.00                   0.00
## mi_pct                                     0.00                  -0.04
##                            unemployment_rate_lag2 unemployment_rate_lag3
## current_delinquency_status                   0.02                   0.02
## loan_age                                     0.32                   0.33
## current_upb                                  0.04                   0.04
## delta_interest_rate                         -0.02                  -0.02
## mod_flag_12m                                 0.00                   0.00
## current_deferred_upb                         0.01                   0.01
## unemployment_rate_lag1                       1.00                   0.99
## unemployment_rate_lag2                       1.00                   1.00
## unemployment_rate_lag3                       1.00                   1.00
## unemployment_rate_lag4                       0.99                   1.00
## hpi_qoq_qlag1                               -0.23                  -0.22
## hpi_qoq_qlag2                               -0.34                  -0.32
## hpi_qoq_qlag3                               -0.44                  -0.42
## hpi_qoq_qlag4                               -0.51                  -0.49
## credit_score                                 0.12                   0.12
## orig_ltv                                    -0.06                  -0.06
## orig_cltv                                   -0.07                  -0.07
## orig_dti                                    -0.05                  -0.05
## orig_interest_rate                          -0.32                  -0.33
## orig_upb                                     0.07                   0.06
## orig_loan_term                              -0.04                  -0.04
## num_borrowers                                0.00                   0.00
## mi_pct                                      -0.04                  -0.04
##                            unemployment_rate_lag4 hpi_qoq_qlag1 hpi_qoq_qlag2
## current_delinquency_status                   0.02         -0.01         -0.01
## loan_age                                     0.33         -0.07         -0.15
## current_upb                                  0.04         -0.09         -0.08
## delta_interest_rate                         -0.02          0.00          0.01
## mod_flag_12m                                 0.00          0.00          0.00
## current_deferred_upb                         0.01          0.00          0.00
## unemployment_rate_lag1                       0.98         -0.25         -0.37
## unemployment_rate_lag2                       0.99         -0.23         -0.34
## unemployment_rate_lag3                       1.00         -0.22         -0.32
## unemployment_rate_lag4                       1.00         -0.20         -0.31
## hpi_qoq_qlag1                               -0.20          1.00          0.53
## hpi_qoq_qlag2                               -0.31          0.53          1.00
## hpi_qoq_qlag3                               -0.39          0.21          0.61
## hpi_qoq_qlag4                               -0.48          0.43          0.34
## credit_score                                 0.12         -0.02         -0.05
## orig_ltv                                    -0.06          0.08          0.08
## orig_cltv                                   -0.07          0.09          0.09
## orig_dti                                    -0.05         -0.02         -0.01
## orig_interest_rate                          -0.34          0.01          0.07
## orig_upb                                     0.06         -0.09         -0.09
## orig_loan_term                              -0.04         -0.03         -0.02
## num_borrowers                                0.00          0.01          0.00
## mi_pct                                      -0.05          0.04          0.05
##                            hpi_qoq_qlag3 hpi_qoq_qlag4 credit_score orig_ltv
## current_delinquency_status         -0.01         -0.01        -0.11     0.02
## loan_age                           -0.16         -0.14        -0.11     0.03
## current_upb                        -0.08         -0.09         0.06     0.12
## delta_interest_rate                 0.01          0.01         0.02    -0.01
## mod_flag_12m                        0.00          0.00        -0.01     0.00
## current_deferred_upb                0.00          0.00         0.00     0.00
## unemployment_rate_lag1             -0.45         -0.52         0.12    -0.06
## unemployment_rate_lag2             -0.44         -0.51         0.12    -0.06
## unemployment_rate_lag3             -0.42         -0.49         0.12    -0.06
## unemployment_rate_lag4             -0.39         -0.48         0.12    -0.06
## hpi_qoq_qlag1                       0.21          0.43        -0.02     0.08
## hpi_qoq_qlag2                       0.61          0.34        -0.05     0.08
## hpi_qoq_qlag3                       1.00          0.63        -0.06     0.08
## hpi_qoq_qlag4                       0.63          1.00        -0.07     0.08
## credit_score                       -0.06         -0.07         1.00    -0.16
## orig_ltv                            0.08          0.08        -0.16     1.00
## orig_cltv                           0.09          0.08        -0.15     0.94
## orig_dti                            0.00          0.00        -0.18     0.15
## orig_interest_rate                  0.10          0.12        -0.33     0.18
## orig_upb                           -0.10         -0.10         0.07     0.11
## orig_loan_term                     -0.01         -0.01        -0.08     0.27
## num_borrowers                       0.00          0.00         0.02    -0.05
## mi_pct                              0.05          0.05        -0.13     0.49
##                            orig_cltv orig_dti orig_interest_rate orig_upb
## current_delinquency_status      0.02     0.03               0.06    -0.01
## loan_age                        0.03     0.04               0.27    -0.11
## current_upb                     0.13     0.11              -0.19     0.96
## delta_interest_rate            -0.01    -0.02              -0.02    -0.01
## mod_flag_12m                    0.00     0.00               0.00     0.00
## current_deferred_upb            0.00     0.00               0.01     0.00
## unemployment_rate_lag1         -0.07    -0.04              -0.30     0.07
## unemployment_rate_lag2         -0.07    -0.05              -0.32     0.07
## unemployment_rate_lag3         -0.07    -0.05              -0.33     0.06
## unemployment_rate_lag4         -0.07    -0.05              -0.34     0.06
## hpi_qoq_qlag1                   0.09    -0.02               0.01    -0.09
## hpi_qoq_qlag2                   0.09    -0.01               0.07    -0.09
## hpi_qoq_qlag3                   0.09     0.00               0.10    -0.10
## hpi_qoq_qlag4                   0.08     0.00               0.12    -0.10
## credit_score                   -0.15    -0.18              -0.33     0.07
## orig_ltv                        0.94     0.15               0.18     0.11
## orig_cltv                       1.00     0.16               0.18     0.13
## orig_dti                        0.16     1.00               0.17     0.11
## orig_interest_rate              0.18     0.17               1.00    -0.20
## orig_upb                        0.13     0.11              -0.20     1.00
## orig_loan_term                  0.27     0.14               0.29     0.18
## num_borrowers                  -0.03    -0.11              -0.10     0.16
## mi_pct                          0.43     0.09               0.19    -0.04
##                            orig_loan_term num_borrowers mi_pct
## current_delinquency_status           0.02         -0.02   0.02
## loan_age                             0.04         -0.04   0.04
## current_upb                          0.20          0.15  -0.04
## delta_interest_rate                 -0.01          0.00  -0.01
## mod_flag_12m                         0.00          0.00   0.00
## current_deferred_upb                 0.00          0.00   0.00
## unemployment_rate_lag1              -0.03          0.00  -0.04
## unemployment_rate_lag2              -0.04          0.00  -0.04
## unemployment_rate_lag3              -0.04          0.00  -0.04
## unemployment_rate_lag4              -0.04          0.00  -0.05
## hpi_qoq_qlag1                       -0.03          0.01   0.04
## hpi_qoq_qlag2                       -0.02          0.00   0.05
## hpi_qoq_qlag3                       -0.01          0.00   0.05
## hpi_qoq_qlag4                       -0.01          0.00   0.05
## credit_score                        -0.08          0.02  -0.13
## orig_ltv                             0.27         -0.05   0.49
## orig_cltv                            0.27         -0.03   0.43
## orig_dti                             0.14         -0.11   0.09
## orig_interest_rate                   0.29         -0.10   0.19
## orig_upb                             0.18          0.16  -0.04
## orig_loan_term                       1.00         -0.07   0.13
## num_borrowers                       -0.07          1.00  -0.04
## mi_pct                               0.13         -0.04   1.00