Skip to main content

Valuein

PyPI version Python 3.10+ License: Apache 2.0

valuein-sdk

Point-in-time, survivorship-free SEC EDGAR fundamentals for Python.

valuein-sdk gives you standardized financial statements from SEC filings back to 1993, queried with SQL in an in-process DuckDB. Every query sees only what was public at your as_of date: rows are filtered on accepted_at, the moment the SEC accepted the filing. Delisted, acquired and bankrupt companies stay in the data, and index membership is stored as historical spells, so a universe on a past date is the one that existed then. Every fact carries a fact_id and the accession number of the filing it came from, so any number can be traced back to its source document.

Documentation · Examples · SQL cookbook · Schema · Pricing

Install

pip install valuein-sdk

Python 3.10 or newer. Optional extras:

Extra Adds
valuein-sdk[polars] client.to_polars() and PriceQuery.to_polars()
valuein-sdk[research] NumPy, Matplotlib and a Jupyter kernel for notebooks
valuein-sdk[otel] OpenTelemetry spans (emitted only if your app configures a tracer)
valuein-sdk[all] polars, otel, NumPy and Matplotlib

Quickstart: 30 seconds, no token

With no API key the client runs on the free sample tier: S&P 500 constituents over the last five years. There is nothing to sign up for.

from valuein_sdk import ValueinClient

with ValueinClient() as client:  # no token: free sample tier
    print(client.resolve("AAPL"))  # ticker -> CIK, name, active flag

    revenue = client.run_template(
        "fundamentals_by_ticker",
        ticker="AAPL",
        form_types=["10-K"],
        metrics=["TotalRevenue", "NetIncome"],
    )
    print(revenue.head())

resolve returns one row per identifier with cik, symbol, name, is_active, valid_from, valid_to and matched_by. The template returns one row per fact: filing_date, report_date, period_end, fiscal_period, standard_concept, numeric_value, unit. A 10-K also carries prior-year comparatives, so use period_end, not report_date, to tell which year a number belongs to.

The same data from the shell:

valuein query 'SELECT symbol, name, sector FROM "references" WHERE is_active LIMIT 5'
valuein doctor   # plan, snapshot, tables and cache, with no secrets

To use your plan, set a token and run the same code:

export VALUEIN_API_KEY="your_token"   # or put it in a .env file

Three lines to a sourced income statement

from valuein_sdk import ValueinClient

client = ValueinClient()  # no token: free sample tier, as_of = now (UTC)
client.financials("AAPL").income  # fiscal years; .lineage traces every cell to its filing

financials() returns .income, .balance and .cash_flow (one row per standardized concept, one column per period end; freq="Q" for standalone quarters, "TTM" for trailing twelve months) and .lineage: one row per number with its fact_id, accession, form type, acceptance time, and when (if ever) a later filing changed it. .as_filed() shows each period as first reported, before any restatement; .explain("TotalRevenue", "2024-09-28") lists the facts behind one cell with EDGAR links.

Five lines to a factor tear sheet (Pro or Institutional)

from valuein_sdk import ValueinClient

client = ValueinClient()  # Pro or Institutional: the study reads daily prices
result = client.factor_backtest("gpoa", start="2015-01-01", end="2025-06-30", freq="QE")
report = result.tearsheet()  # IC decay, quantile curves, turnover, exclusions
report  # renders in a notebook; print(report.summary()) elsewhere

gpoa (gross profit over assets) is one of the library factors computed point in time from the filings (valuein_sdk.quant.describe_library() lists every formula). The backtest ranks the S&P 500 members of each quarter-end, trades one day later and pays 10 bps per unit traded; the tear sheet adds the information coefficient at one, two and four quarters, the return of each quantile, turnover and every exclusion.

Core ideas

Idea What it means in code
Point in time ValueinClient(as_of=...) takes a timezone-aware datetime (default: now, UTC). Point-in-time tables are filtered to accepted_at <= as_of. If that filter cannot be applied, the SDK raises ValueinIntegrityError instead of returning unfiltered rows.
Restatements A later filing that reports a period again adds new rows with their own accepted_at. Under an as_of you see what was public then. The ratio view keeps only the latest vintage per ratio and period as of the cutoff.
Survivorship-free references and entity include inactive companies. index_membership stores each membership as a spell (effective_date, removal_date), so pit_universe(date) returns the index as it was on that date.
CIK over ticker Every method that takes a ticker also takes a CIK ("0000320193", "320193" or 320193). A CIK never changes; a ticker can be retired and later reused by another company.
Traceable numbers Each fact row has a fact_id (SHA-256 of entity_id, accession_id, concept, period_end, unit) and the accession_id of its SEC filing. FactRecord.verify() recomputes the hash; filing_links() gives the EDGAR URLs.
Local compute Queries run in an in-process DuckDB over Parquet streamed from the Valuein gateway. Downloads are cached on disk. There is no database to set up.

