Non-financial Liabilities and Restructuring

Empirical support from 2005 Reform with the North America sample

Author

Hongyi Xu

Published

March 3, 2025

Modified

March 11, 2025

This analysis is suggested by discussant Samuel Antill in 2025 AFA meeting.

The previous version can be found here. In this updated document, we use a new measure to more accurately pinpoint the impact of non-residential real property lease contracts they have.

In this version, we replace the measure contract_intensity by ppe_lease_intensity et al. and re-run all tests.

Updates: Mar 11, 2025

In this version, we set the base_year == 2004 instead of 2005. Based on the S.256 - Bankruptcy Abuse Prevention and Consumer Protection Act of 2005, the bill was first introduced on February 1, 2025 and was signed into law by President George W. Bush. on April 20, 2005. The act’s provisions applied to bankruptcy cases filed on or after October 17, 2005. > Wikipedia

Therefore, the treatment effects should be present at first in the annual reports for the fiscal year 2005 and the treatment happens in fiscal year 2004.

Note 1: To-Do List - Mar 5, 2025

S1. Download and Load the Raw Dataset

We download the firm-level capital structure = from Compustat-CapitalIQ North America. The first measure of executory contracts is accounting data which (under U.S. GAAP) cover leases and rental contracts. We use the variables “Debt Equivalent of Operating Leases”, “Capital Leases” and “Net Rental Expenses”.

  • Debt - Capitalized Lease Obligations (dclo): This item represents long-term obligations due in respect of lease finances and hire purchase arrangements. This item includes:

    • Long-term finance lease obligations
    • Long-term lease financing
    • Long-term hire purchase obligations
    • Non-current obligations under capital leases
  • Rental Expense (xrent): This item represents all costs charged to operations for rental, lease, or hire of space and/or equipment. This item includes:

    • Airlines’ landing fees
    • Contingent rentals associated with capitalized leases
    • Lease charges and plant hire

    In the main test, we construct a new variable called total rent, which is defined as the total rental commitment mrc1 + mrc2 + mrc3 + mrc4 + mrc5 + mrct reported in year t.

  • Asset - Total (at): Book value of total assets.

  • Debt in Current Liabilities - Total (dlc) is for the short-term debt and Long-term debt - Total (dltt) is for the long-term debt.

  • Earnings Before Interest (EBITDA): EBITDA.

  • Industry classifications: naics, sic and spcindcd + (Fama-French 30 Industry Classifiers, To Be Added / Definition).

In this section we add a new variable:

Note

Updated: March 5, 2025

  • Property, Plant, and Equipment - Leases at Cost (fatl) is the capitalized value of leases and leasehold improvements included in property, plant, and equipment, excluding equipment leased to others, and is not applicable to banks or utilities. > Definition

  • Property, Plant, and Equipment - Buildings at Cost (fatb). > Definition

  • Property, Plant, and Equipment - Land and Improvements at Cost (fatp).

  • Property, Plant, and Equipment - Buildings (Net) (ppenb).

  • Property, Plant, and Equipment - Land and Improvements (Net) (ppenli).

  • Property, Plant and Equipment - Total (Gross) (ppegt).

  • Property, Plant and Equipment - Total (Net) (ppent)

  • Loans/Claims/Advances - Lease (lcal). > Defintion > This might be the more promising variable.

Note 2: All North American firms Now!

We download all annual observations with Data Date (datadate) between Jan 2000 and Dec 2007 and restrict to firms either incorporated or having headquarters in US (i.e. fic == "USA" | loc == "USA").

This filter does not apply to the current version of the analysis.

Given that the policy shock happens under the US jurisdiction, we expect more significant treatment effect to be detected in this sample. The period used in Samuel’s slides is between 2002 and 2007, which is after the doc.com bubble and before the GFC. The variables in the dataset are:

Show the code
## create the data file path 
data_file <- "jpbdsuonrpztpw8t.csv" 
data_path <- file.path(work_dir, "Data", data_file)

## load the compustat_na data
compustat_na <- as_tibble(read.csv(file = data_path) ) # %>%
  # filter(fic == "USA" | loc == "USA" ) ## keep only US related observations (| fic == "CAN" | loc == "CAN")

## data file record: 
# | Mar 10, 2025 > jpbdsuonrpztpw8t.csv
# | Mar  9, 2025 > nfmss2xkmjgfjonh.csv 
# | Mar  5, 2025 > e3cdfjocaz4aboqh.csv 
# | Mar  3, 2025(2) > tbrl8c4xqurukptl.csv > more variables 
# | Mar  3, 2025(1) > evvvij0nqoe8sshv.csv
# | Feb 24, 2025 > azsyeo1yjmrb2q1v.csv 
# | Jan 14, 2025 > g4f68dkn3beu1iag.csv 

## load the FF_30ind data 
FF_30ind <- as_tibble(read.csv(file = file.path(work_dir, "Data", "ff_30ind.csv")))

## check the variable names 
cat("Variables include:\n\n")
sort(names(compustat_na)) 
cat("\nSample size: \n\n")
dim(compustat_na)
Variables include:

 [1] "act"      "at"       "bkvlps"   "ceq"      "che"      "cik"     
 [7] "conm"     "consol"   "costat"   "csho"     "curcd"    "cusip"   
[13] "datadate" "datafmt"  "dclo"     "dlc"      "dltt"     "dp"      
[19] "dvc"      "dvp"      "ebit"     "ebitda"   "fatb"     "fatl"    
[25] "fatp"     "fic"      "fyear"    "fyr"      "fyrc"     "gvkey"   
[31] "ib"       "indfmt"   "lcal"     "lct"      "loc"      "lt"      
[37] "mrc1"     "mrc2"     "mrc3"     "mrc4"     "mrc5"     "mrct"    
[43] "mrcta"    "naics"    "ni"       "oibdp"    "popsrc"   "ppegt"   
[49] "ppenb"    "ppenli"   "ppenls"   "ppent"    "prcc_f"   "re"      
[55] "revt"     "seq"      "sic"      "spcindcd" "tic"      "txdb"    
[61] "wcap"     "xrent"   

Sample size: 

[1] 165122     62

S2. Data Cleaning and Prep

Two dependent variables are constructed to measure firm’s leverage: (cf. p18 and Table 2 of the paper)

  • Book leverage: we define leverage as the ratio of the sum of short-term debt and long-term debt to assets (we drop observations where this is outside the [0,1] range)*.

  • Debt/EBITDA: we define debt-to-EBITDA as the ratio of the long- and short-term debt to EBITDA (we drop observations where this is outside the [0,15] range)*.

These restrictions are now imposed in all analyses in Section 3.

Note 3
Show the code
## set the base year 
base_year <- 2004 
period_start <- 2002
period_end <- 2007
intensity_measure_year <- 2000 # choose the base year for the intensity measure 
n_pre <- 1 # number of periods before the period_start in the iplot()  

## create leverage variables 
data <- compustat_na %>% 
  # filter(at >= 0) %>%
  filter(indfmt == "INDL") %>% ## remove all financial firms
  ## create the lagged `ppent` item: 
  group_by(gvkey) %>%
  arrange(fyear) %>%
  mutate(ppent_lag1 = lag(ppent, n = 1)) %>% 
  ungroup() %>% 
  ## create new variables: 
  mutate(
    ## leverage variables: 
    book_leverage = (dlc + dltt) / at, 
    debt_ebitda = (dlc + dltt) / ebitda, 
    
    ## treatment intensity: 
    totalrent = coalesce(mrc1, 0) + coalesce(mrc2, 0) + coalesce(mrc3, 0) + coalesce(mrc4, 0) + coalesce(mrc5, 0) + coalesce(mrcta, 0), # total rent w/o discount
    # contract_intensity = (dclo + xrent * 3) / at, # executory contract intensity
    contract_intensity = (coalesce(dclo, 0) + totalrent) / at, # executory contract intensity
    
    ### for the total: 
    ppe_lease_intensity = fatl / at, # PPE lease intensity 
    building_intensity = fatb / at, # only for buildings (i.e. properties), but only not only leased ones
    land_intensity = fatp / at, # only land intensity 
    bnl_intensity = building_intensity + land_intensity, 
    
    ### for the net: 
    # net_lease_intensity = ppenls / at, # net PPE lease intensity [not available after 1998]
    # net_building_intensity = ppenb / at, # net PPE building intensity [not available after 1998]  
    net_land_intensity = ppenli / at, # net PPE land intensity 
    
    ### for total PPE: 
    net_PPE_intensity = ppent / at, # net PPE intensity 
    PPE_intensity = ppegt / at, # gross PPE intensity 
    
    ### for lessors: 
    lessor_lease_intensity = lcal / at, # this is outstanding lease intensity to be received. 
    
    ## other variables and controls: 
    dyear = as.integer(substr(datadate, start = 1, stop = 4)), # data year 
    roa = ni / at, # return on asset (ROA) 
    tangibility = ppent / at, # tangibility  
    altman_Z = (3.3 * revt + 1.4 * re + 1.2 * wcap) / at, # Altman Z-score
    kz = -1.001909 * ((ib + dp)/ppent_lag1) + 0.2826389 * ((at + prcc_f*csho - ceq - txdb)/at) + 3.139193 * ((dltt + dlc)/(dltt + dlc + seq)) - 39.3678 * ((dvc + dvp)/ppent_lag1) - 1.314759 * (che/ppent_lag1), # KZ index 
    # hw = , # financial contraints (HW) 
    current_ratio = act / lct, # current ratio: current asset / current liabilites 
    market_book = (prcc_f*csho) / (ceq + txdb) # market-to-book
  ) 

## record the variable names 
cat("Variables Created:\n\n")
sort(setdiff(names(data), names(compustat_na))) 
Variables Created:

 [1] "altman_Z"               "bnl_intensity"          "book_leverage"         
 [4] "building_intensity"     "contract_intensity"     "current_ratio"         
 [7] "debt_ebitda"            "dyear"                  "kz"                    
[10] "land_intensity"         "lessor_lease_intensity" "market_book"           
[13] "net_land_intensity"     "net_PPE_intensity"      "PPE_intensity"         
[16] "ppe_lease_intensity"    "ppent_lag1"             "roa"                   
[19] "tangibility"            "totalrent"             

We propose two noisy measures of the PPE lease contract intensity.

  • ppe_lease_intensity: calculated as the Property, Plant, and Equipment - Leases at Cost (fatl) normalized by the total asset for firm i at year t. It measures the future lease obligations in PPE, but it is a noisy measure as it also includes equipment.

  • building_intensity: calculated as Property, Plant, and Equipment - Buildings at Cost (fatb) normalized by the total asset for firm i at year t.

  • oustanding_lease_intensity: calculated as the Loans/Claims/Advances - Lease (lcal) normalized by the total asset for firm i at year t. It measures the amount of lease obgliations to be collected by firm i in the future. You can view this sample as the lessor in the lease contract, while the previous variable, ppe_lease_intensity, captures the sample of lessees.

