ID: S020
Slug: buyback-announcement-drift-v1
Type: EVT
Date added: 2026-06-08
Status: open (data scraper required) — promoted from
lab/candidates/buyback-announcement-drift-v1.md
Wall: 3 — Messy data that won't license cleanly
Data infra dependency (partially resolved 2026-06-13): the PIT shares-outstanding layer now exists (
src/data/edgar_facts.py, SEC companyfacts, ~94% coverage) — built for S017, reused here. That unblocks the realized-buyback angle below (observing share-count declines) immediately. The original announcement leg still needs the SEC EDGAR 8-K scraper + item-type classifier (shared with S019); that part of Stage 1 waits on the scraper.
One-line setup
We expect that small-cap names that file an 8-K announcing a share repurchase programme materially large relative to market cap, entered shortly after the filing posts and held over a multi-week drift window predict positive mean excess return over an equal-weighted small-cap baseline in the US small-cap universe with a liquidity floor over a 20-60 trading-day forward window, because a buyback is management spending real money on the view that the shares are cheap, and it mechanically shrinks the share count, lifting per- share value; the market tends to react gradually rather than instantly, leaving a documented post-announcement drift that's larger and slower in smaller names with less analyst coverage.
Rationale (the "because", expanded)
A buyback is management spending real money on the view that the shares are cheap, and it mechanically shrinks the share count, lifting per-share value. The market tends to react gradually rather than instantly, leaving a documented post-announcement drift — and the drift is larger and slower in smaller names that get less analyst coverage.
Shares the EDGAR-scraping plumbing with S019 (insider-cluster-buys). Orthogonal to the vol/trend book; calendar-mechanical but event- triggered rather than date-triggered.
Data required
- SEC EDGAR 8-K filings with item-type classification (the scraper shared with S019) — keying on filing type + a few repurchase-announcement phrases, not free-text NLP
- Tiingo EOD prices + market-cap data
- Universe filter: small-cap band + liquidity floor
- Filter on programme size relative to market cap (token buybacks excluded — calibrate threshold)
Quick-kill gate (Stage 1)
Will be considered to have passed Stage 1 if:
- Mean per-event 30-day excess return over equal-weighted small-cap baseline ≥ +1.0pp [suggested, to freeze]
- Hit rate ≥ 53% [suggested, to freeze]
- Sample size ≥ 400 announcement events [suggested, to freeze]
- Effect present in both sample halves [suggested, to freeze]
- Welch p<0.05 AND mean>0 [suggested, to freeze]
- Size-conditional check: events where the announced programme is ≥ 5% of market cap [suggested, to freeze] must outperform smaller-programme events — confirms the "real signal vs token" distinction matters
Realized-buyback confirmation (pre-registered angle, added 2026-06-13)
Announcing a buyback ≠ executing one — the spec already flags this as
the main risk. Now that PIT shares outstanding is available
(edgar_facts), we can condition the drift on execution evidence:
does the next 10-Q/10-K actually show shares outstanding declining?
- Signal: for each announcement, check whether trailing shares outstanding fell by ≥ [X]% over the following 1–2 filings.
- Hypothesis: the executed subset drifts more cleanly than the announcement-only set; token/never-completed programmes are the noise the announcement signal carries.
- Status: pre-registered exploratory (non-gating) for v1 — it
cannot pass or fail S020 by itself. If it is the real driver, it
becomes the core of
buyback-execution-drift-v2under a new S-number, NOT bolted onto v1 mid-test (per lab discipline). - Runnable now on the shares side (no 8-K scraper needed): a pure realized-share-count-decline drift can even be tested independently of the announcement leg as an early read.
What I expect to find
Effect probably present but smaller and noisier than the insider- buys signal — announcing a buyback is not the same as executing one, and many programmes are never completed. Expected mean excess return 0.5-1.5pp, hit rate 51-55%. Probability of clearing the gate is moderate (~45%). Most likely failure mode is the friction-sensitivity gap: in the smallest small-caps where the effect is strongest, the round-trip spread can eat 100-200 bps and leave only a marginal edge.
Notes
- Lower priority than S019: noisier signal, same EDGAR cost. Run after S019 to amortise the scraper investment.
- Announcing ≠ executing. Some programmes get cancelled or under- executed. The size-conditional gate exists to favour announcements with skin in the game (large-relative-to-cap programmes).
- Look-ahead trap: 8-K filing timestamp is the entry trigger. The announcement date in press releases occasionally precedes the SEC filing by hours; use the filing timestamp to be safe.
Disclosure boundary
This setup file is internal. Downstream result.md / kill.md
writeups must follow lab/DISCLOSURE_POLICY.md §2. Pre-publish:
python -m pytest tests/test_disclosure.py.