Skip to content

For systematic research

A filed-date join hands your model filings EDGAR had not accepted yet.

The filed date is a day and nothing finer. EDGAR also stamps every filing with the minute it accepted it, and where those two disagree, an event study joined on the date column reads material the market could not see. The date column gives you no way to tell which rows are affected. PIT holds both stamps on every filing, which is what lets you put a number on the margin.

What you use

Three products, in the order a study needs them

01

Point-in-Time API

The as-of query surface. Every read is bounded to an instant, and the response names the timestamp field it filtered on. Identity resolves at the same instant, so a renamed company stays in the sample. A day we never read refuses instead of answering zero.

02

Flat Files

The same rows as 415 parquet partitions, one file per source per day, 178 MiB in total, each carrying its own SHA-256. A manifest pins the corpus version you hold. Load them into DuckDB or pandas and run the study offline.

03

Benchmarks

Our own ablation over the same window, published with its method and its inputs: three clocks, one strategy, real prices. It is the template for measuring what a clock choice is worth in your own study.

The measured margin

How much future a filed-date join lets in

We hold both clocks on every filing across the contiguous window, 2022-11-01 to 2023-03-31, and the figures below are what came out when we measured the distance between them.

10.3% land the wrong side of the boundary
343d largest gap between acceptance and the first public listing

That is 14,975 filings, all of them accepted by EDGAR later than the day boundary a filed-date join uses, with a median gap of 1.1 hours. A join on the filed date hands each one to your model at that boundary, whether or not EDGAR had taken the filing yet. Every hour inside that gap is time your backtest can see and the market could not.

Five ways a filings backtest leaks

What it costs a strategy

The same rule on three clocks, over real prices

The rule is one 8-K signal on twelve Dow names, 88 events across the window, priced on daily bars. Joined on the partition date at midnight it returns +5.13%, which is a number nobody could have traded: 47 of the 64 entries with an acceptance receipt were placed at opening auctions that happened before EDGAR had accepted the filing. Waiting for the nightly index instead returns −2.02%. Entering on the acceptance receipt, which is the first moment the filing was real, returns +0.18%. The gap between the first number and the last two is the size of the leak.

The arms, the basket rule, the price source and the pull date are all published with the run. Read the method, or take the same three clocks through the contamination-control comparison.

What the API does about it

How the API keeps the future out

Every cut names its clock

A query filters on published_at, available_at or committed_at, and the response repeats which one it used. Rows carry acceptance_at alongside, so you can run the same study on both clocks and report the difference.

Identity resolves at the instant you ask about

Ticker to CIK is answered at the query instant: CIK 1326801 comes back as FB in October 2021 and as META in June 2022. A join against today’s ticker table uses assignments nobody had at the instant being studied. That is where a filings backtest usually starts leaking, before anyone looks at the clocks.

An uncertified day refuses

Every answer lists the days it read with a status of complete, partial or missing. A day we certified with nothing matching answers count: 0. A day we never read makes the whole call come back 409, with that day named in coverage.missing. A hole in the corpus therefore cannot enter your study as a zero.

a day the corpus has not certified 409 coverage_missing

$ curl -s "$PIT/v1/sample/news?example=svb&as_of=2021-07-15T23:59:59Z"
{
  "status": "coverage_missing",
  "count": null,
  "coverage": { "missing": ["sec.edgar/2021-07-15", "us.federal_register.pi/2021-07-15"] },
  "error": {
    "code": "coverage_missing",
    "message": "This cut touches at least one day we have not certified, so count is null: the answer is unknown, not empty. coverage.missing names the days."
  }
}

PIT=https://api.pit.aqx.llc. That call takes no key; the response above is trimmed to the fields being discussed.

Getting a cut

Researcher costs $29 a month and covers one person

It reads every row we hold, 2008-09-01 forward across seven sources, at 60 requests a minute with three keys and a coverage certificate — our record of what we read on a day — on every answer. Power at $79 adds the parquet partitions, which is the plan to take if you would rather read the corpus as files than page it. If your study will end up as an eval, the harness that runs an agent over the same window is Apache-2.0 and costs nothing.

Coverage is published day by day on the coverage page, including the days we have not read, so you can check the window your study needs before you subscribe.