Diagnostics, Validation & Export

Robust event study results require validation at every stage: data quality, model fit, and assumption checks. This page covers each diagnostic tool and what to do when checks fail, plus how to export results to CSV, Excel, and LaTeX for publication-ready reporting.

A systematic diagnostic workflow catches data errors and assumption violations before they undermine the credibility of published results. As documented by Campbell, Lo, and MacKinlay (1997), failing to check for residual non-normality or autocorrelation can inflate parametric test rejection rates by 10 to 20 percentage points above their nominal level. The four-step validation process below covers data quality, model fit, pre-trend analysis, and visual inspection.

Diagnostic Checklist

Event study diagnostics are a suite of statistical checks that validate model assumptions, data quality, and result reliability before publication. A well-conducted event study tests for normality of residuals (Shapiro-Wilk), absence of autocorrelation (Durbin-Watson statistic near 2.0), and no pre-event abnormal returns. According to Campbell, Lo, and MacKinlay (1997), failing to validate these assumptions can produce misleading significance levels and effect size estimates, particularly when residual non-normality inflates parametric test rejection rates by 10–20 percentage points.

CheckFunctionPass CriterionIf Failed
Data qualityvalidate_task()No warningsFix missing data, date gaps
Normalitymodel_diagnostics() — Shapiro-Wilkp > 0.05Use non-parametric tests (Sign, Rank)
Autocorrelationmodel_diagnostics() — Durbin-WatsonStat near 2.0Use BMP test
Serial correlationmodel_diagnostics() — Ljung-Boxp > 0.05Increase estimation window
Pre-trendspretrend_test()p > 0.05 (insignificant)Re-check event date, shorten window
Model fitmodel_diagnostics() — R²Reasonable for asset classConsider a different return model

Data Validation

Run validate_task() before the event study to catch data problems early:

Data validation
validate_task(task)

The function checks:

  1. Event date exists in stock data
  2. Sufficient observations in the estimation window (minimum: 30)
  3. Time series gaps (flags gaps > 5 trading days)
  4. No window overlap between estimation and event windows
  5. Thin trading detection (> 10% zero returns)

Fix before proceeding

Validation warnings don’t stop execution, but they signal data issues that can bias results. Address warnings before interpreting abnormal returns.

Model Diagnostics

After fitting the model, assess residual quality. For a market model with a 120-day estimation window, a well-specified model typically yields an R-squared of 0.20–0.50, while the Durbin-Watson statistic should fall between 1.8 and 2.2:

Model diagnostics
diagnostics <- model_diagnostics(task)
print(diagnostics)

Diagnostic Output

ColumnWhat It TestsInterpretation
shapiro_pNormality of residualsp < 0.05 → residuals non-normal
dw_statFirst-order autocorrelation< 1.5 or > 2.5 → autocorrelation present
ljung_box_pHigher-order serial correlationp < 0.05 → serial correlation present
acf1First-order autocorrelation coefficient|acf1| > 0.1 → notable autocorrelation
sigmaResidual standard errorLarger → noisier model
r2R-squaredHigher → better model fit

What to Do When Diagnostics Fail

Non-Normal Residuals (Shapiro-Wilk p < 0.05)

Switch to non-parametric tests
# Switch to non-parametric tests
ps <- ParameterSet$new(
  multi_event_statistics = MultiEventStatisticsSet$new(
    tests = list(SignTest$new(), RankTest$new(), GeneralizedSignTest$new())
  )
)

Autocorrelation (Durbin-Watson Far from 2)

Use BMP test for cross-sectional robustness
# Use BMP test which is robust to cross-sectional correlation
ps <- ParameterSet$new(
  multi_event_statistics = MultiEventStatisticsSet$new(
    tests = list(BMPTest$new(), RankTest$new())
  )
)

Low R-squared

Try a multi-factor model
# Try a multi-factor model
ps <- ParameterSet$new(return_model = FamaFrench3FactorModel$new())
# Or increase estimation window
request$estimation_window_length <- 200

Pre-Trend Testing

Pre-trend tests check whether abnormal returns existed before the event. Significant pre-event AR suggests information leakage, a confounding event, or a misspecified event date. Studies of insider trading events show that roughly 30–40% of M&A targets exhibit significant pre-event abnormal returns in the 5 days before announcement, highlighting the importance of this diagnostic.

Pre-trend test
pretrend <- pretrend_test(task)
print(pretrend)

Pre-Trend Output