Recipes

Every recipe runs on the free sample tier unless its heading says otherwise.

Get fundamentals for a ticker as of a date

from datetime import datetime, timezone

from valuein_sdk import ValueinClient

as_of = datetime(2024, 6, 30, tzinfo=timezone.utc)

with ValueinClient(as_of=as_of) as client:
    facts = client.read_table("fact", tickers="AAPL")

assert (facts["accepted_at"] <= as_of).all()  # nothing from after the cutoff

annual_revenue = (
    facts[(facts["standard_concept"] == "TotalRevenue") & (facts["fiscal_period"] == "FY")]
    .sort_values("accepted_at")
    .drop_duplicates("period_end", keep="last")  # latest value known on as_of
    .sort_values("period_end")
)
print(annual_revenue[["period_end", "numeric_value", "unit", "accepted_at", "fact_id"]])

read_table(table, tickers=...) fetches only that company's partition where the gateway serves one, and applies the same as_of filter. For backtests use numeric_value. With an explicit as_of (or a bundle), value_current, restated and restatement_count are recomputed from the filings accepted by the cutoff; value_as_filed is as exported. Without an explicit as_of they are the latest export's values.

Screen a universe without survivorship bias

from datetime import datetime, timezone

from valuein_sdk import ValueinClient

as_of = datetime(2023, 6, 30, tzinfo=timezone.utc)

with ValueinClient(as_of=as_of) as client:
    members = client.pit_universe("2023-06-30")  # S&P 500 on that date
    roe = client.run_query(
        """
        SELECT entity_id AS cik, value AS roe, period_end
        FROM ratio
        WHERE ratio_name = 'return_on_equity'
          AND fiscal_period = 'FY'
          AND period_end >= DATE '2022-06-30'  -- skip stale fiscal years
        QUALIFY row_number() OVER (PARTITION BY entity_id ORDER BY period_end DESC) = 1
        """
    )

screen = members.merge(roe, on="cik").nlargest(10, "roe")
print(screen[["cik", "ticker_at_date", "company_name", "roe", "period_end", "removal_date"]])
print("members later removed from the index:", members["removal_date"].notna().sum())

pit_universe returns one row per member with cik, company_name, ticker_at_date, sector, industry, effective_date and removal_date. Companies that left the index after the date are still members on it. The ratio table holds annual (fiscal_period = 'FY') and trailing-twelve-month ('TTM') rows: always filter on fiscal_period, or each company appears twice.

Backtest a factor (Pro or Institutional)

The quant layer needs daily prices (stock_price_daily), which only the Pro and Institutional plans carry.

from valuein_sdk import ValueinClient

with ValueinClient() as client:  # reads VALUEIN_API_KEY
    result = client.factor_backtest(
        "return_on_equity",  # a ratio_name, a factor_scores column, or "mom_12m"
        start="2018-01-01",
        end="2024-12-31",
        freq="QE",
    )

print(result.summary())  # net and gross results, with the execution lag and cost used
print(result.mean_ic, result.ic_ir)  # rank information coefficient and its stability
print(result.quantile_summary())  # mean return per quantile

factor_backtest builds the universe at each rebalance date from index membership, reads each signal value as of that date, prices trades with a one-day execution lag (execution_lag=1) and charges 10 bps per unit traded (cost_bps=10.0). Positions in companies that delist are truncated, not dropped, and the summary lists what the study could not use. For a custom signal, run the three steps yourself:

from valuein_sdk import ValueinClient, backtest

with ValueinClient() as client:
    universe = client.universe("SP500", start="2018-01-01", end="2024-12-31", freq="QE")
    panel = client.signal_panel(universe, ratios=["return_on_equity", "debt_to_equity"])
    panel = client.forward_returns(panel)  # appends forward-return columns

panel["score"] = panel["return_on_equity"].rank(pct=True) - panel["debt_to_equity"].rank(pct=True)
result = backtest(panel, signal="score", quantiles=5, cost_bps=10.0)
print(result.summary())

From the shell: valuein backtest return_on_equity --start 2018-01-01 --end 2024-12-31 --freq QE. More recipes, including Monte Carlo and reproducible bundles, are in the Python SDK docs.

Prices and total return

Every tier has stock_price: one close per company at each fiscal period end and each completed month end, with the listing's total_return_index (splits and dividends reinvested).

from valuein_sdk import ValueinClient

with ValueinClient() as client:
    print(client.stock_price("AAPL"))  # latest row
    monthly = client.run_query(
        """
        SELECT price_date, close, total_return_index
        FROM stock_price
        WHERE entity_id = '0000320193' AND observation = 'monthly'
        ORDER BY price_date
        """
    )