Although this will contain other items besides non-residential real property lease obligations, we believe that it is a potentially better measure for a firm’s exposure to this policy shock in 2005.

For definitions of controls, please refer to Section 4.

  • kz: KZ index: -1.001909 \left( \frac{ib + dp}{\text{lagged } ppent} \right) + 0.2826389 \left( \frac{at + \text{prcc_f} \times \text{csho} - ceq - txdb}{at} \right) + 3.139193 \left( \frac{dltt + dlc}{dltt + dlc + seq} \right) - 39.3678 \left( \frac{dvc + dvp}{\text{lagged } ppent} \right) - 1.314759 \left( \frac{che}{\text{lagged } ppent} \right).

S3. Difference-in-Difference Examination

Then, we construct the dataset for the difference-in-difference analysis.

In this section, we use all observations without missing values in subsequent analyses.

The original dataset (data) contains observations with fiscal year (fyear) range in [1996, 2009] and we restrict the sample to the data year in [2002, 2007].

The fiscal year fyear will be chosen as the time index for the following analyses using different lease contract intensity measures.

Note 4: Sensitivity of the choice of the base year

s3.0. Executory contract intensity

contract_intensity is chosen to measure a firm’s executory contract intensity, which was expected to be impacted by the change in the bankruptcy code in 2005.

Show the code
## choose the group definition: 
intensity_measure_name <- c(
  "contract_intensity", 
  "ppe_lease_intensity", 
  "building_intensity", 
  "land_intensity",
  "bnl_intensity")[1]

data_firm <- data %>% 
  filter(fyear == intensity_measure_year) %>% # use `fyear` may create multiple observations for the same firm. E.g. filter(gvkey == 23535, dyear == 2005) 
  group_by(fyear) %>% 
  ## identify large and small firms based on its total asset in the year 2000 
  mutate(median_at = median(at, na.rm = TRUE)) %>% 
  ungroup() %>% 
  mutate(large = ifelse(at > median_at, 1, 0)) %>% 
  select(gvkey, intensity_2000 = all_of(intensity_measure_name), large) 
  
data_did <- data %>% 
  ## merge the grouping variable 
  left_join(y = data_firm, by = join_by(gvkey) ) %>% 
  ## merge the FF 30 industry classifiaction 
  left_join(y = FF_30ind, by = join_by(sic)) %>% 
  ## exclude certain industries 
  filter(
    ff_30ind != 20, # exclude Utiltiy (number 20) 
    !(sic >= 6000 & sic <= 6199) # exclude banks under Banking, Insurance, Real Estate, Trading (number 29)
  ) %>% 
  ## pre- & post- 
  mutate(
    indexyear = (fyear - base_year), # year index with 2005 as base 0.
    post_2005 = as.numeric(fyear > base_year)  # whether it is after the 2005 reform 
  ) 

## gvkey(s) for balanced panel": 
data_did_balanced_id <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  filter(fyear >= period_start - n_pre & fyear <= period_end) %>% 
  group_by(gvkey) %>% 
  summarise(count_obs = sum(!is.na(book_leverage) & !is.na(intensity_2000))) %>% 
  ungroup() %>% 
  filter(count_obs == period_end - period_start + 1 + n_pre) %>% 
  .$gvkey 

data_intensity_panel <- data %>% 
  filter(fyear < 2007) %>%
  select(gvkey, fyear, all_of(intensity_measure_name)) %>% 
  pivot_wider(names_from = fyear, values_from = all_of(intensity_measure_name))

data_intensity_panel %>%  
  .[,-1] %>% 
  apply(MARGIN = 1, FUN = function(x) {
    # sd(x = unlist(x[1:7]), na.rm = TRUE)
    c(
      intensity_sd = sd(x = unlist(x), na.rm = TRUE), 
      intensity_cv = sd(x = unlist(x), na.rm = TRUE)/mean(unlist(x), na.rm = TRUE) 
    )
  }) %>% 
  t() %>% 
  cbind.data.frame(data_intensity_panel, .) %>% 
  as_tibble() %>% 
  select(gvkey, intensity_sd, intensity_cv, intensity_2000 = '2000') %>% 
  lm(intensity_2000 ~ intensity_sd + intensity_cv, data = .) %>% 
  summary()

Call:
lm(formula = intensity_2000 ~ intensity_sd + intensity_cv, data = .)

Residuals:
    Min      1Q  Median      3Q     Max 
-60.296  -0.160  -0.131  -0.047 221.314 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)   0.181344   0.049821   3.640 0.000274 ***
intensity_sd  0.198606   0.006554  30.302  < 2e-16 ***
intensity_cv -0.013677   0.051092  -0.268 0.788942    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 2.836 on 9303 degrees of freedom
  (9997 observations deleted due to missingness)
Multiple R-squared:  0.09014,   Adjusted R-squared:  0.08994 
F-statistic: 460.8 on 2 and 9303 DF,  p-value: < 2.2e-16

I re-construct a measure for the standard deviation of a firm’s intensity measure over time and name it intensity_var. A simple linear regression between the intensity measure in 2000 and its standard deviation shows a positive correlation between the two. It seems that this measure is more volatile when the intensity is high.

The positive relationship persists if we use the coefficient of variation (CV = sd / mean), which measures the relative variability, as the independent variable.

DiD Analysis:

