Event study
Analyst workflows as Claude skills. 62+ tools and 8 workflows spanning earnings, comps, valuation, options flow, factor research, sizing, risk, TCA, and ops. Built in the garage, not the trading floor.
npx -y skills add rgourley/quant-garage --skill event-studyAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Measure abnormal returns around a corporate event for one or many tickers. Three input modes pick the output shape automatically: single ticker + single event renders a sell-side note (with t-stat vs that name's reaction distribution); many tickers + one event class renders a cross-section table; many events + many tickers renders aggregate statistics. Supports earnings (Benzinga or SEC EDGAR fallback), dividend changes, and computed volume spikes out of the box. Generalizes earnings-drilldown's PEAD work to any event class.
SKILL.md
9.6 KB, ~2.4k tokens by cl100k_base, as published. Nobody here has run it
event-study
You hand over an event (a date + a class) and either one ticker or a basket. The skill measures abnormal returns over the event window, compares each reaction to the name's own history, and aggregates across the cross-section when the input is wider than one event.
This is the workflow a quant or event-driven PM runs when asking "did the market actually react to this," "is the cross-section consistent," or "is this kind of event a tradeable signal." The output matches the format an analyst already reads: morning-note style for a single event, screener table for a cross-section, summary stats for an aggregate.
When to invoke
- A PM is sizing into a name post-print and wants to know "what's the T+5 base rate after a beat like this"
- A quant is testing whether dividend hikes (or cuts) lead to measurable abnormal returns across a sector
- A trader saw an unusual volume day on a peer and wants to know whether the event class historically resolves
- The user says "event study on X", "what's the average abnormal return after Y", "did the market price in Z", or "cross-section reaction across mega-cap tech earnings"
Three modes (determined by input shape)
The same code path runs all three; the shape of --tickers and
--event-date (vs --window) picks the output mode.
Mode 1: single (single ticker, single event)
Input: --ticker NVDA --event-date 2026-05-20 --event-class earnings
Output: a sell-side note with the event window returns, t-stat of this
event's abnormal return vs the name's prior reaction distribution, and
a one-line take. Matches the layout of
../earnings-drilldown but generalized to any
event class. See references/rendering.md.
Mode 2: cross-section (many tickers, one event period)
Input: --tickers AAPL,NVDA,MSFT,GOOGL,META --event-class earnings --period 2026Q2
Output: a comparison table (one row per ticker), plus a "Cross-section" footer with the average T+5 CAR, the median, the t-stat of the average against zero, and the correlation between surprise magnitude and reaction.
Mode 3: aggregate (many tickers, many events)
Input: --tickers AAPL,NVDA,MSFT,GOOGL,META --event-class earnings --window 2025-06-01..2026-06-24
Output: only the aggregate statistics. Average CAR by horizon (T+1, T+3, T+5), t-stat against zero, percentile distribution, n. No per-event detail in the rendered output (it's in the JSON for UIs). Used for "is this event class a tradeable signal at all" questions.
Event classes supported
| Class | Source | Trigger definition |
|---|---|---|
earnings | Benzinga (Tier A) or SEC EDGAR 8-K item 2.02 (Tier B) | Press release date + time |
dividend_changes | /v3/reference/dividends | First dividend whose amount differs from the prior payment by ≥1% |
large_volume_spike | computed from /v2/aggs/ticker/{T}/range/1/day/... | Days where volume > 3σ of the trailing 30d mean, with a 5-day cooldown |
Each class has its own resolution helper documented in
references/event-class-definitions.md.
Adding a new event class is a clean PR: implement the resolver, add
a row to the table above, and the skill picks it up.
Out of scope for v1: analyst upgrades/downgrades (the Benzinga analyst-ratings endpoint wasn't reliably reachable in prior sessions; queued for v2), index inclusions/exclusions, M&A announcements.
What you need
- A list of tickers (one or many)
- Either a specific event date or a window
MASSIVE_API_KEYexported
Tiers:
- Tier A (full fidelity for earnings): Stocks Starter + Benzinga Earnings. True press release dates, consensus, surprise %, allows the "surprise vs reaction" correlation column in cross-section.
- Tier B (degraded earnings): Stocks Starter only. 8-K item 2.02
acceptance date as print date; no surprise %, so the cross-section
drops the surprise-vs-reaction correlation and falls back to
reaction-sign bucketing.
dividend_changesandlarge_volume_spikerun identically on either tier.
What you get back
Two output layers from one analysis.
Layer 1: canonical JSON matching
output-schema.json. Discriminated by
output_mode: single, cross_section, or aggregate. Each mode
exposes the per-subject event_window_returns, abnormal_returns,
and t_stat_vs_history. Cross-section and aggregate add the
cross-sectional summary block, which includes distribution_shape
(KDE-derived n_modes, modality label, tail label, skew, excess
kurtosis, sparkline) when n_subjects >= 10 so bimodal or fat-tailed
reactions surface instead of hiding behind a benign mean. UIs and
downstream agents consume this.
Layer 2: rendered output in hybrid mode:
single→ sell-side notecross_section→ comparison table + cross-section footeraggregate→ summary stats block
See references/rendering.md for the
full rules.
How it works
The pipeline is the same regardless of input shape; what changes is how the rendering layer collapses the result.
- Resolve events. Per
references/event-class-definitions.md, convert the input (ticker + class + date-or-window) into a list of concrete(ticker, event_date, event_metadata)tuples. - Pull daily aggregates for each ticker and SPY across the union of event windows plus a 30-day buffer on either side.
- Compute abnormal returns per
references/abnormal-returns.md. AR = raw_return − SPY_return at each horizon (T0, T+1, T+3, T+5). CAR = sum of ARs from T+1 through the horizon. - Compute t-stats per
references/t-stat-significance.md. For a single event, compare this event's T+5 CAR to the name's prior reaction distribution. For a cross-section, t-stat is the mean CAR across events vs zero. Both require n≥8 to be reported as significant; below that, the rendered output prints the t-stat but marks it "underpowered." - Aggregate cross-sectionally per
references/cross-section-methodology.mdwhenn_subjects > 1. Average CAR, median, t-stat vs zero, and the Pearson correlation between event magnitude and reaction. - Detect regime stability per
references/regime-stability.md: for any aggregate-mode result, compare the most-recent 4 events to the full window mean and flag when the gap is >1σ. Recent regime often differs from headline number. - Generate the take off the strongest signal: significant t-stat, regime shift, or surprise-vs-reaction correlation in cross-section.
Foundations used
massive-api-patternsfor REST auth, pagination, and the fallback chain.
Endpoints used
Earnings event class:
GET /benzinga/v1/earnings?ticker={T}&limit=20&order=desc&sort=date(Tier A): press release date, time, surprise %, fiscal period.GET https://data.sec.gov/submissions/CIK{cik}.json(Tier B fallback): SEC EDGAR 8-K filings filtered to item 2.02. Free, public, no API key required. Same date-resolution logic asearnings-drilldownTier B.
Dividend change event class:
GET /v3/reference/dividends?ticker={T}&limit=20&order=desc&sort=ex_dividend_date: cash dividend history; the resolver picks the first ex-date where the cash amount differs from the prior payment by ≥1%.
Volume spike event class:
GET /v2/aggs/ticker/{T}/range/1/day/{from}/{to}: same daily aggregates used for the return computation; the resolver computes volume z-score in-memory.
All classes:
GET /v2/aggs/ticker/{T}/range/1/day/{from}/{to}: daily closes for the ticker. One call per ticker.GET /v2/aggs/ticker/SPY/range/1/day/{from}/{to}: daily closes for SPY (the benchmark). One call total.
Doesn't handle (yet)
- CAPM-style abnormal returns. The skill uses a simple SPY-naive
benchmark (AR = raw − SPY). A v2 would estimate per-name beta on
the 60-day pre-event window and compute AR = raw − (alpha + beta *
SPY). For mega-caps the difference is small (beta is close to 1);
for higher-beta names it matters. Schema reserves
model: "spy" | "capm"so the upgrade doesn't break consumers. - Multi-day pre-event run-up. Some event types (M&A leaks, guidance pre-announces) show abnormal returns before the official event date. The skill measures from T0 forward only.
- Sample-aware significance. Below n=8, t-stats are reported but marked "underpowered" rather than computing a small-sample correction. Bootstrap CIs would be cleaner; queued.
- Event clustering. When multiple events fire in the same window (e.g. earnings + dividend hike same week), the skill attributes the full return to whichever event the user asked about. A cleaner treatment would attribute by cross-section dummy; queued.
- Intraday windows. Event windows are daily closes only. No pre-market or 30-minute reaction measurement.
These are clean PR extensions and welcome contributions.
Gives 0 of the 12 instructions most learn study skills give in ~2.4k tokens
Counted across 546 of the 573 authors here whose files we hold, read 2026-08-06
- produce self-contained HTML lessonsin 24 of 546, across 8 files
- record user preferences in a notes filein 23 of 546, across 5 files
- calculate the zone of proximal development before teachingin 23 of 546, across 6 files
- maintain a teaching workspace in the current directoryin 21 of 546, across 4 files
- make lessons beautiful, short, and quickly completablein 19 of 546, across 3 files
- create reusable components for lessonsin 19 of 546, across 5 files
- create compressed reference documents for quick lookupin 19 of 546, across 3 files
- find high-quality resources before writing lessonsin 18 of 546, across 4 files
- update the mission file and records upon mission changesin 16 of 546, across 2 files
- set min_dist to 0.0 for clustering preprocessingin 16 of 546, across 6 files
- populate the mission file before teachingin 15 of 546, across 1 file
- include interactive feedback loops in lessonsin 15 of 546, across 1 file
Said here and by no other author read
- set MASSIVE_API_KEY environment variable
- pick output mode from input shape
- resolve events into concrete tuples
- pull daily aggregates for tickers and SPY
- compute abnormal returns subtracting SPY return
- compute t-stats against prior distribution
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.