tri = monthly["total_return_index"]
print(f"12-month total return: {tri.iloc[-1] / tri.iloc[-13] - 1:.1%}")

Daily bars (stock_price_daily) are on Pro and Institutional:

from valuein_sdk import ValueinClient

with ValueinClient() as client:
    bars = (
        client.prices(["AAPL", "MSFT"])
        .between("2024-01-01", None)
        .fields("close", "total_return")
        .to_pandas()
    )
    growth = client.total_return("AAPL", "2020-01-01", "2024-12-31")  # a fraction
    # one column per ticker
    panel = client.price_panel(["AAPL", "MSFT"], "2024-01-01", "2024-12-31")

Use a total-return basis (total_return_index, or the total_return field, which is the default) for return math. Raw close is not split-adjusted, and adding div_cash on top of a total-return series counts dividends twice. stock_price_daily has one row per security per day, so a company with two share classes has two rows per day; the SDK's price methods pick one bar per company per day for you.

Run a SQL template

The package ships parameterized SQL templates for common analyses: margins, free cash flow, Piotroski and Altman inputs, DuPont, restatement history, filing delays and more.

from valuein_sdk import ValueinClient

with ValueinClient() as client:
    print(client.list_templates())
    fcf = client.run_template(
        "free_cash_flow",
        ticker="MSFT",
        form_types=["10-K"],
        start_date="2021-01-01",
        end_date="2025-12-31",
    )
print(fcf.head())

Pass parameters as keywords: run_template(name, **params). Every value is validated and quoted before the SQL is rendered: tickers such as "BRK-B" (share classes take a hyphen, as references spells them), XBRL frames such as "CY2023", "CY2024Q1" or "CY2024Q1I", fiscal_period one of Q1 to Q4, FY or TTM, and min_rank a percentile from 0.0 to 1.0. Common parameters you omit get defaults: form_types is ["10-K", "10-Q"], start_date five years ago, end_date today, and fiscal_period is "FY" for a template that reads ratio (otherwise "Q1"). Templates read the same point-in-time views as run_query. The smart-money templates (insider_buys, blockholders, top_institutional_holders, manager_portfolio) need Institutional; price_history, price_return and price_momentum_screen need Pro or Institutional. Copy-paste SQL patterns are in the SQL cookbook.

Raw SQL over the tables

from valuein_sdk import ValueinClient

with ValueinClient() as client:
    current_members = client.run_query(
        """
        SELECT r.cik, r.symbol, r.name, r.sector
        FROM "references" r
        JOIN index_membership im ON im.cik = r.cik
        WHERE im.index_name = 'SP500'
          AND im.removal_date IS NULL
          AND r.is_active AND r.is_primary_ticker
        ORDER BY r.symbol
        """
    )
print(current_members.head())
  • Tables mount on first use; a query can reference any table on your plan.
  • "references" is an SQL keyword: keep the double quotes.
  • run_query accepts one SELECT, WITH or EXPLAIN statement. Writes, file and network functions (read_parquet, glob, ...) and system catalogs are rejected.
  • Other outputs: client.to_arrow(sql), client.to_polars(sql), and client.stream(sql) for results too large to hold in memory.
  • Columns: client.get_schema("fact"), or the schema reference.

Verify a number back to the SEC filing

from valuein_sdk import FactRecord, ValueinClient

with ValueinClient() as client:
    facts = client.read_table("fact", tickers="AAPL")
    row = (
        facts[(facts["standard_concept"] == "TotalRevenue") & (facts["fiscal_period"] == "FY")]
        .sort_values(["period_end", "accepted_at"])
        .iloc[-1]
    )
    record = FactRecord.model_validate(row.to_dict())
    assert record.verify()  # fact_id matches the hash of its identity fields

    links = client.filing_links("AAPL", form_types=["10-K"])
    filing = links[links["accession_id"] == record.accession_id].iloc[0]

print(record.numeric_value, record.unit, record.period_end, record.fact_id)
print(filing["inline_viewer_url"] or filing["document_url"] or filing["sec_url"])

filing_links returns accession_id, form_type, filing_date, accepted_at and four EDGAR URLs per filing: inline_viewer_url (the Inline XBRL viewer; None for older filings), document_url, viewer_url and sec_url (the filing index, always present). compute_fact_id(entity_id, accession_id, concept, period_end, unit) computes the same hash as a plain function.

Track restatements

from valuein_sdk import ValueinClient

with ValueinClient() as client:
    events = client.restatements(ticker="AAPL")

columns = ["period_end", "standard_concept", "first_value", "current_value", "disclosure_class"]
print(events[columns])

