Fundamentals With Price Data

Use your price data with point-in-time fundamentals

Quantamental analysts already buy price data from Databento or elsewhere. The missing piece is point-in-time fundamentals, 13F filings, Commitments of Traders and macro vintages that line up with those bars. FinzData complements your existing price source so you keep the feed you trust and add the rest with a yfinance-compatible client.

Get a free API key See pricing Download free samples

Why fundamentals must be point-in-time

Fundamentals change with filings, restatements and revisions. Using the latest value for every historical bar introduces look-ahead bias and inflates backtests. Point-in-time means the value that was public on a given date, as of the filing date, not as revised later.

Restatements are common. Revenue, EPS and balance sheet items are often revised months after the initial 10-Q or 10-K. If you merge the current database snapshot to historical prices, you are trading on information that did not exist at the time.

For quantamental research you need filing-date accuracy and a survivorship-free universe. FinzData stores fundamentals as first published and revised vintages, so you can query as_of a specific date and reproduce what was known then.

Keeping your price source and adding point-in-time fundamentals avoids re-platforming risk while closing the research gap that price-only feeds leave open.

Joining fundamentals to bars without look-ahead

The safe join is a backward as-of merge on date. You align each price bar to the most recent fundamental value that was available on or before that bar's date. This prevents future information from leaking into the past.

With pandas this is merge_asof with direction="backward". The fundamentals table is sorted by date and ticker, the price bars are sorted by date, and the merge attaches the last known filing without forward filling across gaps.

FinzData fundamentals and valuation concepts are returned as pandas DataFrames via the Python client. You can pull c.fundamentals and c.valuation for a ticker or a universe, then merge to your Databento or other price DataFrame without changing your existing pipeline.

This pattern works for daily, weekly or monthly research and preserves the exact publication lag between filing date and market availability.

13F crowding and institutional flow signals

13F filings reveal quarterly institutional holdings with a 45-day lag. Point-in-time 13F data lets you measure crowding, ownership concentration and flow changes as they became public, not as revised later.

Quantamental models often combine price momentum with ownership changes. For example, rising institutional ownership alongside improving fundamentals can strengthen a signal, while crowded longs can flag risk.

FinzData provides point-in-time 13F holdings and aggregates. You can join 13F snapshots to your price bars with the same backward as-of logic used for fundamentals, keeping the analysis free of look-ahead bias.

Because the client mirrors yfinance, adoption is fast. You keep your price source and add institutional flow as an extra feature set.

COT positioning as a macro overlay

Commitments of Traders reports show how commercial and non-commercial traders are positioned in futures. COT is published weekly with a lag and is a useful macro overlay for equities, rates and commodities.

What matters is timing: positions are reported as of a Tuesday and released the following Friday, so a backtest may only use them from the release date. Point-in-time COT lets you test whether positioning extremes precede price moves in your universe.

FinzData stores COT as a time series with publication dates. You can pull COT for a contract, align it to your price bars, and test regime filters without leaking future positioning information.

Combined with fundamentals, COT adds a demand-side view that price-only research cannot capture.

Macro vintages for real-time decision making

Macro data is revised. CPI, payrolls and GDP are first released as flash estimates and then revised. Research that uses the latest value for historical dates overstates accuracy.

Vintage macro means the value as first published on a given release date. FinzData macro series are stored with as_of support so you can query what was known on a specific trading day.

For quantamental strategies, macro vintages let you build real-time signals that respect publication lags and revisions. You can join macro releases to price bars with backward as-of merges, just like fundamentals.

This is especially important for cross-asset models where macro surprises drive risk premia and sector rotation.

CODE: Merge point-in-time fundamentals with price bars

import finzdata as yf
import pandas as pd

# 1. Bars from your existing price source. With Databento, for example:
#    bars = db.Historical(KEY).timeseries.get_range(dataset="XNAS.ITCH", schema="ohlcv-1d",
#               symbols=["AAPL"], start="2025-11-03").to_df(pretty_px=True).reset_index()
#    bars["date"] = pd.to_datetime(bars["ts_event"]).dt.tz_localize(None).dt.normalize()
bars = yf.Ticker("AAPL").history(interval="1d", start="2025-11-03").reset_index()
bars["date"] = pd.to_datetime(bars.iloc[:, 0]).dt.tz_localize(None).dt.normalize()

# 2. Point-in-time fundamentals and valuation from FinzData
c = yf.Client()
rev = c.fundamentals(ticker="AAPL", concept="Revenues", as_of="2026-10-23")
val = c.valuation("AAPL", start="2025-11-03")
print(rev.columns.tolist(), val.columns.tolist())   # check the filing-date column name

# 3. Backward as-of join on the date each figure became public
rev["date"] = pd.to_datetime(rev["filed"]).dt.tz_localize(None).dt.normalize()   # filing date, not period end
col = "value" if "value" in rev.columns else rev.select_dtypes("number").columns[-1]
out = pd.merge_asof(bars.sort_values("date"), rev.sort_values("date")[["date", col]],
                    on="date", direction="backward")
print(out.tail())

Start free

Keep your price feed and add the rest. Start with the free tier and upgrade when you need longer history.

Get a free API key at https://api.finzdata.com/ and explore samples and pricing.

  • Free tier: last 12 months of every dataset, 1,000 API calls per day, no card
  • Macro Complete $295 for full macro vintages
  • Market bundles $195, $290, $670 for 5, 10 or up to 30 years of the whole US market: 16,000+ stocks including delisted names and 231 ETFs

Own data once and keep it. No metered fees after purchase. Shop datasets and bundles

Frequently asked questions

Can I keep Databento for prices and use FinzData for fundamentals?

Yes. FinzData is designed as a complement. Keep your existing price source and add point-in-time fundamentals, 13F, COT and macro vintages via the yfinance-compatible client.

How do I avoid look-ahead bias when joining fundamentals?

Use pd.merge_asof with direction="backward" on filing date. This attaches the most recent fundamental value that was public on or before each price bar.

Are fundamentals point-in-time and restatement aware?

Yes. FinzData stores first published values and revisions with as_of support so you can query what was known on a specific date.

What is included in the free tier?

Last 12 months of every dataset, 1,000 API calls per day, no card required. Includes prices, fundamentals, valuation, macro vintages, COT and 13F.

What do Databento free credits cover as of October 2026?

As of October 2026 Databento offers $125 per team expiring after 6 months. See https://databento.com/pricing for current rates.