---
title: "Fundamental Analysis with edgarfundamentals"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Fundamental Analysis with edgarfundamentals}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment  = "#>",
  eval     = FALSE
)
```

## Overview

`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 Key
- `get_fundamentals()` -- retrieves ratios for a single stock
- `get_fundamentals_batch()` -- retrieves ratios for a portfolio of stocks
- `get_filing_history()` -- retrieves recent SEC filing history for a stock

## Setup

Before 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.

```{r user-agent}
library(edgarfundamentals)

options(edgarfundamentals.user_agent = "Jane Smith jane@example.com")
```

Replace the name and email with your own. You only need to do this once per R
session.

## Looking Up a CIK

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.

```{r get-cik}
get_cik("LLY")   # Eli Lilly
get_cik("LMT")   # Lockheed Martin
```

## Fundamentals for a Single Stock

`get_fundamentals()` returns a named vector of key financial ratios derived
from the most recent 10-K filing on or before `to_date`.

```{r single}
get_fundamentals("LLY", to_date = "2024-12-31")
```

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 recently
completed fiscal year -- not real-time values. The PE ratio is the only
computed value that uses a live market price (via Yahoo Finance), so it will
change daily even when the underlying 10-K data does not.

## Fundamentals for a Portfolio

`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.

```{r batch}
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.fund
```

Expect 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.

## Screening by Fundamental Criteria

Once you have the data frame, standard `dplyr` operations apply directly.

```{r screening}
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)
```

## Checking Filing History

`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.

```{r filing-history}
# Five most recent annual reports for Lockheed Martin
get_filing_history("LMT", form_type = "10-K", n = 5)

# Four most recent quarterly reports for Eli Lilly
get_filing_history("LLY", form_type = "10-Q", n = 4)
```

## A Note on Data Limitations

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. Price-to-Book
and Dividend Yield both require a current share price, which comes from Yahoo
Finance via `tidyquant`. This means PE, PB, and DIV all reflect today's price
against the most recent annual filing data, which is standard practice for
trailing ratios.
