edgarfundamentals provides a simple, ticker-based
interface for retrieving fundamental financial ratios directly from SEC
EDGAR 10-K filings. No API key or paid subscription is required. All
data comes from the SEC’s official XBRL API at
data.sec.gov, which is free, stable, and
government-maintained.
The package provides four functions:
get_cik() – translates a ticker to its SEC Central
Index Keyget_fundamentals() – retrieves ratios for a single
stockget_fundamentals_batch() – retrieves ratios for a
portfolio of stocksget_filing_history() – retrieves recent SEC filing
history for a stockBefore making any API calls, set your User-Agent string. The SEC requests that automated tools identify themselves so they can contact you if your scripts cause issues with their servers.
Replace the name and email with your own. You only need to do this once per R session.
Every EDGAR API call requires a CIK number. get_cik()
handles this translation automatically inside the other functions, but
you can call it directly if you need the CIK for other purposes.
get_fundamentals() returns a named vector of key
financial ratios derived from the most recent 10-K that had been
filed on or before to_date, so the result contains
only information that was public on that date.
The returned vector contains:
| Name | Description |
|---|---|
CIK |
SEC Central Index Key |
EPS |
Diluted Earnings Per Share (USD) |
NetIncome |
Net Income (USD) |
Revenue |
Total Revenue (USD) |
ROE |
Return on Equity (%) |
ROA |
Return on Assets (%) |
DE |
Debt-to-Equity ratio |
CurrentRatio |
Current Assets / Current Liabilities |
GrossMargin |
Gross Profit as a percentage of Revenue (%) |
OperatingMargin |
Operating Income as a percentage of Revenue (%) |
NetMargin |
Net Income as a percentage of Revenue (%) |
PE |
Price-to-Earnings ratio |
PB |
Price-to-Book ratio |
DIV |
Dividend Yield (%) |
Because ratios come from annual 10-K filings, they reflect the most
recent fiscal year whose 10-K was public on to_date – not
real-time values. Every value is taken from that one fiscal year, so a
concept the company did not report that year is NA rather
than a figure from an earlier year. PE, PB and DIV use the closing price
on or just before to_date (via Yahoo Finance), so with the
default to_date they change daily even when the underlying
10-K data does not.
get_fundamentals_batch() accepts a vector of tickers and
returns a tidy data frame with one row per stock. If retrieval fails for
any ticker, that row contains NA values and a message is
printed – the batch continues rather than stopping.
healthcare <- c("UNH", "PFE", "MRK", "ABT", "LLY", "CVS", "AMGN")
defense <- c("LMT", "RTX", "NOC", "GD", "HII", "LHX", "LDOS")
healthcare.fund <- get_fundamentals_batch(healthcare, to_date = "2024-12-31")
defense.fund <- get_fundamentals_batch(defense, to_date = "2024-12-31")
healthcare.fund
defense.fundExpect retrieval to take approximately 20–30 seconds for 14 stocks. A 0.5 second pause is inserted after each API call to respect the SEC rate limit.
Once you have the data frame, standard dplyr operations
apply directly.
library(dplyr)
# Growth screen: high EPS stocks relative to peers signal strong earnings
healthcare.fund |> arrange(desc(EPS))
# Value screen: low PE and low PB suggest the market is pricing the stock cheaply
# High dividend yield is also characteristic of value stocks
defense.fund |> filter(PE < 20 & PB < 3) |> select(symbol, PE, PB, DIV, ROE)
# GARP screen (Growth at a Reasonable Price): PE below EPS
# Stocks where the market is not overcharging for growth
healthcare.fund |> filter(EPS > 0 & PE < EPS) |> select(symbol, PE, EPS)
# Profitability screen: strong margins signal pricing power and operational efficiency
bind_rows(healthcare.fund, defense.fund) |>
filter(GrossMargin > 40 & OperatingMargin > 15) |>
arrange(desc(NetMargin)) |>
select(symbol, GrossMargin, OperatingMargin, NetMargin, ROA)
# Liquidity screen: current ratio above 1.5 and low leverage
bind_rows(healthcare.fund, defense.fund) |>
filter(CurrentRatio > 1.5 & DE < 1) |>
arrange(desc(CurrentRatio)) |>
select(symbol, CurrentRatio, DE, ROE)get_filing_history() retrieves recent EDGAR filings for
a company, which is useful for verifying data availability or for
finding the accession numbers needed to access the full text of specific
reports.
EDGAR XBRL data is only as good as what companies report. A small
number of companies use non-standard XBRL tag names for common concepts.
The package automatically tries fallback tags when the primary tag
returns no data, but in rare cases a ratio may still be NA.
When this occurs, verifying the company’s most recent 10-K directly on
edgar.sec.gov will confirm whether the data exists under a
different tag name.
Additionally, EDGAR does not provide market-based ratios directly.
PE, Price-to-Book and Dividend Yield all require a share price, which
comes from Yahoo Finance via tidyquant. The package uses
the unadjusted closing price on or just before to_date
against the latest annual filing available on that date, which is
standard practice for trailing ratios. When a stock split falls between
the 10-K and to_date, per-share figures are put on the same
share basis as the price.