Skip to main content

tradevodata

Open in Colab

Point-in-time US equity fundamentals from SEC EDGAR. Every value carries the date it actually became public, so a backtest can only see what was knowable at the time.

See the bug before installing anything

The no-signup Colab experiment joins the same fundamentals two ways. 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. Run the 3-minute proof in Colab.

pip install tradevodata

The public proof pack needs no key

import tradevodata as tv

rows = tv.sample()        # 5 companies, latest 3 fiscal years, 225 rows, CC0

Returns a pandas DataFrame if pandas is installed, otherwise a plain list of dicts — so the line above works on a bare install. Force either shape with to_pandas=True/False.

Same columns and the same semantics as the paid dataset, so you can write and verify your join logic before paying for anything.

as_of is required, on purpose

import tradevodata as tv

client = tv.Client(api_key="tvd_...")     # or set TRADEVODATA_API_KEY

client.fundamentals("AAPL", as_of="2024-06-30")  # annual (default)
client.fundamentals("AAPL", as_of="2024-06-30", period="quarterly")

There is no way to ask this library "what is Apple's revenue?" — only "what was Apple's revenue knowable on this date?". On 2024-06-30 the answer is FY2023, because the FY2024 10-K had not been filed yet. That distinction is the entire product, and a default value for as_of is how lookahead bias gets written by accident.

Whole-universe cross-section

One call per rebalance date, instead of looping tickers:

snap = client.snapshot(
    as_of="2024-06-30", concept="Revenue", period="quarterly", to_pandas=True
)

Bulk

client.download("tradevodata_annual.csv.gz")
client.download("tradevodata_quarterly.csv.gz", period="quarterly")

Doing the point-in-time join yourself

If you're working from sample() or a bulk download, the as-of join is yours to do — as_of_filter does it correctly:

rows = tv.sample()
knowable = tv.as_of_filter(rows, as_of="2020-03-31")

Keeps only rows whose first_filed <= as_of, then the newest fiscal period per ticker/concept. That is the same logic the API applies server-side.

What each row tells you

column meaning
first_filed the date the value became public — the point-in-time stamp
original_value what was first reported. Use this for backtests
latest_value the current revision. May post-date your as_of — not PIT-safe
restated a later filing revised this by more than 0.5%
lag_days days from period end to first publication
qa_status clean, or FLAG: + reasons. We flag; we never silently drop
fiscal_period FY for annual rows; Q1–Q4 for quarterly rows
period_start start of a quarterly duration; null for instant concepts
ytd_value source year-to-date value when a discrete quarter is derived
derivation reported, ytd_diff, or fy_minus_9m

The client raises a UserWarning when rows come back flagged or when your as_of runs past our data cutoff. Silence it with Client(warn_on_flags=False) if you're handling qa_status yourself.

Honest limits

  • Annual data comes from 10-K/10-K/A filings. Quarterly data is requested explicitly with period="quarterly" and includes accepted 10-Q/10-Q/A facts plus supported Q4 derivations.
  • Quarterly depth varies by filer and tag availability; do not assume every company has 48 quarters.
  • US only, and no delisted companies — so mind survivorship bias if you build universes from this alone. We fix lookahead bias; that is a different problem.
  • 16 annual concepts and 7 quarterly concepts, with up to 12 fiscal years of history where SEC XBRL coverage supports it.
  • Filing lag averages 66 days across the universe (median 60, p90 90; reliable rows are QA-capped at 120). The 5-company proof pack averages 35.2 days and is not a proxy for the universe.

If you need delisted coverage or a survivorship-bias-free historical universe, this dataset does not provide it; use a provider that explicitly includes inactive securities.

Zero dependencies

Standard library only. pandas is opt-in:

pip install "tradevodata[pandas]"

See the bug for yourself

The Colab notebook runs the experiment on the public proof pack—no key, no signup, no install. It joins fundamentals both ways at every month-end and counts the disagreements. On the 5-company proof pack: 14 of 85 ticker-months (16%) use a revenue number that was not yet public.

Audit another provider

If you already have a fundamentals CSV, the local audit checks whether it exposes a real availability date and whether revised values appear where the proof pack recorded a different first-reported value:

python examples/audit_provider_csv.py provider.csv \
  --ticker-col ticker --concept-col concept --period-end-col period_end \
  --value-col value --available-col filed

Nothing is uploaded. The script runs locally and explains every check it can and cannot verify.

Build a point-in-time factor snapshot

pip install "tradevodata[pandas]"
python examples/point_in_time_factor.py --as-of 2024-06-30

This produces margins and return-on-capital measures using only annual values that had been filed by the requested date.

MIT licensed. Data sourced from SEC EDGAR (public domain). This is a dataset, not investment advice.

Metadata

Release files for tradevodata 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tradevodata 0.2.1
File Size Uploaded
tradevodata-0.2.1.tar.gz 21.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tradevodata 0.2.1
File Interpreter ABI Platform
tradevodata-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 32.6 kB

Release files / tradevodata-0.2.1.tar.gz

Download URL tradevodata-0.2.1.tar.gz
Size 21.6 kB
Tags Source
SHA-256 checksum
How to use checksums
299134a87ba7c29c792517a2928b0b143e6bbc1ab5a7e1be242703bfe8c24b7b
BLAKE2b-256 checksum
How to use checksums
15cf085a6f2c069bd141b42bc451cf1fd6d73fe5f4d2ce72af17e67f63248d69
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release files / tradevodata-0.2.1-py3-none-any.whl

Download URL tradevodata-0.2.1-py3-none-any.whl
Size 11.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
41fed14f717cb620dc4390fc5448505b051d1427bc25506f9f10b5f85168407f
BLAKE2b-256 checksum
How to use checksums
3b820e44dd3408aad86ce6300297d6c0dfaa64c295d8126c416d3c7b7fa35bd3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page