# Clock ablation methods

This benchmark runs one 8-K strategy three times across 88 filings and twelve issuers using the same daily price bars. Only the timestamp rule changes between runs. The performance difference between the runs isolates the effect of the timestamp choice.

All data on this page comes from [ablation.json](https://pit.aqx.llc/data/ablation.json), regenerated on 2026-08-27 over the corpus described on [coverage](https://pit.aqx.llc/docs/coverage).

## The measurement

Backtests that join SEC filings to prices using only the calendar date trade on filings hours before publication. The top curve shows the result of that lookahead over five months across twelve large-cap stocks. The two lower curves show returns when trades wait until filings become public.

These curves measure the effect of timing lookahead. The return levels reflect this specific basket and time window. You can recompute every value on this page from the source data file.

## The three clocks

The strategy uses one trade rule: buy at the first open at or after the timestamp assigned to the filing, hold for five trading sessions, and sell at the close of the fifth session. Each arm uses a different timestamp rule.

| Curve | Moment it treats the filing as known | First auction it can reach | Reachable |
| --- | --- | --- | --- |
| `leaky` | The filing's index date at `00:00:00Z`, the instant a join on the filed date implicitly anchors to. | The morning of the filing's own index day. | No |
| `dump` | `published_at`, the day-end bound at `23:59:59Z` on the index day. See [timestamps](https://pit.aqx.llc/docs/clocks). | The next morning. | Yes |
| `pit` | `acceptance_at`, the receipt EDGAR wrote when it took the submission, where the corpus carries one. Rows without a stamp use `published_at`. | Whichever session opens after that receipt. | Yes |

Midnight UTC occurs at 19:00 or 20:00 the previous evening in New York. The `leaky` timestamp always falls before the market open on the filing date, so `leaky` buys at that open. The day-end bound is 18:59:59 in New York after market close, so `dump` buys at the next morning's open. The acceptance receipt provides the exact time of day. A filing accepted at 07:12 ET trades that morning, while a filing accepted at 17:22 ET waits for the next session.

The two realistic curves only diverge when an acceptance timestamp changes the trading session. In this test, `pit` and `dump` enter on different sessions for 17 of the 88 filings. They enter on the same session for the other 71 filings, either because the receipt arrived after market close or because the record has no acceptance receipt yet.

## Two worked filings

3M filed `0000066740-22-000080` with an EDGAR acceptance receipt at 2022-11-14 17:22:43 ET. The `leaky` arm bought at the 2022-11-14 open at 09:30 ET, which was 7.88 hours before EDGAR received the filing. This is the largest timing error in the test. Across the 47 filings with this error, the average lead time is 6.05 hours.

Boeing filed `0000012927-22-000077` with a receipt of 2022-11-28 17:53:20 ET. EDGAR indexed the filing the next day, setting its `published_at` to 2022-11-29 at 23:59:59Z. The `pit` arm reads the receipt time and buys at the 2022-11-29 open for +7.07%. The `dump` arm waits for the daily index cutoff and buys at the 2022-11-30 open for +0.24%. Both arms trade the same filing one session apart.

## The basket

The universe is the Dow Jones Industrial Average. Its membership did not change between 2020-08-31 and 2024-02-26, so the same 30 members cover the test window from 2022-11-01 through 2023-03-31 without substitutions.

To select twelve stocks from the thirty: keep members with available price data, rank them by number of 8-Ks filed during the window, select the top twelve, and break ties by ticker. This selection uses filing counts rather than price returns. The twelve tickers are AMGN, AXP, BA, CRM, CSCO, GS, HON, JPM, MMM, PG, V, and WMT. Filing counts appear in [ablation.json](https://pit.aqx.llc/data/ablation.json).

All three arms use the same twelve stocks. Stock selection changes absolute return levels, but it does not cause the differences between arms. The reported returns apply only to this basket.

Filing records contain CIK numbers rather than tickers. Tickers are mapped using a curated CIK table valid during the test window, joined at each row's `published_at` timestamp. The SEC's current `company_tickers.json` file omits SVB Financial and Walgreens Boots Alliance, so joining against current data would drop those 2023 filers.

## The strategy

- Long only, with one position per 8-K. Exclude amendments (`8-K/A`).
- Buy at the opening auction allowed by the arm's timestamp. Hold for five sessions. Sell at the close of the fifth session.
- Equal weight across all open positions, rebalanced at market close. Sessions with no open positions earn 0% return. Idle cash earns no interest.
- The entry session return is close divided by open. Subsequent session returns are close divided by previous close.
- Two filings from the same issuer inside one hold window open separate positions, resulting in double weight while they overlap.
- No transaction costs, slippage, borrow fees, dividends, taxes, or short positions.
- All curves start indexed to 100 at the close on 2022-10-31, the session immediately before the window.

The holding period is fixed at five sessions.

## Prices

Daily open and close prices come from Yahoo Finance's daily bar endpoint, fetched once at build time on 2026-08-27 and cached outside the repository. Prices are split-adjusted. None of the twelve stocks split during the window. Dividends are omitted.

The published data file contains only derived values: curve levels indexed to 100 and per-filing percentage returns. Raw price rows are not redistributed.

The benchmark originally used Stooq end-of-day CSV files. Stooq now requires a JavaScript challenge, so the build pipeline uses Yahoo Finance instead.

## Exclusions

- **SIVB**: SVB Financial Group filed 10 8-Ks during the window and was attempted outside the index universe for that reason, but the price source provides no price bars. It is excluded from all curves.
- **WBA**: Walgreens Boots Alliance was an index member during the window, but the price source is missing data. It is excluded from all curves.
- If any arm cannot trade a filing (due to no remaining entry sessions or a hold extending past available price data), the filing is excluded from **all three** arms and recorded in `exclusions`. This ensures all arms evaluate the exact same filings.

The test scanned 287,929 corpus rows for the window and traded 88 filings. 64 filings include an EDGAR acceptance receipt. The remaining 24 fall back to the day-end bound. The `pit` and `dump` curves will diverge further as missing acceptance receipts are backfilled.

## The measured result

| Curve | Total return | Max drawdown |
| --- | --- | --- |
| `leaky` | +5.13% | −13.83% |
| `dump` | −2.02% | −17.58% |
| `pit` | +0.18% | −16.91% |

The test covers 88 filings across 12 issuers over 105 sessions from 2022-10-31 to 2023-03-31. The difference between `leaky` and `pit` is 4.95 points, labeled `lookahead_inflation` in the data file. The difference between `leaky` and `dump` is 7.15 points. The difference between `pit` and `dump` is 2.20 points.

## Reading the numbers

The `leaky` performance gap is caused by lookahead bias. The `leaky` arm trades one session before `dump` on all 88 filings. On 47 of the 64 filings with receipts, it trades hours before EDGAR received the filing. The timing lead occurs on every filing in the sample.

The 2.20-point difference between `pit` and `dump` occurs on the 17 filings where the arms entered on different sessions. Across those 17 filings, the per-filing return difference averages +0.95% with a standard deviation of 2.92%. The `pit` arm outperformed on 9 of the 17 filings. The mean is approximately 1.3 standard errors from zero. The sample measures the size of the effect without establishing its sign. The 2.20 points describe this basket over this window.

The sample covers one filing type, twelve issuers, and five months. The data file includes all per-filing details: accession number, both timestamps, entry sessions for each arm, and per-arm returns. You can recompute all summary statistics from the file.

## Reproducing it

**regenerate the chart data — go run ./cmd/ablation**

```
$ go run ./cmd/ablation
events 88  rows scanned 287929  sessions 105
acceptance stamped 64  fallback to published_at 24
leaky  total_return  +5.1287%  max_drawdown -13.8255%  trades 88
dump   total_return  -2.0185%  max_drawdown -17.5796%  trades 88
pit    total_return  +0.1779%  max_drawdown -16.9131%  trades 88
```

The generation script reads the corpus files, fetches prices into an external cache, and writes [ablation.json](https://pit.aqx.llc/data/ablation.json). Object keys are alphabetical, arrays are sorted, floating-point numbers use fixed width, and the pull date comes from the price cache. Running the script with the same inputs produces identical output bytes.