restatements() reads restatement_events on every tier, including with no token. Each row is one reported value that a later filing changed, with both accession numbers. disclosure_class is non_reliance (an 8-K Item 4.02 notice), amended (a 10-K/A or 10-Q/A) or undisclosed (the change appeared in a routine filing). Filter with disclosure_class=, severity= and min_delta_pct=.

Value a company and compare its peers

from valuein_sdk import ValueinClient

with ValueinClient() as client:
    result = client.dcf("AAPL", stage1_growth_rate=0.08)
    table = client.peers("AAPL", n=5)

print(result.value_per_share, result.price, result.upside)
print(result.inputs_frame()[["name", "value", "fact_id", "accession_id"]])
print(table[["ticker", "is_subject", "pe_ratio", "roe"]])

dcf() is the MCP compute_dcf model (two-stage, free cash flow growing at your stage1_growth_rate, discounted at wacc, default 9%) computed in-process from the annual filings known at the client's as_of: nothing is sent to the MCP server. Every input (operating cash flow, capex, debt, cash, shares) carries the fact_id and filing it came from, defaults are flagged in result.assumptions, and projection_frame() and sensitivity_frame() give the year-by-year cash flows and a 5x5 grid. The growth rate is yours: the SDK never guesses one. peers() returns the subject first, then companies sharing its SIC code (S&P 500 members first), with the pipeline ratios as of the same date; pass peers=["MSFT", "GOOGL"] to choose them yourself. Formatted DCF and comps workbooks come from the Valuein Workspace or the MCP server's document tools.

Mirror a snapshot locally and pin it

client.sync(path) copies your plan's published table files into a directory, byte for byte, with a SHA-256 and the published ETag for each. Running it again moves only the tables that were republished: an unchanged table costs one body-free request. The mirror is also a research bundle, so it replays offline (an air-gapped host included) through the same point-in-time views, and a client pinned to its snapshot refuses to read any other.

from valuein_sdk import ValueinClient

with ValueinClient() as client:
    report = client.sync("./valuein-mirror", tables=["references", "fact"])
print(report.snapshot, report.downloaded, report.bytes_downloaded)

with ValueinClient.from_bundle("./valuein-mirror") as offline:
    revenue = offline.run_query(
        "SELECT entity_id, period_end, numeric_value FROM fact "
        "WHERE standard_concept = 'TotalRevenue' LIMIT 5"
    )

with ValueinClient(snapshot=report.snapshot) as pinned:
    assert pinned.manifest()["snapshot"] == report.snapshot

The gateway serves only its current snapshot. Once it publishes the next one, the pinned client raises ValueinSnapshotError; the mirror still reads that snapshot offline. A sync writes nothing if the snapshot changes while it runs, so a mirror never mixes two.

Plans and tiers

The SDK reads your plan from your token; your code does not change between plans. The same token unlocks the bulk data API, the MCP server and the Valuein Workspace at your plan.

Plan Key in code How to get it Coverage
Sample sample No token S&P 500 constituents, last five years
Benchmark sp500 Free registration Every S&P 500 constituent, full history
Pro pro Paid Full US universe, plus daily prices (stock_price_daily)
Institutional full Paid Pro, plus insider, 13F/13D/13G and Form ADV tables

client.plan shows the active plan. get_plans() returns each plan's request rate limits from the gateway. Prices and history windows: valuein.biz/pricing.

Tables

The table list and every column come from the gateway's manifest at runtime: use client.tables() and client.get_schema(table), and client.manifest() for the snapshot and schema version you are reading. "PIT" means the view is filtered to accepted_at <= as_of.

Table What it holds PIT Plans
references Start here. One row per security: cik, symbol, name, sector, industry, is_active, is_primary_ticker, FIGI identifiers All
entity Company master: addresses, SIC code, state of incorporation, former names All
security Ticker history with valid_from / valid_to All
filing One row per SEC filing: accession_id, form_type, filing_date, report_date, accepted_at, primary_document Yes All
filing_registrant Every registrant of a filing (accession_id, entity_id). filing lists a co-registrant filing under one CIK; join this table to filing on accession_id to list a company's filings including the combined ones. The join to filing applies the point-in-time filter Where the plan's manifest lists it
fact Standardized financial facts: standard_concept, raw XBRL concept, numeric_value, unit, period_end, fiscal_period, accepted_at, fact_id, accession_id. priority = 1 marks the tag elected for its concept in a filing, decided at export by tag precedence Yes All
ratio Computed ratios by company and period: ratio_name, category, value, fiscal_period (FY or TTM). confidence_score is computed over the full export history and is not point-in-time under a past as_of Yes All
standard_concept Dictionary of the standardized concepts in fact.standard_concept All
taxonomy_guide Reference for the raw us-gaap tags in fact.concept All
index_membership Index membership spells keyed on cik: index_name, effective_date, removal_date (exclusive) All
factor_scores Cross-sectional factor scores and percentile ranks by company and period Yes All
earnings_signals EPS trend estimate and surprise, revenue growth, price momentum Yes All
stock_price Close and total_return_index at period ends and completed month ends Yes All
stock_price_daily Daily OHLCV bars, div_cash, split_factor, total_return_index, is_primary_listing Yes Pro, Institutional
restatement_events Values a later filing changed, with both accessions and a disclosure_class All
Smart money insider_party, insider_filing, insider_transaction, insider_ownership, insider_footnote, insider_ownership_purpose, institutional_filing, institutional_holding, institutional_other_manager Yes, except insider_party Institutional
Form ADV investment_adviser, investment_adviser_private_fund (keyed on CRD, not CIK) Institutional

