Tradevodata/point-in-time-us-equity-fundamentals-sample
Tradevo Data — honest point-in-time US equity fundamentals Fundamentals with filed-date stamps, so a backtest only sees what was public — and restatements are flagged, not silently applied. A deliberately small public proof pack of point-in-time US equity fundamentals, built from SEC EDGAR. Every value is stamped with the date it first became public (first_filed), so a join that filters by first_filed <= as_of only sees what was knowable on that date — and later revisions are… See the full description on the dataset page: https://huggingface.co/datasets/Tradevodata/point-in-time-us-equity-fundamentals-sample.
Tradevo Data — honest point-in-time US equity fundamentals
Fundamentals with filed-date stamps, so a backtest only sees what was public — and restatements are flagged, not silently applied.
A deliberately small public proof pack of point-in-time US equity fundamentals, built from SEC EDGAR. Every value is stamped with the date it first became public (first_filed), so a join that filters by first_filed <= as_of only sees what was knowable on that date — and later revisions are kept alongside the original number with a restated flag rather than silently overwriting it.
Using this? I'd genuinely like to know what for. I'm one person, and GitHub tells me this repo gets cloned but not by whom — so unless you say something, I'm building in the dark. What are you testing it against? What's missing that would make it useful? One line to christianpichichero@gmail.com, or open an issue, and I'll read it and reply. No signup, no list, nothing gated. The proof pack is CC0 whether you answer or not.
Run the proof in 3 minutes

The notebook joins the same fundamentals two ways at every month-end. On this compact proof pack, the ordinary period-end join uses a value that was not public yet in 14 of 85 ticker-months (16%). The point-in-time join removes those future values. No key, signup, or local setup required.
Or check your own data
That notebook shows the problem on our numbers. This measures it on yours:
python3 check_your_data.py your_fundamentals.csvPoint it at whatever you already backtest on — any CSV with a ticker, a period or fiscal year, and one value column. It finds the columns itself, needs no dependencies, and sends nothing anywhere. It separates the two failures because they have different fixes:
- Timing — how many days early a period-end join hands you each number. Fixed by joining on the filing date.
- Vintage — rows where your value is what the company reports now, not what it filed at the time. This one survives correct filing-date handling, because the date is right and the number underneath it was rewritten later.
Run against a typical current-values source, it reports things like:
2. VINTAGE — values that are today's number, not the one filed at the time
26 of 475 rows (5.5%) match the CURRENT value but not the as-filed one.
HON FY2024 revenue: as filed 38,498,000,000 · latest 34,717,000,000
NFLX FY2024 diluted EPS: as filed 19.83 · split-adjusted latest 1.98
NVDA FY2024 diluted shares: as filed 2,494,000,000 · latest 24,940,000,000It only compares against the 5 companies in this proof pack, and it says so — rows outside that coverage are counted and reported, never quietly dropped. A clean result is evidence about these 5 names, not proof about your universe.
Use it in Python
pip install tradevodataimport tradevodata as tv
rows = tv.sample() # this sample — no key, no signup
knowable = tv.as_of_filter(rows, "2020-03-31") # correct point-in-time joinas_of is a required argument everywhere in that package, so every join you write filters by first_filed <= as_of — there is no way to ask it for today's numbers by accident. The Colab notebook above runs the experiment on this data with zero setup: it joins both ways at every month-end and finds 14 of 85 ticker-months (16%) where the naive join uses a number that was not yet public.
The problem this fixes
A backtest that joins fundamentals on the period-end date is using numbers that weren't public yet (the 10-K files weeks later) — classic lookahead bias. In this sample's reliable-filing-date rows (224 of 225), fundamentals became public an average of 35.2 days after the period ended (max 48). That hidden future-peek inflates every fundamental backtest.
Point-in-time products exist at the institutional vendors — S&P Global's Compustat and FactSet among them — but their pricing is quote-based and aimed at funds with a data budget; check their sites for current terms. This is the small-budget tier for point-in-time US fundamentals: a tiny annual CC0 proof pack here, a 30-day card-required evaluation, and a $29/mo annual-and-quarterly API for the full universe (details below).
The public proof pack
Figures below were measured on the CSV in this repo (reduced 2026-09-24):
- 5 recognizable US companies · latest 3 fiscal years each · 16 concepts (Revenue, Net Income, Assets, Equity, Operating Cash Flow, Diluted EPS, Diluted Shares, Gross Profit, Operating Income, Pretax Income, Income Tax Expense, Capital Expenditures, Cash and Cash Equivalents, Current Assets, Current Liabilities, and Net PP&E)
- 225 point-in-time rows → `pit_fundamentals_history.csv`
- Browse it, and the API it previews, on the sample page
- Every row carries:
period_end,first_filed(the point-in-time stamp),lag_days,original_valuevslatest_value, arestatedflag, and a per-rowqa_status.
See [METHODOLOGY.md](METHODOLOGY.md) for exactly how it's built, validated, and where its limits are — because with data, showing your work is the product.
Use it — point-in-time queries
query_asof.py answers the one question that keeps a backtest honest — what could I actually know on date X?
python3 query_asof.py AAPL 2024-06-30What you could HONESTLY know about AAPL as of 2024-06-30:
Revenue $383.3B (FY2023, filed 2023-11-03)
NetIncome $97.0B (FY2023, filed 2023-11-03)
OperatingCashFlow $110.5B (FY2023, filed 2023-11-03)
... (16 concepts)Run it again as of 2025-01-15 and every line jumps to FY2024 — because that 10-K wasn't filed until Nov 1, 2024. Same company, months apart, a different known reality. That gap is the lookahead the first_filed stamp lets you filter out.
Want the full universe?
The full annual US universe is live, served as a JSON query API with server-side as_of semantics. Start with a 30-day evaluation (card required; 10 companies total; rolling 3-year history; 100 requests/day; no bulk or whole-universe snapshot), then continue for $29/mo unless canceled. Totals move with each EDGAR refresh; the current ones are on the live status page.
The same tradevodata package above talks to the API — Client(api_key=...).fundamentals("AAPL", as_of="2024-06-30") — with as_of required on every query. Source: tradevodata-py.
🌐 [tradevodata.com](https://tradevodata.com/?utm_source=github&utm_medium=repo&utm_campaign=pit-proof-2026-08) · sample page · docs
Honest limits, stated up front: the public proof pack in this repository contains annual 10-K/10-K/A rows. The hosted API also serves seven quarterly concepts from 10-Q filings; supported Q4 values are reported or derived and labelled, with no derived Q4 EPS or diluted shares and no TTM. Bulk is included in the $29 plan: GET /v1/download?period=annual|quarterly and GET /v1/snapshot?as_of=&period=annual|quarterly; Parquet is not included. Across the full annual universe, filing lag on reliable rows is mean 66 / median 60 / 90th percentile 90 days (rows are QA-capped at 120), measured 2026-09-08. If you need broader statements, TTM, non-US data, or delisted-company coverage, a research-grade vendor will fit you better. Current annual and quarterly coverage totals are published on the live status page.
Data
Source data is U.S. SEC EDGAR (public domain). Tradevo Data is a product of Tradevo Technologies Inc.
