10-KAnnual filings. 30 years of alpha.
The 10-K is the most information-dense document a public company produces. Audited financials, risk factors, segment breakdowns, management commentary. We standardize every XBRL tag across 12,000+ companies so your queries work across tickers and decades without schema gymnastics.
- Full income statement, balance sheet, cash flow statement
- Segment-level revenue and operating income
- Historical data from 1994 to present
- Amendment tracking — 10-K/A restated values preserved
- Point-in-time: knowledge_at timestamps for clean backtests
~85M
Annual report facts in dataset
200+
Standardized financial concepts
1994
Earliest filing year
< 24h
Post-EDGAR processing time
SQL queries that deliver alpha
Production-ready queries using ValueinClient. Copy, run, adapt.
5-Year Revenue CAGR Screener
Find S&P500 companies with 5-year revenue CAGR above 15% — the core compounders screen. Uses a single pivot over the fact table for efficiency.
from valuein_sdk import ValueinClient, ValueinError
sql = """
SELECT
r.symbol,
r.name,
r.sector,
MAX(CASE WHEN standard_concept = 'Revenues' AND fiscal_year = 2024 THEN numeric_value END) AS rev_2024,
MAX(CASE WHEN standard_concept = 'Revenues' AND fiscal_year = 2019 THEN numeric_value END) AS rev_2019,
ROUND(
POWER(
MAX(CASE WHEN standard_concept = 'Revenues' AND fiscal_year = 2024 THEN numeric_value END) /
NULLIF(MAX(CASE WHEN standard_concept = 'Revenues' AND fiscal_year = 2019 THEN numeric_value END), 0),
0.2
) - 1, 4
) AS cagr_5yr
FROM fact f
JOIN references r USING (entity_id)
WHERE f.form_type = '10-K'
AND f.standard_concept = 'Revenues'
AND r.is_sp500 = TRUE
AND r.is_active = TRUE
GROUP BY r.symbol, r.name, r.sector
HAVING cagr_5yr > 0.15
ORDER BY cagr_5yr DESC
LIMIT 25
"""
try:
with ValueinClient() as client:
df = client.query(sql)
print(df)
except ValueinError as e:
print(f"Valuein error: {e}")Operating Leverage Detector
Find companies where operating margin expanded more than 3 percentage points over 3 years — a hallmark of businesses with fixed-cost structures scaling into profit.
from valuein_sdk import ValueinClient, ValueinError
sql = """
WITH annual_metrics AS (
SELECT
r.symbol,
r.name,
f.fiscal_year,
MAX(CASE WHEN standard_concept = 'Revenues' THEN numeric_value END) AS revenue,
MAX(CASE WHEN standard_concept = 'OperatingIncomeLoss' THEN numeric_value END) AS op_income
FROM fact f
JOIN references r USING (entity_id)
WHERE f.form_type = '10-K'
AND f.fiscal_year BETWEEN 2021 AND 2024
AND r.is_sp500 = TRUE
GROUP BY r.symbol, r.name, f.fiscal_year
),
margins AS (
SELECT symbol, name, fiscal_year,
op_income / NULLIF(revenue, 0) AS op_margin
FROM annual_metrics
)
SELECT
m24.symbol, m24.name,
ROUND(m21.op_margin * 100, 1) AS margin_2021_pct,
ROUND(m24.op_margin * 100, 1) AS margin_2024_pct,
ROUND((m24.op_margin - m21.op_margin) * 100, 1) AS margin_expansion_pp
FROM margins m24
JOIN margins m21 USING (symbol, name)
WHERE m24.fiscal_year = 2024
AND m21.fiscal_year = 2021
AND (m24.op_margin - m21.op_margin) > 0.03
ORDER BY margin_expansion_pp DESC
LIMIT 20
"""
try:
with ValueinClient() as client:
df = client.query(sql)
print(df)
except ValueinError as e:
print(f"Valuein error: {e}")Free Cash Flow Quality Screen
High FCF conversion — where FCF exceeds net income — signals earnings quality. Companies with persistent FCF > net income generate real cash, not accrual accounting profits.
from valuein_sdk import ValueinClient, ValueinError
sql = """
SELECT
r.symbol, r.name, r.sector,
ROUND(
MAX(CASE WHEN standard_concept = 'NetCashProvidedByUsedInOperatingActivities'
THEN COALESCE(derived_quarterly_value, numeric_value) END) -
ABS(MAX(CASE WHEN standard_concept = 'PaymentsToAcquirePropertyPlantAndEquipment'
THEN numeric_value END)), 0
) AS fcf,
ROUND(
MAX(CASE WHEN standard_concept = 'NetIncomeLoss' THEN numeric_value END), 0
) AS net_income,
ROUND(
(MAX(CASE WHEN standard_concept = 'NetCashProvidedByUsedInOperatingActivities'
THEN COALESCE(derived_quarterly_value, numeric_value) END) -
ABS(MAX(CASE WHEN standard_concept = 'PaymentsToAcquirePropertyPlantAndEquipment'
THEN numeric_value END))) /
NULLIF(MAX(CASE WHEN standard_concept = 'NetIncomeLoss' THEN numeric_value END), 0),
2
) AS fcf_conversion_ratio
FROM fact f
JOIN references r USING (entity_id)
WHERE f.form_type = '10-K'
AND f.fiscal_year = 2024
AND r.is_sp500 = TRUE
GROUP BY r.symbol, r.name, r.sector
HAVING fcf > 0 AND fcf_conversion_ratio > 1.1
ORDER BY fcf_conversion_ratio DESC
LIMIT 20
"""
try:
with ValueinClient() as client:
df = client.query(sql)
print(df)
except ValueinError as e:
print(f"Valuein error: {e}")Return on Invested Capital (ROIC) Trend
ROIC is the most reliable predictor of long-term equity returns. This query computes ROIC across 5 annual filings and filters to companies sustaining above 15% average.
from valuein_sdk import ValueinClient, ValueinError
sql = """
WITH invested_capital AS (
SELECT
r.symbol, r.name,
f.fiscal_year,
MAX(CASE WHEN standard_concept = 'OperatingIncomeLoss' THEN numeric_value END)
* (1 - 0.21) AS nopat,
MAX(CASE WHEN standard_concept = 'Assets' THEN numeric_value END) -
MAX(CASE WHEN standard_concept = 'LiabilitiesCurrent' THEN numeric_value END) AS ic
FROM fact f
JOIN references r USING (entity_id)
WHERE f.form_type = '10-K'
AND f.fiscal_year BETWEEN 2020 AND 2024
AND r.is_sp500 = TRUE
GROUP BY r.symbol, r.name, f.fiscal_year
)
SELECT
symbol, name, fiscal_year,
ROUND(nopat / NULLIF(ic, 0) * 100, 1) AS roic_pct
FROM invested_capital
WHERE ic > 0
QUALIFY AVG(nopat / NULLIF(ic, 0)) OVER (PARTITION BY symbol) > 0.15
ORDER BY symbol, fiscal_year
"""
try:
with ValueinClient() as client:
df = client.query(sql)
print(df.pivot(index=["symbol", "name"], columns="fiscal_year", values="roic_pct"))
except ValueinError as e:
print(f"Valuein error: {e}")Query 10-K data with natural language
The Valuein MCP (Model Context Protocol) server connects Claude, ChatGPT, and other AI assistants directly to your 10-K dataset. Ask a question in plain English — the MCP server translates it to the right DuckDB query and returns structured results.
Add your Valuein API key to your Claude Desktop or Cursor config and get instant access to 30 years of annual filings without writing a single line of SQL.
# Claude Desktop config (claude_desktop_config.json)
{
"mcpServers": {
"valuein": {
"command": "uvx",
"args": ["valuein-mcp"],
"env": {
"VALUEIN_API_KEY": "vi_live_your_key"
}
}
}
}Example prompts for 10-K data:
MCP server available for Pro and Institutional subscribers. See pricing →
10-K data live in your spreadsheet
Connect Power Query to the Valuein API and your spreadsheet refreshes automatically every time a new 10-K is filed. No VBA. No copy-paste. One M-Code formula to pull 10 years of annual data for any company.
let
ApiKey = "vi_live_your_key",
Ticker = "AAPL",
BaseUrl = "https://data.valuein.biz/v1/sp500/fact",
Source = Parquet.Document(
Web.Contents(BaseUrl,
[Headers = [#"X-API-Key" = ApiKey]])
),
Filtered = Table.SelectRows(Source,
each [symbol] = Ticker
and [form_type] = "10-K"
and [standard_concept] = "Revenues"),
Sorted = Table.Sort(Filtered, {{"fiscal_year", Order.Descending}}),
Top10 = Table.FirstN(Sorted, 10)
in
Top10Start with 10-K data today
Free tier includes sample data. Pro unlocks the full S&P500 universe.