Join keys: fact.entity_id, filing.entity_id and security.entity_id hold the CIK; fact.accession_id = filing.accession_id; index_membership.cik = "references".cik. There is no is_sp500 column: join index_membership instead. For one quarter of a cash-flow item use COALESCE(derived_quarterly_value, numeric_value), because Q2 and Q3 10-Qs report year-to-date figures.

API at a glance

Everything below imports from valuein_sdk. Every public method is typed and documented: help(ValueinClient.read_table) shows the arguments, the returned columns and the errors, and client.capabilities() returns the whole surface as a dictionary.

ValueinClient(as_of=None, api_key=None, gateway_url=None, tables=None, config=None, snapshot=None)

Method Returns Use it to
Read data
read_table(table, *, columns=None, limit=None, tickers=None, dtype_backend="numpy") DataFrame Read a table through its point-in-time view, optionally for some companies
run_query(sql, *, dtype_backend="numpy") DataFrame Run one read-only DuckDB query; dtype_backend="pyarrow" returns Arrow-backed columns, faster and lighter on large results
run_template(name, **params) DataFrame Run a packaged SQL template
list_templates() list[str] List template names
to_arrow(sql) / to_polars(sql) / stream(sql, batch_size=10_000) / stream_arrow(sql, batch_size=100_000) Arrow / Polars / iterator / RecordBatchReader Other output formats
get(table) DataFrame Download the raw published table, without the as_of filter
Companies and universes
resolve(identifiers) DataFrame See which company each ticker or CIK matches
pit_universe(as_of_date, index="SP500") DataFrame Index members on a past date
factor_scores(ticker=None, sector=None, min_composite_rank=None, limit=100) DataFrame Factor scores and ranks
earnings_signals(ticker=None, min_surprise_pct=None, direction=None, limit=100) DataFrame EPS surprise and trend
restatements(*, ticker=None, disclosure_class=None, severity=None, min_delta_pct=None, limit=100) DataFrame Restatement events
filing_links(ticker, form_types=None, start_date=None, end_date=None, limit=20) DataFrame EDGAR URLs per filing
financials(ticker, *, freq="FY", periods=8, statements=..., concepts=None, vintage="pit") Financials Income statement, balance sheet and cash flow as known at as_of (FY, standalone Q, TTM), each cell traced to its fact_id and filing; .as_filed(), .periods(), .ratios(), .explain()
screen(as_of=None, *, universe="SP500", min_dollar_volume=None, min_price=None, max_age_days=None) Screen Point-in-time screen of the members on that date: .where("roic > 0.15"), .rank(...), .top(n), .preset(...), then .to_pandas()
Prices
stock_price(ticker, date=None) DataFrame Latest (or dated) close; every tier
prices(tickers) PriceQuery Daily bars: .between(), .fields(), .last(), .to_pandas(); Pro+
total_return(ticker, start, end, *, basis="total_return") float Total return over a window; Pro+
price_panel(tickers, start, end, *, field="total_return") DataFrame Wide price matrix; Pro+
pit_panel(tickers, dates, *, concepts=None) DataFrame Price and fundamentals known by the end (UTC) of each date; flows as trailing twelve months; Pro+
pit_valuation_ratios(ticker, as_of) DataFrame P/E, P/S, P/B and EV/Revenue on a date, on trailing-twelve-month flows; Pro+
dcf(ticker, *, stage1_growth_rate, stage1_years=None, terminal_growth_rate=None, wacc=None, fcf_base_override=None, shares_override=None) DcfResult Local forward DCF (the MCP compute_dcf model): EV, equity, per share, upside, projection and sensitivity frames, every input with its fact_id and filing
peers(ticker, *, n=5, peers=None, categories=None) DataFrame Subject row first, then SIC-matched peers (or yours) with pipeline ratios (P/E, P/B, EV/EBITDA, margins, ROE, ROIC, FCF yield, ...) as of the client's as_of
price_health() / corporate_actions(ticker) dict / DataFrame Price data coverage; splits and dividends; Pro+
Quant research (Pro+)
factor_backtest(signal, *, start, end, freq="ME", ...) BacktestResult Universe, signal, forward returns and backtest in one call; .tearsheet(), .explain(date) (with lineage=True), .robustness()
restatement_impact(signal, *, start, end, freq="QE", ...) VintageComparison The same study on point-in-time, as-filed and latest vintages, with the restatement events behind the differences
study(name) Study with client.study(...): counts every backtest as a trial; summaries then print the deflated Sharpe ratio, haircut Sharpe and PBO
universe(index_name="SP500", *, dates=None, start=None, end=None, freq="ME") DataFrame Index members at each rebalance date (dates= works on every tier)
signal_panel(universe, *, ratios=, concepts=, factors=, momentum_months=, library=, max_age_days=, vintage="pit", lineage=False) DataFrame Signal values accepted by the end (UTC) of each rebalance date; flow concepts (revenue, income, cash flow) as trailing twelve months; library= adds documented factors (ep, gpoa, mom_12_1, …, describe_library()); lineage=True traces each cell to its filings
forward_returns(panel, *, execution_lag=1, horizons=(1,)) DataFrame Return to the next rebalance (and horizons intervals out), delisting-aware
duckdb() ReadOnlySession A read-only DuckDB session over the same point-in-time views
trading_days(start, end) / rebalance_dates(start, end, freq=) DatetimeIndex / list[str] Calendars built from actual trading days
write_bundle(path, *, tables, ...) / ValueinClient.from_bundle(path) BundleManifest / client Freeze a data slice with SHA-256 hashes; replay it offline
sync(path, *, tables=None, verify=False) SyncReport Mirror the published table files; a re-run moves only republished ones
Session
plan / as_of str / datetime Active plan and cutoff
tables() / get_schema(table) list[str] / dict Tables on your plan; column types
me() / manifest() / health() dict Token, snapshot and gateway status
capabilities() / diagnostics() / usage() dict / dict / report Machine-readable surface; redacted support bundle; download budget
cache_info() / clear_cache(*, table=None) dict On-disk cache
report_issue(message, *, category="bug", ...) FeedbackReceipt Report a bug or a data problem; works with no token
close() Release DuckDB and HTTP resources (or use with)