ColumnMeaning
n_pre_periodsNumber of pre-event days tested
mean_pre_arAverage pre-event abnormal return
t_statt-statistic for joint test
p_valueSignificance (p < 0.05 → pre-trend detected)

Pre-trend detected?

If pre-event AR are significant: (1) verify the event date against multiple sources, (2) shorten the event window, (3) check for confounding events, or (4) consider Panel DiD which explicitly tests parallel trends.

Shapiro-Wilk Test
A normality test for estimation-window residuals. A p-value below 0.05 indicates non-normal residuals, suggesting that non-parametric tests (Sign, Rank) should replace or supplement parametric alternatives.
Durbin-Watson Statistic
A test for first-order autocorrelation in residuals, ranging from 0 to 4. Values near 2.0 indicate no autocorrelation; values below 1.5 or above 2.5 suggest positive or negative autocorrelation, respectively.
Pre-Trend Test
A joint significance test of abnormal returns in the pre-event window, used to detect information leakage, confounding events, or misspecified event dates before interpreting post-event results.

Event Study Plots

Available Plot Types

TypeShowsUse For
"ar"Abnormal returns per firm per dayIndividual event-time impact
"car"Cumulative AR per firmTotal firm-level impact
"aar"Average AR across firms per dayCross-sectional daily impact
"caar"Cumulative average AROverall event impact (most common)

Export Results

The package exports to CSV, Excel, and LaTeX. The format is auto-detected from the file extension.

CSV

Export to CSV
export_results(task, file = "results/ar_results.csv", which = "ar")
export_results(task, file = "results/aar_results.csv", which = "aar")

Excel

Export to Excel
export_results(task, file = "results/event_study.xlsx",
               which = c("ar", "car", "aar", "model"))

Creates a multi-sheet workbook with auto-sized columns. One sheet per result type: Abnormal Returns, Cumulative AR, AAR & CAAR, Model Statistics. Requires openxlsx.

LaTeX

Export to LaTeX
export_results(task, file = "results/tables/results.tex", which = "aar")

Publication-ready tables with booktabs formatting and numeric columns rounded to 6 decimal places. Requires knitr.

Export Options

ParameterOptionsDefault
which"ar", "car", "aar", "model"All four
format"csv", "xlsx", "latex"Auto from extension
stat_nameTest statistic name for AAR tables"CSectT"

Diagnostic Plots

The four-panel diagnostic plot gives a quick visual assessment of model quality:

Four-panel diagnostic plot
plot_diagnostics(task)

Diagnostic Plot Panels

PanelWhat to Check
Residuals vs. IndexRandom scatter around zero — no patterns or trends
Q-Q PlotPoints follow the diagonal — deviations indicate non-normality
Residual HistogramRoughly bell-shaped — heavy tails suggest outliers
ACF of ResidualsBars within blue bands — bars outside indicate autocorrelation

Tidy Output

tidy.EventStudyTask() returns results as a tibble for piping into ggplot2 or other tidyverse tools:

Tidy output
tidy_results <- tidy.EventStudyTask(task, type = "aar")
print(tidy_results)

Extract Specific Results

Extract individual result components
# Individual result components
ar  <- task$get_ar(event_id = 1)    # Abnormal returns for firm 1
car <- task$get_car(event_id = 1)   # Cumulative AR for firm 1
aar <- task$get_aar()               # Average abnormal returns (all groups)

Complete Diagnostic Workflow

Complete diagnostic workflow
library(EventStudy)

# 1. Setup
task <- EventStudyTask$new(firm_data, index_data, request)
ps <- ParameterSet$new()

# 2. Validate input data
validate_task(task)

# 3. Run event study
task <- run_event_study(task, ps)

# 4. Diagnose
model_diagnostics(task)
pretrend_test(task)
plot_diagnostics(task)

# 5. Visualize
plot_event_study(task, type = "caar")

# 6. Export
export_results(task, file = "output/results.xlsx", which = c("ar", "car", "aar"))
export_results(task, file = "output/tables/aar.tex", which = "aar")

Literature

  • Campbell, J.Y., Lo, A.W. & MacKinlay, A.C. (1997). The Econometrics of Financial Markets. Chapter 4.
  • Kolari, J.W. & Pynnönen, S. (2010). Event Studies for Financial Research.

Run this in R

The EventStudy R package lets you run these calculations programmatically with full control over parameters.

What Should I Read Next?

We use cookies for analytics to improve this site. See our Privacy Policy.