Empirical financial econometrics project measuring how U.S. equity markets react around public data-breach disclosures. Combines a cited breach-events dataset with daily firm and S&P 500 prices (Yahoo Finance via tidyquant).
Skills demonstrated: event studies · market-model abnormal returns · CAR · Callaway–Sant’Anna / did · data cleaning & confound handling · reproducible R workflow · research documentation
Results below are from the documented run dated 2026-04-20 (see docs/RESULTS.md). Classic CAR and CS ATT are different objects — they should not be compared as if they were the same estimate.
| Branch | Main result | Takeaway |
|---|---|---|
| Event study | Mean CAR(0,+10) ≈ −0.12% (n = 224 non-confounded; sd ≈ 6.5%) | Average 10-day post-disclosure abnormal return is near zero; the distribution is skewed (median slightly positive) with a heavy downside tail. |
| Event study | Mean AR sharply negative at t = 0 | Market reaction concentrates on disclosure day; pre-window AR is not systematically negative. |
| Event study | log(breach_size) OLS coef ≈ −0.0023 (p ≈ 0.23) |
Size association has the expected sign but is not statistically strong in the baseline cross-section. |
| CS / DID | Overall dynamic ATT ≈ −0.22 (95% CI [−0.42, −0.02]); pre-trend p ≈ 0.91 | Firm cumulative-return paths underperform the S&P benchmark on the same trading days; most individual event-time CIs include zero. |
How do stock prices react when a firm publicly discloses a data breach?
Two complementary pipelines answer that question with different identification strategies:
- Classic event study (
scripts/event_study.R,reports/event_study.Rmd) — fit a single-factor market model before disclosure; compute AR and CAR(0,+10) afterward. - Callaway–Sant’Anna (
scripts/cs_estimator.R) — compare firm vs S&P cumulative return paths on the same trading days; estimate dynamic ATTs withdid.
flowchart TD
A[data/raw/Data_Breach_Dataset.csv] --> B[Parse dates and clean breach rows]
B --> C[Download firm and S&P 500 daily prices]
C --> D{Pipeline}
D -->|Event study| E[Market model on t in -200..-11]
E --> F[AR and CAR on t in -5..+10]
F --> G[Figures tables OLS exports]
D -->|CS estimator| H[Firm vs S&P cumulative paths]
H --> I["att_gt then aggte dynamic"]
I --> J[Figure CSV RDS]
Sample rules differ: the event study keeps more breach types (HACK, PHYS, …) and drops confounds mainly at analysis time; CS uses a narrower type set and requires confound_dum == 0 up front. Do not expect identical event counts.
data/raw/ Breach events (Rosati & Lynn 2020)
data/processed/ Exported analysis panels (after you run scripts)
scripts/event_study.R Classic market-model event study
scripts/cs_estimator.R Callaway–Sant’Anna / did pipeline
scripts/archive/ Legacy / exploratory scripts
reports/event_study.Rmd Knit-ready HTML report
R/project_paths.R Portable path helpers
outputs/figures/ Named PNG figures
outputs/tables/ CAR summaries, CS estimates, OLS tables
outputs/models/ Saved att_gt RDS
docs/ Methodology and results write-ups
tests/ Smoke tests (data + paths)
- R (≥ 4.2 recommended)
- Network access (Yahoo Finance price pulls)
- Packages:
tidyverse,tidyquant,lubridate,ggplot2,knitr,rmarkdown,did,testthat
With renv:
install.packages("renv")
renv::restore() # uses renv.lock when presentOr install manually:
install.packages(c(
"tidyverse", "tidyquant", "lubridate", "ggplot2",
"knitr", "rmarkdown", "did", "testthat"
))Open Data_breach_stock.Rproj (or setwd() to the repo root). Paths are relative — no absolute setwd required.
# Classic event study (writes figures + CAR tables)
source("scripts/event_study.R")
# Callaway–Sant’Anna (writes CS figure, estimates CSV, RDS)
source("scripts/cs_estimator.R")
# Full knitted HTML report (slow; needs Yahoo)
Rscript reports/render_report.R
# Smoke tests (no Yahoo required)
testthat::test_dir("tests/testthat")Full price loops are slow (Sys.sleep(0.3) per event). Committed figures, CS estimates, and reports/summary.html let reviewers inspect results without a full re-run.
- Estimation window: (t \in [-200,-11]); ≥ 60 trading days required
- Market model:
firm_ret ~ mkt_ret→ (\hat\alpha, \hat\beta) - Event window: (t \in [-5,+10]); AR = actual − expected; CAR(0,+10) is the main cross-sectional outcome
- Confounds:
confound_dum == 1excluded from main plots/regressions
- Treated unit = firm cumulative simple returns; never-treated control = S&P path on the same dates
att_gt(..., est_method = "dr")withpre_mom + log_size, breach-size weights, bootstrap- S&P-as-control is a benchmark design, not a firm-matched control sample — see
docs/CS_ESTIMATOR.md
| Document | Contents |
|---|---|
docs/RESULTS.md |
Executive summary, quantified findings, interpretation |
docs/EDA.md |
Variables, cleaning, sample limitations |
docs/PLOTS.md |
Figure-by-figure reading guide |
docs/CS_ESTIMATOR.md |
Panel construction, att_gt / aggte, caveats |
Breach records: Rosati & Lynn (2020), Mendeley Data, DOI 10.17632/w33nhh3282.1 (NYSE/NASDAQ firms, ~2005–2015).
Market data: Yahoo Finance via tidyquant (downloaded at run time).
Code in this repository is released under the MIT License. The breach dataset remains subject to its original source terms; cite Rosati & Lynn (2020) if you reuse it.