Also exported: backtest, factor_report, describe_library, to_alphalens, block_bootstrap, bootstrap, gbm and correlated_gbm (every simulation requires a seed), AlphaEngine with built-in factors such as ROE and GROSS_MARGIN, FactRecord, compute_fact_id, ValueinConfig and the ValueinError hierarchy; valuein_sdk.quant adds fama_macbeth, factor_returns, deflated_sharpe, probability_of_backtest_overfitting, haircut_sharpe and explain_cell. Every result object (BacktestResult, FactorReport, Financials, ScreenResult, VintageComparison, Study, FamaMacBethResult, SimulationResult) has summary(), to_frame(), to_dict() (strict JSON with params and provenance), plot() (needs valuein-sdk[research]), explain() and a notebook view. valuein_sdk.aio.AsyncValueinClient is the asyncio client.

Command line

The valuein command installs with the package and uses the same token rules.

Command Does
valuein doctor Print a redacted diagnostics bundle
valuein tables List tables on your plan
valuein schema TABLE Show a table's columns and types
valuein query "SQL" [--format csv|json] Run a read-only query
valuein prices TICKER [--start] [--end] [--last N] Daily bars (Pro+)
valuein health [TICKERS...] Price data coverage (Pro+)
valuein backtest SIGNAL --start --end [--freq] [--quantiles] [--cost-bps] ... Factor backtest (Pro+)
valuein bundle PATH --tables T1 T2 ... Write an offline research bundle
valuein cache stats / valuein cache clear [--table T] Inspect or clear the cache, offline

Configuration

Environment variables

Variable Effect
VALUEIN_API_KEY Your token, read when api_key is not passed. A .env file found from the current directory upward is loaded once per process.
VALUEIN_NO_DOTENV 1, true, yes or on (any case) skips loading .env; any other value, 0 included, loads it.
VALUEIN_GATEWAY_URL Override the data gateway URL (development).
VALUEIN_MCP_URL Override the MCP server URL used by report_issue().
VALUEIN_PLANS_ENDPOINT Override the URL that get_plans() reads.
VALUEIN_DISABLE_TELEMETRY 1 or true turns off OpenTelemetry spans.
VALUEIN_DEBUG Make the CLI print full tracebacks.
XDG_CACHE_HOME Cache root (default ~/.cache); the SDK uses valuein-sdk/ under it.

api_key=None (the default) reads the environment, api_key="" forces the sample tier, and any other string is used as the token.

ValueinConfig

from valuein_sdk import ValueinClient, ValueinConfig

