# Replication kit

This folder lets you reproduce every event-study number in **"Read the Fine
Print: What ExxonMobil's Proxy Actually Says About Texas Redomiciliation"**
(Goodwin, Columbia Law School Blue Sky Blog, May 2026) on your own computer,
in Python, R, or Stata. Pick whichever you prefer; all three produce the same
answers within the published tolerances.

## What's in this folder

| File | What it is |
|------|-----------|
| `Goodwin_Read_the_Fine_Print.pdf` | The full article (PDF, 11 pp.) |
| `data.json` | Every number on the companion site, in structured JSON |
| `daily_closes.csv` | Daily adjusted closing prices for ExxonMobil + 21 energy peers + SPY, BNO (Brent oil ETF), and XLE. June 2023 – April 2026. Source: S&P Capital IQ `IQ_CLOSEPRICE_ADJ` feed |
| `donor_weights.json` | The 10-firm pre-registered synthetic-control weights |
| `expected_results.json` | Reference values for cross-platform diffing |
| `event_study.py` | Python replication script (pandas, statsmodels) |
| `event_study.R` | R replication script (base R, jsonlite) |
| `event_study.do` | Stata replication script (no add-ons required) |

## How to replicate (pick one)

### Python (most popular, runs in 5 seconds)

```bash
pip install pandas numpy statsmodels scipy
python event_study.py
```

You'll get a `results.json` file and a printed diff against
`expected_results.json`. If everything lines up, you'll see no
`*OUT OF TOLERANCE*` flags.

### R

```bash
Rscript event_study.R
```

The script only needs `jsonlite` (which comes with most R installs). It
produces the same `results.json` and prints the same diff.

### Stata

```stata
do event_study.do
```

No add-on packages required. Stata produces `results.txt` (tab-separated)
and `results.log`. Diff against `expected_results.json` by hand or eyeball
the on-screen output.

## Published tolerances

A result is considered "reproduced" if it falls within these bands:

| Statistic | Tolerance |
|-----------|----------|
| Point estimates (CARs, BHARs, Day-0 ARs) | ± 0.5 percentage points |
| P-values | ± 0.05 |
| R² values | ± 0.01 |
| Donor weights | ± 0.05 (5 percentage points) |

These bands absorb routine cross-platform differences (slightly different
OLS implementations, floating-point rounding, etc.) without papering over
substantive disagreements.

## What the five specifications compute

| Specification | What it asks |
|---------------|-------------|
| **1. Market model** | Did ExxonMobil's Day-0 return deviate from what its history-with-SPY would predict? |
| **2. Oil-augmented** | Same question, after controlling for the WTI crude shock that hit every energy stock that day |
| **3. Matched pair** | Did ExxonMobil move differently from Chevron, after both are market-adjusted? |
| **4. Raw differential** | What's the unadjusted XOM−CVX gap on Day 0? (Sanity check; no inference) |
| **5. Synthetic control** | Did ExxonMobil's actual return diverge from a weighted-blend "synthetic ExxonMobil" built from 10 energy peers? |

## Data provenance

- **Prices**: S&P Capital IQ daily adjusted closes (`IQ_CLOSEPRICE_ADJ` feed).
  Same series across all replications; no FX, no dividend adjustments
  beyond CIQ's standard back-adjustment.
- **Estimation window**: 240 trading days ending the day before the
  announcement (T−1 = 2026-03-09).
- **Event date**: 2026-03-10 (the day ExxonMobil filed its preliminary proxy
  announcing the Texas redomiciliation).
- **Donor pool**: Pre-registered ahead of the announcement; weights are
  fixed in `donor_weights.json`.

## What to do if your numbers don't match

1. **Verify your CSV**. The script reads `daily_closes.csv` from the same
   folder. Make sure the file isn't truncated and the date format is
   `YYYY-MM-DD`.
2. **Check the Python version**. The script targets Python 3.9+.
   `statsmodels >= 0.14` is recommended for stable OLS output.
3. **Time zone / date parsing**. The announcement date is 2026-03-10
   regardless of time zone. The script looks up the first trading day on
   or after that date, so a one-day off-by-one in your data won't matter.
4. **If a value is still outside tolerance**, the most likely cause is a
   different return-computation convention. This script uses simple returns
   (`P_t / P_{t-1} - 1`). Log returns (`ln(P_t / P_{t-1})`) will produce
   results within ~0.01 pp on Day 0 but can diverge slightly on multi-day
   horizons.

If you find a substantive discrepancy, please email
[sgoodwin@smu.edu](mailto:sgoodwin@smu.edu) with your platform and the
values you obtained.

## License

This replication kit is released into the public domain. Use it however
you like — but please cite the article when you do:

> Shane Goodwin, *Read the Fine Print: What ExxonMobil's Proxy Actually
> Says About Texas Redomiciliation*, Columbia Law School Blue Sky Blog
> (May 5, 2026).

---

*Maintained by Shane Goodwin (sgoodwin@smu.edu), SMU Cox School of Business
and SMU Dedman School of Law. Issues, corrections, and questions are welcome.*