Variable treated is defined as whether the firm has a positive contract_intensity in year rintensity_measure_year`.

Show the code
cat(intensity_measure_name); cat(": \n"); 

did_model_s3z_a <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0) 
  ) %>% 
  fixest::feols(fml = book_leverage ~ treated*post_2005*large | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) 
  
did_model_s3z_b <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0) 
  ) %>% 
  fixest::feols(fml = book_leverage ~ intensity_2000*post_2005*large | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) 

mget(ls(pattern = "did_model_s3z_")) %>% 
  `names<-`(value = c("(a) treatment", "(b) intensity")) %>% 
  etable() %>% 
  knitr::kable(format = "html", caption = paste("DiD Results with `", intensity_measure_name, "`", sep = "")) %>% 
  kableExtra::kable_styling(
    font_size = 8,       # Smaller font (default is 16px)
    full_width = FALSE,   # Table width fits content 
    bootstrap_options = c("striped", "condensed")
  )
contract_intensity: 
DiD Results with `contract_intensity`
(a) treatment (b) intensity
Dependent Var.: book_leverage book_leverage
treated x post_2005 -0.0079 (0.0071)
post_2005 x large -0.0112 (0.0089) -0.0059 (0.0049)
treated x post_2005 x large 0.0074 (0.0082)
intensity_2000 x post_2005 -0.0010 (0.0040)
intensity_2000 x post_2005 x large 0.0035 (0.0058)
Fixed-Effects: ---------------- ----------------
gvkey Yes Yes
fyear Yes Yes
ff_30ind_name-fyear Yes Yes
__________________________________ ________________ ________________
S.E.: Clustered by: gvkey & ff_3. by: gvkey & ff_3.
Observations 36,900 36,890
R2 0.80304 0.80314
Within R2 0.00025 0.00015

s3.1. PPE lease intensity

ppe_lease_intensity is chosen to measure a firm’s long-term exposure to lease contracts, especially non-residential real property lease obligations, which was expected to be impacted by the change in the bankruptcy code in 2005.

Show the code
## choose the group definition: 
intensity_measure_name <- c(
  "contract_intensity", 
  "ppe_lease_intensity", 
  "building_intensity", 
  "land_intensity",
  "bnl_intensity")[2]

data_firm <- data %>% 
  filter(fyear == intensity_measure_year) %>% # use `fyear` may create multiple observations for the same firm. E.g. filter(gvkey == 23535, dyear == 2005) 
  group_by(fyear) %>% 
  mutate(median_at = median(at, na.rm = TRUE)) %>% 
  ungroup() %>% 
  mutate(large = ifelse(at > median_at, 1, 0)) %>% 
  select(gvkey, intensity_2000 = all_of(intensity_measure_name), large) 
  
data_did <- data %>% 
  ## merge the grouping variable 
  left_join(y = data_firm, by = join_by(gvkey) ) %>% 
  ## merge the FF 30 industry classifiaction 
  left_join(y = FF_30ind, by = join_by(sic)) %>% 
  ## exclude certain industries 
  filter(
    ff_30ind != 20, # exclude Utiltiy (number 20) 
    !(sic >= 6000 & sic <= 6199) # exclude banks under Banking, Insurance, Real Estate, Trading (number 29)
  ) %>% 
  ## pre- & post- 
  mutate(
    indexyear = (fyear - base_year), # year index with 2005 as base 0.
    post_2005 = as.numeric(fyear > base_year)  # whether it is after the 2005 reform 
  ) 

## gvkey(s) for balanced panel": 
data_did_balanced_id <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  filter(fyear >= period_start - n_pre & fyear <= period_end) %>% 
  group_by(gvkey) %>% 
  summarise(count_obs = sum(!is.na(book_leverage) & !is.na(intensity_2000))) %>% 
  ungroup() %>% 
  filter(count_obs == period_end - period_start + 1 + n_pre) %>% 
  .$gvkey 

data_intensity_panel <- data %>% 
  filter(fyear < 2007) %>%
  select(gvkey, fyear, all_of(intensity_measure_name)) %>% 
  pivot_wider(names_from = fyear, values_from = all_of(intensity_measure_name))

data_intensity_panel %>%
  .[,-1] %>%
  apply(MARGIN = 1, FUN = function(x) {
    # sd(x = unlist(x[1:7]), na.rm = TRUE)
    c(
      intensity_sd = sd(x = unlist(x), na.rm = TRUE),
      intensity_cv = sd(x = unlist(x), na.rm = TRUE)/mean(unlist(x), na.rm = TRUE)
    )
  }) %>%
  t() %>%
  cbind.data.frame(data_intensity_panel, .) %>%
  as_tibble() %>%
  select(gvkey, intensity_sd, intensity_cv, intensity_2000 = '2000') %>%
  lm(intensity_2000 ~ intensity_sd + intensity_cv, data = .) %>%
  summary()

Call:
lm(formula = intensity_2000 ~ intensity_sd + intensity_cv, data = .)

Residuals:
     Min       1Q   Median       3Q      Max 
-1.43054 -0.02519 -0.01069  0.01839  1.80266 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)   0.047995   0.002372   20.23   <2e-16 ***
intensity_sd  1.531545   0.014390  106.43   <2e-16 ***
intensity_cv -0.055780   0.002310  -24.14   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.09947 on 4888 degrees of freedom
  (14412 observations deleted due to missingness)
Multiple R-squared:  0.704, Adjusted R-squared:  0.7039 
F-statistic:  5814 on 2 and 4888 DF,  p-value: < 2.2e-16

DiD Analysis:

Show the code
cat(intensity_measure_name); cat(": \n"); 

did_model_s3a_a <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0) 
  ) %>% 
  fixest::feols(fml = book_leverage ~ treated*post_2005*large | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) 
  
did_model_s3a_b <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0) 
  ) %>% 
  fixest::feols(fml = book_leverage ~ intensity_2000*post_2005*large | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) 

mget(ls(pattern = "did_model_s3a_")) %>% 
  `names<-`(value = c("(a) treatment", "(b) intensity")) %>% 
  etable() %>% 
  knitr::kable(format = "html", caption = paste("DiD Results with `", intensity_measure_name, "`", sep = "")) %>% 
  kableExtra::kable_styling(
    font_size = 8,       # Smaller font (default is 16px)
    full_width = FALSE,   # Table width fits content 
    bootstrap_options = c("striped", "condensed")
  )
ppe_lease_intensity: 
DiD Results with `ppe_lease_intensity`
(a) treatment (b) intensity
Dependent Var.: book_leverage book_leverage
treated x post_2005 -0.0079 (0.0077)
post_2005 x large -0.0122 (0.0088) -0.0057 (0.0048)
treated x post_2005 x large 0.0149 (0.0101)
intensity_2000 x post_2005 -0.0312 (0.0218)
intensity_2000 x post_2005 x large 0.0982* (0.0367)
Fixed-Effects: ---------------- ----------------
gvkey Yes Yes
fyear Yes Yes
ff_30ind_name-fyear Yes Yes
__________________________________ ________________ ________________
S.E.: Clustered by: gvkey & ff_3. by: gvkey & ff_3.
Observations 24,775 24,775
R2 0.78916 0.78917
Within R2 0.00029 0.00033

s3.2. builing intensity

building_intensity is chosen to measure a firm’s long-term exposure to buildings at cost under the PPE.

Show the code
## choose the group definition: 
intensity_measure_name <- c(
  "contract_intensity", 
  "ppe_lease_intensity", 
  "building_intensity", 
  "land_intensity",
  "bnl_intensity")[3]

data_firm <- data %>% 
  filter(fyear == intensity_measure_year) %>% # use `fyear` may create multiple observations for the same firm. E.g. filter(gvkey == 23535, dyear == 2005) 
  group_by(fyear) %>% 
  mutate(median_at = median(at, na.rm = TRUE)) %>% 
  ungroup() %>% 
  mutate(large = ifelse(at > median_at, 1, 0)) %>% 
  select(gvkey, intensity_2000 = all_of(intensity_measure_name), large) 
  
data_did <- data %>% 
  ## merge the grouping variable 
  left_join(y = data_firm, by = join_by(gvkey) ) %>% 
  ## merge the FF 30 industry classifiaction 
  left_join(y = FF_30ind, by = join_by(sic)) %>% 
  ## exclude certain industries 
  filter(
    ff_30ind != 20, # exclude Utiltiy (number 20) 
    !(sic >= 6000 & sic <= 6199) # exclude banks under Banking, Insurance, Real Estate, Trading (number 29)
  ) %>% 
  ## pre- & post- 
  mutate(
    indexyear = (fyear - base_year), # year index with 2005 as base 0.
    post_2005 = as.numeric(fyear > base_year)  # whether it is after the 2005 reform 
  ) 

## gvkey(s) for balanced panel": 
data_did_balanced_id <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  filter(fyear >= period_start - n_pre & fyear <= period_end) %>% 
  group_by(gvkey) %>% 
  summarise(count_obs = sum(!is.na(book_leverage) & !is.na(intensity_2000))) %>% 
  ungroup() %>% 
  filter(count_obs == period_end - period_start + 1 + n_pre) %>% 
  .$gvkey 

data_intensity_panel <- data %>% 
  filter(fyear < 2007) %>%
  select(gvkey, fyear, all_of(intensity_measure_name)) %>% 
  pivot_wider(names_from = fyear, values_from = all_of(intensity_measure_name))

DiD Analysis:

Show the code
cat(intensity_measure_name); cat(": \n"); 

did_model_s3b_a <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0) 
  ) %>% 
  fixest::feols(fml = book_leverage ~ treated*post_2005*large | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) 
  
did_model_s3b_b <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0) 
  ) %>% 
  fixest::feols(fml = book_leverage ~ intensity_2000*post_2005*large | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) 

mget(ls(pattern = "did_model_s3b_")) %>% 
  `names<-`(value = c("(a) treatment", "(b) intensity")) %>% 
  etable() %>% 
  knitr::kable(format = "html", caption = paste("DiD Results with `", intensity_measure_name, "`", sep = "")) %>% 
  kableExtra::kable_styling(
    font_size = 8,       # Smaller font (default is 16px)
    full_width = FALSE,   # Table width fits content 
    bootstrap_options = c("striped", "condensed")
  ) 
building_intensity: 
DiD Results with `building_intensity`
(a) treatment (b) intensity
Dependent Var.: book_leverage book_leverage
treated x post_2005 -0.0302*** (0.0060)
post_2005 x large 0.0013 (0.0081) -0.0032 (0.0049)
treated x post_2005 x large 0.0116 (0.0089)
intensity_2000 x post_2005 -0.1015*** (0.0219)
intensity_2000 x post_2005 x large 0.0552 (0.0331)
Fixed-Effects: ------------------- -------------------
gvkey Yes Yes
fyear Yes Yes
ff_30ind_name-fyear Yes Yes
__________________________________ ___________________ ___________________
S.E.: Clustered by: gvkey & ff_3. by: gvkey & ff_3.
Observations 26,682 26,682
R2 0.79252 0.79242
Within R2 0.00244 0.00193

DDD plot:

Show the code
## a test ground: 
bb <- data_did %>%
  filter(book_leverage >= 0 & book_leverage <= 1) %>%
  # filter(gvkey %in% data_did_balanced_id) %>% 
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, indexyear, intensity_2000, post_2005,
         book_leverage, debt_ebitda, sic, ff_30ind_name,
         at, ebitda, large, roa, ppent, bnl_intensity, ppe_lease_intensity, 
         altman_Z, kz, market_book, tangibility, current_ratio) %>%
  filter(fyear >= period_start - n_pre & fyear <= period_end) %>%
  filter(!is.na(intensity_2000) & !is.na(at)) %>%
  mutate(
    gvkey = as.factor(gvkey),
    fyear = as.factor(fyear),
    # treated = ifelse(intensity_2000 > 0, "Treated", "Untreated"),
    treated = ifelse(intensity_2000 > 0, 1, 0),
    ebitda_at = ebitda / at,
    at_thousand = at * 10^-3,
    large = ifelse(large, yes = "Large", no = "Small"), 
    tangiblity_exbnl = tangibility - bnl_intensity, 
    bnl = bnl_intensity * at, 
    # large = ifelse(large, yes = 1, no = 0),
    treated_large = paste(treated, large, sep = "_") 
  ) %>%
  # separately estimate the regression coefficients from two subsamples: 
  fixest::feols(fml = book_leverage ~ roa + ebitda_at + log(at_thousand) + # tangiblity_exbnl + 
                ### adding different controls: 
                # altman_Z + kz + market_book + tangibility + current_ratio + 
                i(indexyear, treated, ref = -1) | gvkey + indexyear + ff_30ind_name^indexyear,
                data = ., 
                cluster = c("gvkey", "ff_30ind_name"), 
                split = ~ large ## split the sample by the variable 'large' 
                )
NOTE: 324 observations removed because of NA values (RHS: 324).
Show the code
# mm$coeftable %>% data.frame() %>%  rownames_to_column(., var = "Rowname") %>% mutate(Treated = str_detect(string = Rowname, pattern = "Treated"), Period = str_extract(string = Rowname, pattern = "-?\\d+"), Size = str_detect(string = Rowname, pattern = "Large")) %>% arrange(Treated, Size) %>% as_tibble() 

etable(bb)
                                       bb.1                bb.2
Sample (large)                        Large               Small
Dependent Var.:               book_leverage       book_leverage
                                                               
roa                        -0.0009 (0.0032)    7.58e-5 (0.0001)
ebitda_at                 -0.1434* (0.0595)     0.0001 (0.0001)
log(at_thousand)          0.0336** (0.0094)     0.0048 (0.0055)
treated x indexyear = -3 0.0316*** (0.0080)  0.0348*** (0.0081)
treated x indexyear = -2  0.0144** (0.0048)     0.0050 (0.0071)
treated x indexyear = 0   -0.0137* (0.0065)    -0.0079 (0.0067)
treated x indexyear = 1   -0.0124. (0.0061) -0.0333*** (0.0079)
treated x indexyear = 2   -0.0138. (0.0080)  -0.0234** (0.0083)
treated x indexyear = 3    -0.0175 (0.0111)  -0.0301** (0.0097)
Fixed-Effects:           ------------------ -------------------
gvkey                                   Yes                 Yes
indexyear                               Yes                 Yes
ff_30ind_name-indexyear                 Yes                 Yes
________________________ __________________ ___________________
S.E.: Clustered           by: gvkey & ff_3.   by: gvkey & ff_3.
Observations                         14,669              17,721
R2                                  0.84124             0.71226
Within R2                           0.02451             0.00714
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
bb %>% 
  iplot(., 
        xlab = paste("Time to treatment (Year; 0 = ", base_year, ")", sep = ""),
        main = paste("Treatment Effect (TWFE): fiscal year & `", intensity_measure_name, "`", sep = ""), 
        ref.line = FALSE,
        ref.line.par = list(col = "red", lty = 2),
        pt.join = FALSE
        ); axis(1, at = -7:2); abline(v = 0.5, col = "red", lty = 2, lwd = 3); legend('bottomleft', bty = "n", col = c(1, 2), pch = c(20, 17), legend = c('Large', 'Small'))

test the statistical difference between the treatment effect estimate across two samples:

Show the code
# Calculate the Wald statistics 
model_large <- bb$`sample.var: large; sample: Large`
model_small <- bb$`sample.var: large; sample: Small`
## get the name of the coefficnet of interests 
coef_names <- names(model_large$coefficients) %>% 
  .[str_detect(string = ., pattern = "::")]

coef_large <- coef(model_large)[coef_names]
coef_small <- coef(model_small)[coef_names] 

# Difference in treatment effects
diff_coef <- coef_large - coef_small

# Variance of the difference
var_diff <- vcov(model_large)[coef_names, coef_names] + vcov(model_small)[coef_names, coef_names]

# Wald statistic for each treatment effect estimate 
wald_stat <- (diff_coef)^2 / diag(var_diff) 
# (t(diff_coef) %*% solve(var_diff) %*% (diff_coef))

# Degrees of freedom
df <- 1 

# P-value
p_value <- 1 - pchisq(wald_stat, df)

convert_p_to_stars <- function(p_values) {
  # Initialize a character vector to store the significance stars
  stars <- character(length(p_values))
  
  # Assign stars based on p-value thresholds
  stars[p_values < 0.001] <- "***"
  stars[p_values >= 0.001 & p_values < 0.01] <- "**"
  stars[p_values >= 0.01 & p_values < 0.05] <- "*"
  stars[p_values >= 0.05 & p_values < 0.1] <- "."
  stars[p_values >= 0.1] <- ""
  
  return(stars)
}

# Output results
cat("Wald test for the difference in the treatment effect\n between the Large firms and Small firms: \n\n"); 
data.frame(
  Diff = diff_coef, 
  `Std. Error` = sqrt(diag(var_diff)), 
  `Wald stat` = wald_stat, 
  `P value` = p_value, 
  Star = convert_p_to_stars(p_value)
) 
cat("Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 \n") 
Wald test for the difference in the treatment effect
 between the Large firms and Small firms: 

                              Diff  Std..Error  Wald.stat    P.value Star
indexyear::-3:treated -0.003214634 0.011334485 0.08043767 0.77670516     
indexyear::-2:treated  0.009372697 0.008536675 1.20545661 0.27223380     
indexyear::0:treated  -0.005872131 0.009302074 0.39850325 0.52786325     
indexyear::1:treated   0.020953748 0.009964421 4.42200590 0.03547831    *
indexyear::2:treated   0.009569850 0.011510913 0.69117939 0.40576352     
indexyear::3:treated   0.012619826 0.014693625 0.73764747 0.39041552     
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 

s3.3. land intensity

land_intensity is chosen to measure a firm’s long-term exposure to land and improvements at cost under the PPE.

Show the code
## choose the group definition: 
intensity_measure_name <- c(
  "contract_intensity", 
  "ppe_lease_intensity", 
  "building_intensity", 
  "land_intensity",
  "bnl_intensity")[4]

data_firm <- data %>% 
  filter(fyear == intensity_measure_year) %>% # use `fyear` may create multiple observations for the same firm. E.g. filter(gvkey == 23535, dyear == 2005) 
  group_by(fyear) %>% 
  mutate(median_at = median(at, na.rm = TRUE)) %>% 
  ungroup() %>% 
  mutate(large = ifelse(at > median_at, 1, 0)) %>% 
  select(gvkey, intensity_2000 = all_of(intensity_measure_name), large) 
  
data_did <- data %>% 
  ## merge the grouping variable 
  left_join(y = data_firm, by = join_by(gvkey) ) %>% 
  ## merge the FF 30 industry classifiaction 
  left_join(y = FF_30ind, by = join_by(sic)) %>% 
  ## exclude certain industries 
  filter(
    ff_30ind != 20, # exclude Utiltiy (number 20) 
    !(sic >= 6000 & sic <= 6199) # exclude banks under Banking, Insurance, Real Estate, Trading (number 29)
  ) %>% 
  ## pre- & post- 
  mutate(
    indexyear = (fyear - base_year), # year index with 2005 as base 0.
    post_2005 = as.numeric(fyear > base_year)  # whether it is after the 2005 reform 
  ) 

## gvkey(s) for balanced panel": 
data_did_balanced_id <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  filter(fyear >= period_start - n_pre & fyear <= period_end) %>% 
  group_by(gvkey) %>% 
  summarise(count_obs = sum(!is.na(book_leverage) & !is.na(intensity_2000))) %>% 
  ungroup() %>% 
  filter(count_obs == period_end - period_start + 1 + n_pre) %>% 
  .$gvkey 

data_intensity_panel <- data %>% 
  filter(fyear < 2007) %>%
  select(gvkey, fyear, all_of(intensity_measure_name)) %>% 
  pivot_wider(names_from = fyear, values_from = all_of(intensity_measure_name)) 

DiD Analysis:

Show the code
cat(intensity_measure_name); cat(": \n"); 

did_model_s3c_a <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0) 
  ) %>% 
  fixest::feols(fml = book_leverage ~ treated*post_2005*large | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) 
  
did_model_s3c_b <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>% 
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0) 
  ) %>% 
  fixest::feols(fml = book_leverage ~ intensity_2000*post_2005*large | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) 

mget(ls(pattern = "did_model_s3c_")) %>% 
  `names<-`(value = c("(a) treatment", "(b) intensity")) %>% 
  etable() %>% 
  knitr::kable(format = "html", caption = paste("DiD Results with `", intensity_measure_name, "`", sep = "")) %>% 
  kableExtra::kable_styling(
    font_size = 8,       # Smaller font (default is 16px)
    full_width = FALSE,   # Table width fits content 
    bootstrap_options = c("striped", "condensed")
  )
land_intensity: 
DiD Results with `land_intensity`
(a) treatment (b) intensity
Dependent Var.: book_leverage book_leverage
treated x post_2005 -0.0308*** (0.0067)
post_2005 x large -0.0023 (0.0072) -0.0048 (0.0048)
treated x post_2005 x large 0.0170. (0.0090)
intensity_2000 x post_2005 -0.0821*** (0.0221)
intensity_2000 x post_2005 x large 0.1605* (0.0592)
Fixed-Effects: ------------------- -------------------
gvkey Yes Yes
fyear Yes Yes
ff_30ind_name-fyear Yes Yes
__________________________________ ___________________ ___________________
S.E.: Clustered by: gvkey & ff_3. by: gvkey & ff_3.
Observations 26,763 26,763
R2 0.79348 0.79310
Within R2 0.00227 0.00040

DDD plot:

Show the code
## a test ground: 
nn <- data_did %>%
  filter(book_leverage >= 0 & book_leverage <= 1) %>%
  # filter(gvkey %in% data_did_balanced_id) %>% 
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, indexyear, intensity_2000, post_2005,
         book_leverage, debt_ebitda, sic, ff_30ind_name,
         at, ebitda, large, roa, ppent, bnl_intensity, ppe_lease_intensity, 
         altman_Z, kz, market_book, tangibility, current_ratio) %>%
  filter(fyear >= period_start - n_pre & fyear <= period_end) %>%
  filter(!is.na(intensity_2000) & !is.na(at)) %>%
  mutate(
    gvkey = as.factor(gvkey),
    fyear = as.factor(fyear),
    # treated = ifelse(intensity_2000 > 0, "Treated", "Untreated"),
    treated = ifelse(intensity_2000 > 0, 1, 0),
    ebitda_at = ebitda / at,
    at_thousand = at * 10^-3,
    large = ifelse(large, yes = "Large", no = "Small"), 
    tangiblity_exbnl = tangibility - bnl_intensity, 
    bnl = bnl_intensity * at, 
    # large = ifelse(large, yes = 1, no = 0),
    treated_large = paste(treated, large, sep = "_") 
  ) %>%
  # separately estimate the regression coefficients from two subsamples: 
  fixest::feols(fml = book_leverage ~ roa + ebitda_at + log(at_thousand) + # tangiblity_exbnl + 
                ### adding different controls: 
                # altman_Z + kz + market_book + tangibility + current_ratio + 
                i(indexyear, treated, ref = -1) | gvkey + indexyear + ff_30ind_name^indexyear,
                data = ., 
                cluster = c("gvkey", "ff_30ind_name"), 
                split = ~ large ## split the sample by the variable 'large' 
                )
NOTE: 324 observations removed because of NA values (RHS: 324).
Show the code
# mm$coeftable %>% data.frame() %>%  rownames_to_column(., var = "Rowname") %>% mutate(Treated = str_detect(string = Rowname, pattern = "Treated"), Period = str_extract(string = Rowname, pattern = "-?\\d+"), Size = str_detect(string = Rowname, pattern = "Large")) %>% arrange(Treated, Size) %>% as_tibble() 

etable(nn)
                                      nn.1                nn.2
Sample (large)                       Large               Small
Dependent Var.:              book_leverage       book_leverage
                                                              
roa                       -0.0008 (0.0031)    7.64e-5 (0.0001)
ebitda_at                -0.1419* (0.0597)     0.0001 (0.0001)
log(at_thousand)         0.0338** (0.0098)     0.0049 (0.0055)
treated x indexyear = -3 0.0300** (0.0089)  0.0376*** (0.0092)
treated x indexyear = -2 0.0131** (0.0038)     0.0032 (0.0060)
treated x indexyear = 0  -0.0203* (0.0077)    -0.0104 (0.0066)
treated x indexyear = 1   -0.0126 (0.0081) -0.0357*** (0.0080)
treated x indexyear = 2   -0.0113 (0.0085)  -0.0289** (0.0102)
treated x indexyear = 3   -0.0108 (0.0098)  -0.0314** (0.0099)
Fixed-Effects:           ----------------- -------------------
gvkey                                  Yes                 Yes
indexyear                              Yes                 Yes
ff_30ind_name-indexyear                Yes                 Yes
________________________ _________________ ___________________
S.E.: Clustered          by: gvkey & ff_3.   by: gvkey & ff_3.
Observations                        14,741              17,749
R2                                 0.84128             0.71371
Within R2                          0.02475             0.00795
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
nn %>% 
  iplot(., 
        xlab = paste("Time to treatment (Year; 0 = ", base_year, ")", sep = ""),
        main = paste("Treatment Effect (TWFE): fiscal year & `", intensity_measure_name, "`", sep = ""), 
        ref.line = FALSE,
        ref.line.par = list(col = "red", lty = 2),
        pt.join = FALSE
        ); axis(1, at = -7:2); abline(v = 0.5, col = "red", lty = 2, lwd = 3); legend('bottomleft', bty = "n", col = c(1, 2), pch = c(20, 17), legend = c('Large', 'Small'))

test the statistical difference between the treatement effect estimate across two samples:

Show the code
# Calculate the Wald statistics 
model_large <- nn$`sample.var: large; sample: Large`
model_small <- nn$`sample.var: large; sample: Small`
## get the name of the coefficnet of interests 
coef_names <- names(model_large$coefficients) %>% 
  .[str_detect(string = ., pattern = "::")]

coef_large <- coef(model_large)[coef_names]
coef_small <- coef(model_small)[coef_names] 

# Difference in treatment effects
diff_coef <- coef_large - coef_small

# Variance of the difference
var_diff <- vcov(model_large)[coef_names, coef_names] + vcov(model_small)[coef_names, coef_names]


# Wald statistic for each treatment effect estimate 
wald_stat <- (diff_coef)^2 / diag(var_diff) 
# (t(diff_coef) %*% solve(var_diff) %*% (diff_coef))

# Degrees of freedom
df <- 1 

# P-value
p_value <- 1 - pchisq(wald_stat, df)

convert_p_to_stars <- function(p_values) {
  # Initialize a character vector to store the significance stars
  stars <- character(length(p_values))
  
  # Assign stars based on p-value thresholds
  stars[p_values < 0.001] <- "***"
  stars[p_values >= 0.001 & p_values < 0.01] <- "**"
  stars[p_values >= 0.01 & p_values < 0.05] <- "*"
  stars[p_values >= 0.05 & p_values < 0.1] <- "."
  stars[p_values >= 0.1] <- ""
  
  return(stars)
}

# Output results
cat("Wald test for the difference in the treatment effect\n between the Large firms and Small firms: \n\n"); 
data.frame(
  Diff = diff_coef, 
  `Std. Error` = sqrt(diag(var_diff)), 
  `Wald stat` = wald_stat, 
  `P value` = p_value, 
  Star = convert_p_to_stars(p_value)
) 
cat("Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 \n") 
Wald test for the difference in the treatment effect
 between the Large firms and Small firms: 

                              Diff  Std..Error Wald.stat    P.value Star
indexyear::-3:treated -0.007598785 0.012802509 0.3522882 0.55282066     
indexyear::-2:treated  0.009869943 0.007150296 1.9053786 0.16747752     
indexyear::0:treated  -0.009892381 0.010166007 0.9468930 0.33051142     
indexyear::1:treated   0.023125249 0.011382467 4.1276229 0.04218857    *
indexyear::2:treated   0.017512363 0.013278817 1.7392848 0.18722947     
indexyear::3:treated   0.020618901 0.013909916 2.1972628 0.13825604     
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 

The wald test shows that the treatment effect between the large and small firms are indifferent before 2005 and significantly positive afterwards. In particular, after the policy shock in 2005, the large firms with positive land_intensity have higher book leverages relative to the small firms with positive land_intensity.

Since we expect that large firms are not affected by this treatment after 2005, even being in the treatment group, we can argue that small firms which receive an exogenous shock to the option value of their lease contracts will reduce their leverage.

s3.4. builindg and land intensity

bnl_intensity is chosen to measure a firm’s long-term exposure to builings, land and improvements at cost under the PPE.

Show the code
## choose the group definition: 
intensity_measure_name <- c(
  "contract_intensity", 
  "ppe_lease_intensity", 
  "building_intensity", 
  "land_intensity",
  "bnl_intensity")[5]

data_firm <- data %>% 
  filter(fyear == intensity_measure_year) %>% # use `fyear` may create multiple observations for the same firm. E.g. filter(gvkey == 23535, dyear == 2005) 
  group_by(fyear) %>% 
  mutate(
    median_at = median(at, na.rm = TRUE), 
    
    ) %>% 
  ungroup() %>% 
  mutate(large = ifelse(at > median_at, 1, 0)) %>% 
  select(gvkey, intensity_2000 = all_of(intensity_measure_name), large) 
  
data_did <- data %>% 
  ## merge the grouping variable 
  left_join(y = data_firm, by = join_by(gvkey) ) %>% 
  ## merge the FF 30 industry classifiaction 
  left_join(y = FF_30ind, by = join_by(sic)) %>% 
  ## exclude certain industries 
  filter(
    ff_30ind != 20, # exclude Utiltiy (number 20) 
    !(sic >= 6000 & sic <= 6199) # exclude banks under Banking, Insurance, Real Estate, Trading (number 29)
  ) %>% 
  ## pre- & post- 
  mutate(
    indexyear = (fyear - base_year), # year index with 2005 as base 0.
    post_2005 = as.numeric(fyear > base_year)  # whether it is after the 2005 reform 
  ) 

## gvkey(s) for balanced panel": 
data_did_balanced_id <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  filter(fyear >= period_start - n_pre & fyear <= period_end) %>% 
  group_by(gvkey) %>% 
  summarise(count_obs = sum(!is.na(book_leverage) & !is.na(intensity_2000))) %>% 
  ungroup() %>% 
  filter(count_obs == period_end - period_start + 1 + n_pre) %>% 
  .$gvkey 

data_intensity_panel <- data %>% 
  filter(fyear < 2007) %>%
  select(gvkey, fyear, all_of(intensity_measure_name)) %>% 
  pivot_wider(names_from = fyear, values_from = all_of(intensity_measure_name)) 

DiD Analysis:

In this part of the analysis, I also added the firm-year controls in the DiD and triple difference analyses. The first is called àt_thousand, which is the total asset of firm i in fiscal year t in thousand of dollars. The second is the ebitda_at, which is the EBITDA of firm i in fiscal year t divided by its total asset. Adding both controls positively correlated with the book leverage, they do not have a significant impact on the coefficient estimate of interest, which is the coefficient on treated x post_2005 and intensity_2000 x post_2005.

Show the code
did_model_pattern = "did_model_s3d_" 
cat(intensity_measure_name); cat(": \n"); 

did_model_s3d_a1 <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, at, ebitda, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0), 
    ebitda_at = ebitda / at
  ) %>% 
  fixest::feols(fml = book_leverage ~ treated*post_2005 | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) 
  
did_model_s3d_a2 <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, at, ebitda, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0), 
    ebitda_at = ebitda / at, 
    at_thousand = at * 10^-3 # scale the total asset 
  ) %>% 
  fixest::feols(fml = book_leverage ~ treated*post_2005 + ebitda_at + at_thousand | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) 

did_model_s3d_b1 <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>% 
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, at, ebitda, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0), 
    ebitda_at = ebitda / at 
  ) %>% 
  fixest::feols(fml = book_leverage ~ intensity_2000*post_2005 | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) 

did_model_s3d_b2 <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>% 
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, at, ebitda, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0), 
    ebitda_at = ebitda / at, 
    at_thousand = at * 10^-3
  ) %>% 
  fixest::feols(fml = book_leverage ~ intensity_2000*post_2005 + ebitda_at + at_thousand  | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) 

did_model_s3d_c <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, at, ebitda, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0), 
    ebitda_at = ebitda / at, 
    at_thousand = at * 10^-3
  ) %>% 
  fixest::feols(fml = book_leverage ~ treated*post_2005*large | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) 

did_model_s3d_c2 <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, at, ebitda, roa, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0), 
    ebitda_at = ebitda / at, 
    at_thousand = at * 10^-3
  ) %>% 
  fixest::feols(fml = book_leverage ~ treated*post_2005*large + ebitda_at + at_thousand | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) 
  
did_model_s3d_d <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>% 
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, at, ebitda, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0), 
    ebitda_at = ebitda / at, 
    at_thousand = at * 10^-3
  ) %>% 
  fixest::feols(fml = book_leverage ~ intensity_2000*post_2005*large | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) 

did_model_s3d_d2 <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>% 
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, at, ebitda, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0), 
    ebitda_at = ebitda / at, 
    at_thousand = at * 10^-3
  ) %>% 
  fixest::feols(fml = book_leverage ~ intensity_2000*post_2005*large + ebitda_at + at_thousand | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) 

## make the table 
mget(ls(pattern = did_model_pattern)) %>% 
  `names<-`(value = sapply(X = .,
                           FUN = function(x) any(str_detect(string = as.character(x$fml), pattern = "intensity")) ) %>% 
              ifelse(test = ., yes = "Intensity", no = "Treatment") %>% 
              paste(paste("(", 1:length(.), ")", sep = ""), ., sep = " ")
            ) %>% 
  etable() %>% 
  knitr::kable(
    format = "html", 
    caption = paste("DiD Results with `", intensity_measure_name, "`", sep = "")
    ) %>% 
  kableExtra::kable_styling(
    font_size = 8,       # Smaller font (default is 16px)
    full_width = FALSE,   # Table width fits content 
    bootstrap_options = c("striped", "condensed")
  ) %>% 
  kableExtra::footnote(
    general = "Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1",
    general_title = "Note:"
  ) 
bnl_intensity: 
DiD Results with `bnl_intensity`
(1) Treatment (2) Treatment (3) Intensity (4) Intensity (5) Treatment (6) Treatment (7) Intensity (8) Intensity
Dependent Var.: book_leverage book_leverage book_leverage book_leverage book_leverage book_leverage book_leverage book_leverage
treated x post_2005 -0.0215*** (0.0036) -0.0222*** (0.0035) -0.0291*** (0.0067) -0.0295*** (0.0065)
ebitda_at 0.0003. (0.0002) 0.0003. (0.0002) 0.0003. (0.0002) 0.0003. (0.0002)
at_thousand 0.0008* (0.0003) 0.0008* (0.0003) 0.0008* (0.0003) 0.0008* (0.0003)
intensity_2000 x post_2005 -0.0535*** (0.0116) -0.0593*** (0.0132) -0.0784*** (0.0132) -0.0801*** (0.0132)
post_2005 x large 0.0014 (0.0075) -0.0009 (0.0069) -0.0043 (0.0049) -0.0052 (0.0050)
treated x post_2005 x large 0.0108 (0.0090) 0.0120 (0.0090)
intensity_2000 x post_2005 x large 0.0512. (0.0259) 0.0451 (0.0269)
Fixed-Effects: ------------------- ------------------- ------------------- ------------------- ------------------- ------------------- ------------------- -------------------
gvkey Yes Yes Yes Yes Yes Yes Yes Yes
fyear Yes Yes Yes Yes Yes Yes Yes Yes
ff_30ind_name-fyear Yes Yes Yes Yes Yes Yes Yes Yes
__________________________________ ___________________ ___________________ ___________________ ___________________ ___________________ ___________________ ___________________ ___________________
S.E.: Clustered by: gvkey & ff_3. by: gvkey & ff_3. by: gvkey & ff_3. by: gvkey & ff_3. by: gvkey & ff_3. by: gvkey & ff_3. by: gvkey & ff_3. by: gvkey & ff_3.
Observations 26,664 26,414 26,664 26,414 26,664 26,414 26,664 26,414
R2 0.79243 0.79204 0.79229 0.79192 0.79250 0.79210 0.79236 0.79198
Within R2 0.00196 0.00311 0.00131 0.00256 0.00232 0.00340 0.00165 0.00281
Note:
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Make a plot:

DiD only (with balanced panel)
Show the code
## a test ground: 
cat("use intensity: \n")
use intensity: 
Show the code
mm_intensity <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>%
  filter(gvkey %in% data_did_balanced_id) %>% 
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, indexyear, intensity_2000, post_2005,
         book_leverage, debt_ebitda, sic, ff_30ind_name,
         at, ebitda, large, roa, ppent, bnl_intensity, ppe_lease_intensity, 
         altman_Z, kz, market_book, tangibility, current_ratio) %>%
  filter(fyear >= period_start - n_pre & fyear <= period_end) %>%
  filter(!is.na(intensity_2000) & !is.na(at)) %>%
  mutate(
    gvkey = as.factor(gvkey),
    fyear = as.factor(fyear),
    # treated = ifelse(intensity_2000 > 0, "Treated", "Untreated"),
    treated = ifelse(intensity_2000 > 0, 1, 0),
    ebitda_at = ebitda / at,
    at_thousand = at * 10^-3,
    large = ifelse(large, yes = "Large", no = "Small"), 
    tangiblity_exbnl = tangibility - bnl_intensity, 
    bnl = bnl_intensity * at, 
    # large = ifelse(large, yes = 1, no = 0),
    treated_large = paste(treated, large, sep = "_") 
  ) %>%
  # separately estimate the regression coefficients from two subsamples: 
  fixest::feols(fml = book_leverage ~ roa + ebitda_at + log(at_thousand) + # tangiblity_exbnl + 
                ### adding different controls: 
                altman_Z + tangibility + # current_ratio + 
                  # kz + market_book + 
                i(indexyear, intensity_2000, ref = -1) | gvkey + indexyear + ff_30ind_name^indexyear,
                data = ., 
                cluster = c("gvkey", "ff_30ind_name"), 
                # split = ~ large ## split the sample by the variable 'large' 
                )
NOTE: 1,532 observations removed because of NA values (RHS: 1,532).
Show the code
etable(mm_intensity)
                                       mm_intensity
Dependent Var.:                       book_leverage
                                                   
roa                             -0.0052*** (0.0011)
ebitda_at                         0.0025** (0.0008)
log(at_thousand)                  0.0160** (0.0054)
altman_Z                         8.84e-5* (4.07e-5)
tangibility                      0.1867*** (0.0214)
intensity_2000 x indexyear = -3     0.0008 (0.0299)
intensity_2000 x indexyear = -2    -0.0032 (0.0132)
intensity_2000 x indexyear = 0  -0.0380*** (0.0090)
intensity_2000 x indexyear = 1  -0.0525*** (0.0114)
intensity_2000 x indexyear = 2   -0.0603** (0.0167)
intensity_2000 x indexyear = 3    -0.0463* (0.0212)
Fixed-Effects:                  -------------------
gvkey                                           Yes
indexyear                                       Yes
ff_30ind_name-indexyear                         Yes
_______________________________ ___________________
S.E.: Clustered                   by: gvkey & ff_3.
Observations                                 21,197
R2                                          0.75241
Within R2                                   0.02271
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
mm_intensity %>% 
  iplot(., 
        xlab = paste("Time to treatment (Year; 0 = ", base_year, ")", sep = ""),
        main = paste("Treatment Effect (TWFE): fiscal year & `", intensity_measure_name, "`", sep = ""), 
        ref.line = FALSE,
        ref.line.par = list(col = "red", lty = 2),
        pt.join = FALSE
        ); axis(1, at = -7:2); abline(v = 0.5, col = "red", lty = 2, lwd = 3); legend('bottomleft', bty = "n", col = c(1, 2), pch = c(20, 17), legend = c('Large', 'Small'))

Show the code
## with the binary grouping:  
cat("use treated: \n")
use treated: 
Show the code
mm_binary <- data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>%
  filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, indexyear, intensity_2000, post_2005,
         book_leverage, debt_ebitda, sic, ff_30ind_name,
         at, ebitda, large, roa, ppent, bnl_intensity, ppe_lease_intensity, 
         altman_Z, kz, market_book, tangibility, current_ratio) %>%
  filter(fyear >= period_start - n_pre & fyear <= period_end) %>%
  filter(!is.na(intensity_2000) & !is.na(at)) %>%
  mutate(
    gvkey = as.factor(gvkey),
    fyear = as.factor(fyear),
    # treated = ifelse(intensity_2000 > 0, "Treated", "Untreated"),
    treated = ifelse(intensity_2000 > 0, 1, 0),
    ebitda_at = ebitda / at,
    at_thousand = at * 10^-3,
    large = ifelse(large, yes = "Large", no = "Small"), 
    tangiblity_exbnl = tangibility - bnl_intensity, 
    bnl = bnl_intensity * at, 
    # large = ifelse(large, yes = 1, no = 0),
    treated_large = paste(treated, large, sep = "_") 
  ) %>%
  # separately estimate the regression coefficients from two subsamples: 
  fixest::feols(fml = book_leverage ~ roa + ebitda_at + log(at_thousand) + # tangiblity_exbnl + 
                ### adding different controls: 
                altman_Z + tangibility + # current_ratio + 
                  # kz + market_book + 
                i(indexyear, treated, ref = -1) | gvkey + indexyear + ff_30ind_name^indexyear,
                data = ., 
                cluster = c("gvkey", "ff_30ind_name"), 
                # split = ~ large ## split the sample by the variable 'large' 
                )
NOTE: 1,532 observations removed because of NA values (RHS: 1,532).
Show the code
etable(mm_binary)
                                   mm_binary
Dependent Var.:                book_leverage
                                            
roa                      -0.0052*** (0.0012)
ebitda_at                  0.0026** (0.0008)
log(at_thousand)           0.0157** (0.0054)
altman_Z                  8.88e-5* (4.11e-5)
tangibility               0.1870*** (0.0218)
treated x indexyear = -3   0.0202** (0.0060)
treated x indexyear = -2     0.0024 (0.0044)
treated x indexyear = 0   -0.0106** (0.0033)
treated x indexyear = 1     -0.0098 (0.0059)
treated x indexyear = 2    -0.0116. (0.0065)
treated x indexyear = 3    -0.0138* (0.0058)
Fixed-Effects:           -------------------
gvkey                                    Yes
indexyear                                Yes
ff_30ind_name-indexyear                  Yes
________________________ ___________________
S.E.: Clustered            by: gvkey & ff_3.
Observations                          21,197
R2                                   0.75276
Within R2                            0.02411
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
mm_binary %>% 
  iplot(., 
        xlab = paste("Time to treatment (Year; 0 = ", base_year, ")", sep = ""),
        main = paste("Treatment Effect (TWFE): fiscal year & `", intensity_measure_name, "`", sep = ""), 
        ref.line = FALSE,
        ref.line.par = list(col = "red", lty = 2),
        pt.join = FALSE
        ); axis(1, at = -7:2); abline(v = 0.5, col = "red", lty = 2, lwd = 3); legend('bottomleft', bty = "n", col = c(1, 2), pch = c(20, 17), legend = c('Large', 'Small'))  

DiD with Subsample
Show the code
data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, indexyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, at, ebitda, large, roa) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  filter(!is.na(intensity_2000) & !is.na(at)) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = ifelse(intensity_2000 > 0, "Treated", "Untreated"), 
    ebitda_at = ebitda / at, 
    at_thousand = at * 10^-3, 
    large = factor(ifelse(large, yes = "Large", no = "Small"), levels = c("Large", "Small") ), 
    treated_large = paste(treated, large, sep = "_")
  ) %>% 
  fixest::feols(fml = book_leverage ~ i(indexyear, treated, ref = -1)*large + roa + ebitda_at + at_thousand | gvkey + indexyear + ff_30ind_name^indexyear, data = ., cluster = c("gvkey", "ff_30ind_name")) %>% 
  .$coeftable 
NOTE: 250 observations removed because of NA values (RHS: 250).
The variables 'indexyear::-2:treated::Untreated', 'indexyear::0:treated::Untreated' and thirteen others have been removed because of collinearity (see $collin.var).
                                                 Estimate   Std. Error
indexyear::-2:treated::Treated               0.0070514090 0.0033104034
indexyear::0:treated::Treated               -0.0078798750 0.0053801198
indexyear::1:treated::Treated               -0.0339921025 0.0075000077
indexyear::2:treated::Treated               -0.0272345414 0.0085079400
indexyear::3:treated::Treated               -0.0335952171 0.0088591556
roa                                          0.0001027132 0.0001317617
ebitda_at                                    0.0002418524 0.0001965989
at_thousand                                  0.0007673121 0.0003167689
largeLarge:indexyear::-2:treated::Treated   -0.0026754138 0.0046977203
largeSmall:indexyear::-2:treated::Treated   -0.0051546624 0.0079100579
largeLarge:indexyear::-2:treated::Untreated -0.0064839755 0.0042577838
largeLarge:indexyear::0:treated::Treated    -0.0032179495 0.0064883568
largeLarge:indexyear::0:treated::Untreated   0.0033449464 0.0082101790
largeLarge:indexyear::1:treated::Treated     0.0092626739 0.0070621320
largeLarge:indexyear::1:treated::Untreated  -0.0082729887 0.0074808195
largeLarge:indexyear::2:treated::Treated     0.0038899334 0.0090279664
largeLarge:indexyear::2:treated::Untreated  -0.0073698220 0.0062264462
largeLarge:indexyear::3:treated::Treated     0.0205076810 0.0099512136
largeLarge:indexyear::3:treated::Untreated   0.0123548963 0.0118176606
                                               t value     Pr(>|t|)
indexyear::-2:treated::Treated               2.1300754 4.209013e-02
indexyear::0:treated::Treated               -1.4646282 1.541611e-01
indexyear::1:treated::Treated               -4.5322757 9.951029e-05
indexyear::2:treated::Treated               -3.2010735 3.395889e-03
indexyear::3:treated::Treated               -3.7921466 7.315823e-04
roa                                          0.7795371 4.422029e-01
ebitda_at                                    1.2301817 2.288649e-01
at_thousand                                  2.4223089 2.214511e-02
largeLarge:indexyear::-2:treated::Treated   -0.5695132 5.735490e-01
largeSmall:indexyear::-2:treated::Treated   -0.6516592 5.199345e-01
largeLarge:indexyear::-2:treated::Untreated -1.5228522 1.390110e-01
largeLarge:indexyear::0:treated::Treated    -0.4959575 6.237951e-01
largeLarge:indexyear::0:treated::Untreated   0.4074146 6.868017e-01
largeLarge:indexyear::1:treated::Treated     1.3115974 2.003094e-01
largeLarge:indexyear::1:treated::Untreated  -1.1058934 2.781844e-01
largeLarge:indexyear::2:treated::Treated     0.4308759 6.698575e-01
largeLarge:indexyear::2:treated::Untreated  -1.1836322 2.465105e-01
largeLarge:indexyear::3:treated::Treated     2.0608221 4.871854e-02
largeLarge:indexyear::3:treated::Untreated   1.0454604 3.047522e-01
attr(,"type")
[1] "Clustered (gvkey & ff_30ind_name)"
Show the code
## a test ground: 
mm <- data_did %>%
  filter(book_leverage >= 0 & book_leverage <= 1) %>%
  # filter(gvkey %in% data_did_balanced_id) %>% 
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, indexyear, intensity_2000, post_2005,
         book_leverage, debt_ebitda, sic, ff_30ind_name,
         at, ebitda, large, roa, ppent, bnl_intensity, ppe_lease_intensity, 
         altman_Z, kz, market_book, tangibility, current_ratio) %>%
  filter(fyear >= period_start - n_pre & fyear <= period_end) %>%
  filter(!is.na(intensity_2000) & !is.na(at)) %>%
  mutate(
    gvkey = as.factor(gvkey),
    fyear = as.factor(fyear),
    # treated = ifelse(intensity_2000 > 0, "Treated", "Untreated"),
    treated = ifelse(intensity_2000 > 0, 1, 0),
    ebitda_at = ebitda / at,
    at_thousand = at * 10^-3,
    large = ifelse(large, yes = "Large", no = "Small"), 
    tangiblity_exbnl = tangibility - bnl_intensity, 
    bnl = bnl_intensity * at, 
    # large = ifelse(large, yes = 1, no = 0),
    treated_large = paste(treated, large, sep = "_") 
  ) %>%
  # separately estimate the regression coefficients from two subsamples: 
  fixest::feols(fml = book_leverage ~ roa + ebitda_at + log(at_thousand) + # tangiblity_exbnl + 
                ### adding different controls: 
                # altman_Z + kz + market_book + tangibility + current_ratio + 
                i(indexyear, treated, ref = -1) | gvkey + indexyear + ff_30ind_name^indexyear,
                data = ., 
                cluster = c("gvkey", "ff_30ind_name"), 
                split = ~ large ## split the sample by the variable 'large' 
                )
NOTE: 324 observations removed because of NA values (RHS: 324).
Show the code
# mm$coeftable %>% data.frame() %>%  rownames_to_column(., var = "Rowname") %>% mutate(Treated = str_detect(string = Rowname, pattern = "Treated"), Period = str_extract(string = Rowname, pattern = "-?\\d+"), Size = str_detect(string = Rowname, pattern = "Large")) %>% arrange(Treated, Size) %>% as_tibble() 

etable(mm)
                                       mm.1                mm.2
Sample (large)                        Large               Small
Dependent Var.:               book_leverage       book_leverage
                                                               
roa                        -0.0009 (0.0032)    7.52e-5 (0.0001)
ebitda_at                 -0.1437* (0.0597)     0.0001 (0.0001)
log(at_thousand)          0.0335** (0.0095)     0.0048 (0.0055)
treated x indexyear = -3 0.0342*** (0.0086)  0.0356*** (0.0078)
treated x indexyear = -2   0.0160* (0.0059)     0.0035 (0.0068)
treated x indexyear = 0   -0.0145. (0.0074)    -0.0066 (0.0067)
treated x indexyear = 1    -0.0112 (0.0071) -0.0312*** (0.0080)
treated x indexyear = 2   -0.0133. (0.0078)   -0.0228* (0.0091)
treated x indexyear = 3    -0.0183 (0.0126)  -0.0302** (0.0100)
Fixed-Effects:           ------------------ -------------------
gvkey                                   Yes                 Yes
indexyear                               Yes                 Yes
ff_30ind_name-indexyear                 Yes                 Yes
________________________ __________________ ___________________
S.E.: Clustered           by: gvkey & ff_3.   by: gvkey & ff_3.
Observations                         14,648              17,721
R2                                  0.84134             0.71226
Within R2                           0.02468             0.00715
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
mm %>% 
  iplot(., 
        xlab = paste("Time to treatment (Year; 0 = ", base_year, ")", sep = ""),
        main = paste("Treatment Effect (TWFE): fiscal year & `", intensity_measure_name, "`", sep = ""), 
        ref.line = FALSE,
        ref.line.par = list(col = "red", lty = 2),
        pt.join = FALSE
        ); axis(1, at = -7:2); abline(v = 0.5, col = "red", lty = 2, lwd = 3); legend('bottomleft', bty = "n", col = c(1, 2), pch = c(20, 17), legend = c('Large', 'Small'))

Show the code
### Calculate the Wald statistics 
model_large <- mm$`sample.var: large; sample: Large`
model_small <- mm$`sample.var: large; sample: Small`
## get the name of the coefficnet of interests 
coef_names <- names(model_large$coefficients) %>% 
  .[str_detect(string = ., pattern = "::")]

coef_large <- coef(model_large)[coef_names]
coef_small <- coef(model_small)[coef_names] 

# Difference in treatment effects
diff_coef <- coef_large - coef_small

# Variance of the difference
var_diff <- vcov(model_large)[coef_names, coef_names] + vcov(model_small)[coef_names, coef_names]

# Wald statistic for each treatment effect estimate 
wald_stat <- (diff_coef)^2 / diag(var_diff) 
# (t(diff_coef) %*% solve(var_diff) %*% (diff_coef))

# Degrees of freedom
df <- 1 

# P-value
p_value <- 1 - pchisq(wald_stat, df)

convert_p_to_stars <- function(p_values) {
  # Initialize a character vector to store the significance stars
  stars <- character(length(p_values))
  
  # Assign stars based on p-value thresholds
  stars[p_values < 0.001] <- "***"
  stars[p_values >= 0.001 & p_values < 0.01] <- "**"
  stars[p_values >= 0.01 & p_values < 0.05] <- "*"
  stars[p_values >= 0.05 & p_values < 0.1] <- "."
  stars[p_values >= 0.1] <- ""
  
  return(stars)
}

# Output results
cat("Wald test for the difference in the treatment effect\n between the Large firms and Small firms: \n\n"); 
Wald test for the difference in the treatment effect
 between the Large firms and Small firms: 
Show the code
data.frame(
  Diff = diff_coef, 
  `Std. Error` = sqrt(diag(var_diff)), 
  `Wald stat` = wald_stat, 
  `P value` = p_value, 
  Star = convert_p_to_stars(p_value)
) 
                              Diff  Std..Error  Wald.stat    P.value Star
indexyear::-3:treated -0.001363119 0.011628006 0.01374223 0.90667997     
indexyear::-2:treated  0.012518591 0.009051385 1.91284950 0.16664708     
indexyear::0:treated  -0.007947731 0.009985452 0.63350617 0.42607214     
indexyear::1:treated   0.019989423 0.010689657 3.49681725 0.06148689    .
indexyear::2:treated   0.009523742 0.011984678 0.63148424 0.42681141     
indexyear::3:treated   0.011904756 0.016102811 0.54655971 0.45972681     
Show the code
cat("Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 \n") 
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 

a test field with more controls:

Show the code
data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>%
  # filter(debt_ebitda >= 0 & debt_ebitda <= 15) %>% 
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>%
  select(
    gvkey, fyear, intensity_2000, post_2005, 
    book_leverage, debt_ebitda, sic, ff_30ind_name, 
    at, ebitda, roa, large, bnl_intensity, 
    altman_Z, kz, market_book, tangibility, current_ratio
  ) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
    gvkey = as.factor(gvkey), 
    fyear = as.factor(fyear), 
    treated = as.numeric(intensity_2000 > 0), 
    tangible = tangibility > 0, 
    large = ifelse(large == 1, yes = "Large", no = "Small"), 
    ebitda_at = ebitda / at, 
    at_thousand = at * 10^-3
  ) %>% 
 fixest::feols(fml = book_leverage ~ treated*post_2005*i(large) + 
                  # kz + market_book + 
                  tangibility + # roa +
                  altman_Z + current_ratio + # bnl_intensity +
                  ebitda_at + log(at_thousand) | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) %>% 
  etable() 
NOTE: 22,592 observations removed because of NA and infinite values (RHS: 22,592).
The variables 'treated', 'post_2005' and four others have been removed because of collinearity (see $collin.var).
                                                      .
Dependent Var.:                           book_leverage
                                                       
tangibility                          0.2106*** (0.0286)
altman_Z                              7.56e-6. (4.1e-6)
current_ratio                       -9.58e-5** (3.3e-5)
ebitda_at                              0.0001 (9.45e-5)
log(at_thousand)                        0.0084 (0.0051)
treated x post_2005                     0.0016 (0.0049)
post_2005 x large = Large              -0.0054 (0.0074)
treated x post_2005 x large = Large  -0.0094** (0.0026)
treated x post_2005 x large = Small   -0.0234* (0.0100)
Fixed-Effects:                      -------------------
gvkey                                               Yes
fyear                                               Yes
ff_30ind_name-fyear                                 Yes
___________________________________ ___________________
S.E.: Clustered                       by: gvkey & ff_3.
Observations                                     24,904
R2                                              0.78420
Within R2                                       0.02104
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

A test run…

Show the code
data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>%
  # filter(gvkey %in% data_did_balanced_id) %>%
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, at, ebitda, large, roa, bnl_intensity) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
      gvkey = as.factor(gvkey), 
      fyear = as.factor(fyear), 
      treated = as.numeric(intensity_2000 > 0), 
      ebitda_at = ebitda / at, 
      small = ifelse(large, yes = 0, no = 1),
      at_thousand = at * 10^-3
  ) %>% 
  fixest::feols(fml = book_leverage ~ treated*i(fyear, ref =2004) + roa + ebitda_at + log(at_thousand) | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name"), split = ~ large) %>% 
  summary()
NOTE: 21,082 observations removed because of NA values (RHS: 21,082, split: 10,485).
Notes from the estimations:
[x 2] The variables 'treated', 'fyear::2002' and four others have been removed because of collinearity (see $collin.var).
Standard-errors: Clustered (gvkey & ff_30ind_name) 
Sample: 0
                     Estimate Std. Error   t value   Pr(>|t|)    
roa                  0.000113   0.000127  0.889571 0.38155409    
ebitda_at            0.000165   0.000180  0.919055 0.36620519    
log(at_thousand)     0.005930   0.005781  1.025691 0.31413941    
treated:fyear::2002  0.013513   0.009004  1.500825 0.14500551    
treated:fyear::2003  0.008591   0.006354  1.352067 0.18757186    
treated:fyear::2005 -0.024833   0.006175 -4.021715 0.00041785 ***
treated:fyear::2006 -0.017211   0.007612 -2.260935 0.03203097 *  
treated:fyear::2007 -0.024732   0.007010 -3.527969 0.00152003 ** 
---
Sample: 1
                     Estimate Std. Error   t value   Pr(>|t|)    
roa                  0.001005   0.003873  0.259603 7.9707e-01    
ebitda_at           -0.177129   0.055557 -3.188234 3.5080e-03 ** 
log(at_thousand)     0.044382   0.009059  4.899519 3.6503e-05 ***
treated:fyear::2002  0.030792   0.007255  4.244079 2.1770e-04 ***
treated:fyear::2003  0.014818   0.007322  2.023664 5.2643e-02 .  
treated:fyear::2005  0.002454   0.006178  0.397258 6.9419e-01    
treated:fyear::2006  0.001226   0.007150  0.171534 8.6504e-01    
treated:fyear::2007 -0.003901   0.010198 -0.382567 7.0493e-01    
Show the code
cat("Number of Observations in Each Group over time: \n")
Number of Observations in Each Group over time: 
Show the code
data_did %>%
  filter(book_leverage >= 0 & book_leverage <= 1) %>%
  # filter(gvkey %in% data_did_balanced_id) %>% 
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, indexyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, at, ebitda, large, roa) %>%
  filter(fyear >= period_start & fyear <= period_end) %>%
  filter(!is.na(intensity_2000) & !is.na(at)) %>%
  mutate(
  gvkey = as.factor(gvkey),
  fyear = as.factor(fyear),
  treated = ifelse(intensity_2000 > 0, "Treated", "Untreated"),
  # treated = ifelse(intensity_2000 > 0, 1, 0),
  ebitda_at = ebitda / at,
  at_thousand = at * 10^-3,
  large = factor(ifelse(large, yes = "Large", no = "Small"), levels = c("Large", "Small") ),
  # large = ifelse(large, yes = 1, no = 0),
  treated_large = paste(treated, large, sep = "_")
  ) %>% 
  group_by(treated_large, fyear) %>% 
  summarise(n = n()) %>% 
  ungroup() %>% 
  # mutate(
  #   Treated = str_extract(string = treated_large, pattern = "^[^_]+"), 
  #   Size = str_extract(string = treated_large, pattern = "[^_]+$")
  #   ) %>% 
  pivot_wider(names_from = treated_large, values_from = n) %>% 
  gt(caption = "Number of Observations in each group between 2002 and 2007") %>% 
  tab_style(
    style = cell_text(size = "x-small"),  # Reduce font size
    locations = cells_column_labels(columns = everything()) # reduce the size of tab headers 
  ) %>% 
  tab_style(
    style = cell_text(size = "x-small"),  # Reduce font size
    locations = cells_body()
  ) 
`summarise()` has grouped output by 'treated_large'. You can override using the
`.groups` argument.
Number of Observations in each group between 2002 and 2007
fyear Treated_Large Treated_Small Untreated_Large Untreated_Small
2002 1863 948 555 2050
2003 1761 859 495 1826
2004 1666 791 449 1693
2005 1555 725 422 1549
2006 1452 671 371 1403
2007 1333 617 340 1270
Show the code
## Interacting with Large/Small: 
data_did %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>%   
  # filter(gvkey %in% data_did_balanced_id) %>% 
  # filter(intensity_2000 > 0) %>%
  select(gvkey, fyear, intensity_2000, post_2005, book_leverage, debt_ebitda, sic, ff_30ind_name, at, ebitda, large) %>% 
  filter(fyear >= period_start & fyear <= period_end) %>% 
  mutate( 
      gvkey = as.factor(gvkey), 
      fyear = as.factor(fyear), 
      treated = as.numeric(intensity_2000 > 0), 
      large = ifelse(large == 1, yes = "Large", no = "Small"), 
      ebitda_at = ebitda / at, 
      at_thousand = at * 10^-3
  ) %>% 
  fixest::feols(fml = book_leverage ~ treated + post_2005 + large + post_2005*large + treated*large + treated:post_2005:i(large) | gvkey + fyear + ff_30ind_name^fyear, data = ., cluster = c("gvkey", "ff_30ind_name")) %>% 
  etable() 
NOTE: 20,832 observations removed because of NA values (RHS: 20,832).
The variables 'treated', 'post_2005' and two others have been removed because of collinearity (see $collin.var).
                                                      .
Dependent Var.:                           book_leverage
                                                       
post_2005 x largeSmall                 -0.0014 (0.0075)
treated x post_2005 x large = Large  -0.0183** (0.0065)
treated x post_2005 x large = Small -0.0291*** (0.0067)
Fixed-Effects:                      -------------------
gvkey                                               Yes
fyear                                               Yes
ff_30ind_name-fyear                                 Yes
___________________________________ ___________________
S.E.: Clustered                       by: gvkey & ff_3.
Observations                                     26,664
R2                                              0.79250
Within R2                                       0.00232
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Check the trend of movement in the intensity measure:

Show the code
cat("`bnl_intensity`: \n")
`bnl_intensity`: 
Show the code
data %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  filter(fyear >= intensity_measure_year & fyear <= period_end) %>% 
  select(gvkey, fyear, all_of(intensity_measure_name)) %>% 
  pivot_wider(names_from = fyear, values_from = all_of(intensity_measure_name)) %>% 
  column_to_rownames(var = "gvkey") %>% # convert into rownames 
  round(digits = 6) %>% 
  na.omit() %>% 
  head(20) 
         2000     2001     2002     2003     2004     2005     2006     2007
1004 0.109925 0.108170 0.108367 0.090809 0.080233 0.064026 0.069679 0.084466
1021 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
1034 0.095755 0.085633 0.098100 0.109003 0.128727 0.061396 0.115526 0.096297
1050 0.131387 0.136394 0.155087 0.135856 0.128910 0.131329 0.089732 0.060413
1062 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
1072 0.106598 0.129059 0.137992 0.146348 0.160801 0.160973 0.156375 0.168714
1078 0.143917 0.110799 0.112253 0.112998 0.099345 0.103850 0.102737 0.102812
1082 0.375528 0.661385 0.818204 0.667496 0.611982 0.599924 0.709494 0.489888
1094 0.000000 0.000000 0.000000 0.000000 0.002178 0.022419 0.000018 0.015997
1096 0.828436 0.785170 0.869140 0.862246 0.879633 0.891396 0.746847 0.773825
1097 0.141147 0.146789 0.131890 0.121762 0.117395 0.123977 0.132147 0.141016
1104 0.103561 0.111139 0.141933 0.143785 0.132426 0.110165 0.083864 0.074511
1109 0.172354 0.170392 0.203393 0.202864 0.140946 0.130897 0.166074 0.111574
1111 0.011718 0.007991 0.007761 0.005095 0.004037 0.003540 0.003081 0.002584
1117 0.000000 0.005561 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
1161 0.251989 0.264631 0.254025 0.329692 0.322195 0.144987 0.111280 0.094026
1173 0.182648 0.181556 0.241647 0.225388 0.238369 0.222096 0.258697 0.128344
1209 0.098277 0.100494 0.101460 0.102376 0.095156 0.096130 0.090790 0.087199
1228 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
1234 0.189732 0.191952 0.167563 0.174638 0.158038 0.245521 0.357150 0.346692
Show the code
cat("`book_leverage`: \n")
`book_leverage`: 
Show the code
data %>% 
  filter(book_leverage >= 0 & book_leverage <= 1) %>% 
  filter(fyear >= intensity_measure_year & fyear <= period_end) %>% 
  select(gvkey, fyear, book_leverage) %>% 
  pivot_wider(names_from = fyear, values_from = book_leverage) %>% 
  column_to_rownames(var = "gvkey") %>% # convert into rownames 
  round(digits = 6) %>% 
  na.omit() %>% 
  head(20) 
         2000     2001     2002     2003     2004     2005     2006     2007
1004 0.275896 0.366410 0.374171 0.355366 0.315344 0.327808 0.307087 0.389800
1013 0.011334 0.001880 0.023160 0.314828 0.280302 0.260782 0.248231 0.227335
1021 0.436768 0.464968 0.366115 0.458637 0.268054 0.082792 0.000000 0.234036
1034 0.326074 0.443761 0.390025 0.350821 0.350195 0.256678 0.000000 0.241454
1045 0.239194 0.322950 0.435392 0.474940 0.498036 0.498220 0.459427 0.389976
1050 0.534511 0.403809 0.392527 0.376197 0.370203 0.336014 0.245173 0.048760
1062 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
1072 0.013737 0.009064 0.002012 0.000016 0.000000 0.000000 0.000000 0.000000
1075 0.349877 0.401539 0.387488 0.357503 0.330733 0.265757 0.285440 0.322986
1078 0.101799 0.312873 0.264751 0.224204 0.235704 0.227633 0.343050 0.307542
1082 0.531551 0.550577 0.489912 0.463896 0.464892 0.428487 0.456049 0.388829
1094 0.017597 0.116427 0.065755 0.026603 0.006680 0.004201 0.003001 0.002785
1096 0.544320 0.553017 0.562115 0.565844 0.569743 0.651411 0.632386 0.644374
1097 0.246810 0.224277 0.176378 0.144280 0.117324 0.102331 0.087648 0.071132
1104 0.355763 0.283349 0.290962 0.246117 0.064149 0.198163 0.292025 0.241343
1109 0.307899 0.399875 0.329045 0.244701 0.257918 0.098786 0.180593 0.208470
1111 0.204558 0.005908 0.003998 0.000000 0.000000 0.000000 0.000000 0.000000
1117 0.390891 0.403337 0.398258 0.361599 0.035546 0.000000 0.000000 0.000000
1121 0.026560 0.054949 0.056773 0.054575 0.048042 0.036701 0.010370 0.000000
1161 0.224966 0.177900 0.345518 0.295015 0.237002 0.188026 0.288811 0.456190

EndNotes

  • Use small firms with zero bnl_lease as the benchmark.

    • big firms with zero bnl_lease have similar level of leverage over time.

    • small firms with positive bnl_lease have significantly higher leverage before the treatment and significantly lower leverage afterwards.

    • big firms with positive bnl_lease have significantly higher leverage before the treatment and are indifferent from the benchmark after the treatment.

    • parallel trend assumption should hold.

  • For nice plots: ggiplot()

  • Measures for financial constraints are from Appendix A.2 > Section 2

    • Joan Farre-Mensa, Alexander Ljungqvist, Do Measures of Financial Constraints Measure Financial Constraints?, The Review of Financial Studies, Volume 29, Issue 2, February 2016, Pages 271–308, https://doi.org/10.1093/rfs/hhv052