config = ValueinConfig(memory_limit="8GB", threads=8, safe_mode=True)
with ValueinClient(config=config) as client:
    print(client.run_query('SELECT count(*) AS n FROM "references"'))
Field Default Meaning
memory_limit "4GB" DuckDB memory ceiling; DuckDB spills to disk above it
threads 4 DuckDB threads
temp_directory None Spill and download directory; None uses a temporary directory removed on close()
max_temp_directory_size "20GB" Cap on spill-disk use
connect_timeout / read_timeout 30.0 / 120.0 HTTP timeouts in seconds
cache_enabled / cache_dir / cache_max_bytes True / None / 4 GiB On-disk Parquet cache
cache_revalidate True Check a cached file's ETag once per session; if the check cannot run, the cached copy is used
safe_mode False Block DuckDB file and network access; use it when running SQL written by a model
hot_data True Include filings published since the last weekly snapshot in filing, fact and ratio
hot_index_ttl_s / hot_max_partitions 60.0 / 200 How often to re-check for those filings; most companies folded in per table
download_streams 4 Parallel ranged requests for a table file of 32 MiB or more, all pinned to one ETag; 1 is a single stream
partition_fanout 24 Most per-company files a read_table(..., tickers=...) fetches before it reads the whole table once instead
progress None Download and mount progress: a callable receiving a ProgressEvent, or "auto" for a rich/tqdm bar in a terminal

ValueinConfig is frozen: build a new one instead of changing a field.

Errors

Every SDK error subclasses ValueinError, and every message says what was wrong and how to fix it.

Exception Raised when
ValueinAuthError The token is invalid, expired or revoked
ValueinPlanError The request needs a higher plan
ValueinNotFoundError A table, ticker or CIK is not found, or is outside your plan's universe
ValueinRateLimitError Too many requests; .retry_after holds seconds when the gateway sends it
ValueinAPIError The gateway returned a 5xx; .status_code holds it
ValueinConnectionError The gateway cannot be reached (also a ConnectionError)
ValueinTimeoutError A request timed out after retries (also a TimeoutError)
ValueinValidationError An argument, query or parameter is invalid (also a ValueError)
ValueinDataError A query failed in DuckDB, a table could not be loaded for your plan, or a bundle file failed its hash check
ValueinSnapshotError A client pinned with snapshot= finds another snapshot, or the snapshot changes during sync() (a ValueinDataError)
ValueinIntegrityError The point-in-time filter could not be applied to a table
ValueinConfigError ValueinConfig or a tables= list is invalid
ValueinDependencyError An optional package is missing, e.g. matplotlib for plot(); the message names the extra to install (also an ImportError)
FeedbackError The server rejected a report_issue() call
from valuein_sdk import ValueinClient, ValueinError

with ValueinClient() as client:
    try:
        client.run_query("DELETE FROM fact")
    except ValueinError as exc:
        print(type(exc).__name__, exc)  # ValueinValidationError and the reason

Using valuein-sdk with AI coding assistants

Paste this block into ChatGPT, Claude, Copilot or your agent's system prompt before asking for code that uses this library.

You are writing Python that uses the valuein-sdk library (PyPI: valuein-sdk).

Core API
- from valuein_sdk import ValueinClient
- Use it as a context manager:
  with ValueinClient(as_of=datetime(2024, 6, 30, tzinfo=timezone.utc)) as client: ...
- as_of must be a timezone-aware datetime. It defaults to now (UTC). Point-in-time tables
  (filing, fact, ratio, factor_scores, earnings_signals, stock_price, stock_price_daily
  and the smart-money tables) only show rows with accepted_at <= as_of.
- client.read_table(table, columns=None, limit=None, tickers=None) -> DataFrame
- client.run_query(sql) -> DataFrame. One SELECT, WITH or EXPLAIN statement. Values go
  inline as SQL literals. No read_parquet, no file or network functions.
- client.run_template(name, **params) -> DataFrame. Keyword arguments only.
  client.list_templates() lists the names.
- Also: client.resolve(identifiers), client.pit_universe("YYYY-MM-DD"),
  client.restatements(ticker=...), client.filing_links(ticker),
  client.stock_price(ticker), client.get_schema(table), client.tables(),
  client.capabilities().
- Quant layer, which needs a Pro or Institutional plan because it reads
  stock_price_daily: client.factor_backtest(signal, start=, end=, freq=),
  client.universe(), client.signal_panel(), client.forward_returns(),
  valuein_sdk.backtest().

Rules
1. Identify companies by CIK (10 digits, zero-padded, e.g. "0000320193"). Resolve a
   ticker once with client.resolve() and carry the CIK. Tickers get reused by other
   companies; CIKs do not.
2. Never invent, estimate or round a financial number. Only report values the library
   returned. If a query returns no rows, say so.
3. When you report a number from the fact table, cite its fact_id and accession_id. Use
   client.filing_links() for the SEC URL.
4. For backtests, set as_of and use fact.numeric_value. With an explicit as_of,
   value_current, restated and restatement_count are recomputed at the cutoff;
   without one they are the latest export's values.
5. In SQL, write "references" with double quotes (it is a keyword). Index membership is
   a JOIN on index_membership.cik; there is no is_sp500 column.
6. ratio has FY and TTM rows: always filter fiscal_period. A 10-K carries prior-year
   comparatives: group by period_end, not report_date. For one quarter of a cash-flow
   item use COALESCE(derived_quarterly_value, numeric_value).
7. For return math use total_return_index (or the SDK's total_return basis), never raw
   close, and never add div_cash on top of it.
8. client.get(table) skips the as_of filter. Use read_table or run_query instead.
9. To run SQL you generated, create the client with
   config=ValueinConfig(safe_mode=True).
10. SDK errors are ValueinError subclasses whose message states the fix. Read it before
    retrying.

The SDK is data plus local compute: every query, ratio and backtest runs in your process. Documents (DCF and comps workbooks, research briefs) come from the Valuein Workspace or the MCP server at https://mcp.valuein.biz/mcp, which agents that call tools instead of writing Python can use with the same token.

Examples and notebooks

Runnable examples live in the public valuein/valuein repository:

Notebook Open
01 · Quickstart: your first query Open in Colab
02 · Fundamentals as of a date Open in Colab
03 · Survivorship-free screening Open in Colab
04 · Point-in-time factor backtest Open in Colab
05 · Prices and total return Open in Colab
06 · Restatements and how they were disclosed Open in Colab
07 · Smart money: insiders, 13F holders, advisers Open in Colab
08 · Verify a number against its SEC filing Open in Colab
09 · Use Valuein from an AI assistant Open in Colab
10 · Discounted cash flow valuation Open in Colab
11 · Piotroski F-score screen Open in Colab
12 · Earnings quality: the accrual anomaly Open in Colab
13 · Sector comparison: DuPont ROE Open in Colab
14 · Restatement alpha Open in Colab
15 · Capital allocation Open in Colab
16 · Filing delay Open in Colab

Support

License

Apache License 2.0. See the license text.

This library and its data are for research and education. Nothing here is financial advice.

Metadata

Release files for valuein-sdk 7.2.0

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

Source distribution (sdist)

Source distribution for valuein-sdk 7.2.0
File Size Uploaded
valuein_sdk-7.2.0.tar.gz 462.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for valuein-sdk 7.2.0
File Interpreter ABI Platform
valuein_sdk-7.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.0 MB

Release files / valuein_sdk-7.2.0.tar.gz

Download URL valuein_sdk-7.2.0.tar.gz
Size 462.7 kB
Tags Source
SHA-256 checksum
How to use checksums
ca60c76f04a6f97871f22612a5144d39ec978087fbfaa841cb8232ee7471f3e3
BLAKE2b-256 checksum
How to use checksums
bb845bebd489dd8f76225617f235128063ad05bc9d36800cf86473c6412b5c55
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 16, 2026.

Transparency log

Release files / valuein_sdk-7.2.0-py3-none-any.whl

Download URL valuein_sdk-7.2.0-py3-none-any.whl
Size 550.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9f6f6b0d101b71fe8645a4d31edddfe2ff5ceb8957fe197441c1962df3825a7f
BLAKE2b-256 checksum
How to use checksums
5d9dbbd57f5609c968ae516f7e0949c003bee32e849ba2e4d1bd94662992b498
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 16, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

7.2.0 This release

2 release files

7.1.0

2 release files

7.0.0

2 release files

6.2.0

2 release files

6.1.0

2 release files

6.0.0

2 release files

5.4.1

2 release files

5.4.0

2 release files

5.3.0

2 release files

5.2.0

2 release files

5.1.0

2 release files

5.0.0

2 release files

4.1.0

2 release files

4.0.0

2 release files

3.8.0

2 release files

3.7.1

2 release files

3.6.0

2 release files

3.5.1

2 release files

3.4.0

2 release files

3.3.1

2 release files

3.3.0

2 release files

3.2.0

2 release files

3.1.0

2 release files

3.0.1

2 release files

3.0.0

2 release files

2.4.1

2 release files

2.4.0

2 release files

2.3.0

2 release files

2.2.1

2 release files

2.1.0

2 release files

2.0.3

2 release files

2.0.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.7

2 release files

0.7.6

2 release files

0.7.5

2 release files

0.7.4

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.4

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.8

2 release files

0.5.6

2 release files

0.5.5

2 release files

0.5.4

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.2.2

2 release files

0.2.0

2 release files

0.1.1

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