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

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

## Overview

Fundamental analysis evaluates a company's financial health, operational profitability, balance sheet strength, and market valuation multiples. In this guide, you will build an end-to-end fundamental analysis and stock screening workflow using `yahoofinancer`:

1. **Extract Financial Statements**: Download income statements, balance sheets, and cash flow statements across multiple peer companies using `yf_get_financials()`.
2. **Compute Core Ratios**: Calculate profitability margins (operating margin, net profit margin) and cash generation metrics (free cash flow conversion).
3. **Inspect Valuation Multiples**: Retrieve quarterly valuation ratios (P/E, forward P/E, PEG, EV/EBITDA, P/B) with `Tickers$valuation_measures`.
4. **Build a Fundamental Screener**: Combine statement metrics and valuation multiples into a tidy scorecard to filter and rank candidates.
5. **Visualize Peer Comparisons**: Compare financial performance and valuation multiples using `ggplot2`.

### Required Packages

```{r load-libraries, message=FALSE, warning=FALSE}
# Install required packages if needed:
# install.packages(c("yahoofinancer", "dplyr", "tidyr", "ggplot2", "scales"))

library(yahoofinancer)
library(dplyr)
library(tidyr)
library(ggplot2)
library(scales)
```

---

## 1. Downloading Financial Statements

The functional helper `yf_get_financials()` retrieves tidy financial statements across single or multiple tickers. Statements are available at `"annual"` (default) or `"quarterly"` frequencies.

### Income Statement

```{r fetch-income}
peer_tickers <- c("AAPL", "MSFT", "GOOG")

income_df <- yf_get_financials(
  tickers        = peer_tickers,
  statement_type = "income",
  frequency      = "annual"
)

income_df |>
  select(symbol, date, period_type, total_revenue, operating_income, net_income) |>
  head(n = 6)
#> # A tibble: 6 x 6
#>   symbol date       period_type total_revenue operating_income   net_income
#>   <chr>  <date>     <chr>               <dbl>            <dbl>        <dbl>
#> 1 AAPL   2021-09-25 12M          365817000000     108949000000  94680000000
#> 2 AAPL   2022-09-24 12M          394328000000     119437000000  99803000000
#> 3 AAPL   2023-09-30 12M          383285000000     114301000000  96995000000
#> 4 MSFT   2022-06-30 12M          198270000000      83383000000  72738000000
#> 5 MSFT   2023-06-30 12M          211915000000      88523000000  72361000000
#> 6 MSFT   2024-06-30 12M          245122000000     109433000000  88136000000
```

### Cash Flow Statement

Cash flow statements provide visibility into actual cash generated from operations and free cash flow after capital expenditures:

```{r fetch-cashflow}
cashflow_df <- yf_get_financials(
  tickers        = peer_tickers,
  statement_type = "cash-flow",
  frequency      = "annual"
)

cashflow_df |>
  select(symbol, date, operating_cash_flow, capital_expenditure, free_cash_flow) |>
  head(n = 6)
#> # A tibble: 6 x 5
#>   symbol date       operating_cash_flow capital_expenditure free_cash_flow
#>   <chr>  <date>                   <dbl>               <dbl>          <dbl>
#> 1 AAPL   2021-09-25        104038000000        -11085000000    92953000000
#> 2 AAPL   2022-09-24        122151000000        -10708000000   111443000000
#> 3 AAPL   2023-09-30        110543000000        -10959000000    99584000000
#> 4 MSFT   2022-06-30         89035000000        -23886000000    65149000000
#> 5 MSFT   2023-06-30         87582000000        -28107000000    59475000000
#> 6 MSFT   2024-06-30        118548000000        -44477000000    74071000000
```

### Balance Sheet

Balance sheets expose liquidity and solvency positions including working capital, cash reserves, and debt levels:

```{r fetch-balancesheet}
balance_df <- yf_get_financials(
  tickers        = peer_tickers,
  statement_type = "balance-sheet",
  frequency      = "annual"
)

balance_df |>
  select(symbol, date, total_assets, total_stockholder_equity, working_capital, total_debt) |>
  head(n = 6)
```

---

## 2. Computing Profitability & Solvency Ratios

By joining the statement tables, we can compute standardized performance indicators:

* **Operating Margin**: $\text{Operating Income} / \text{Total Revenue}$
* **Net Margin**: $\text{Net Income} / \text{Total Revenue}$
* **Free Cash Flow Conversion**: $\text{Free Cash Flow} / \text{Operating Cash Flow}$

```{r compute-ratios}
fundamentals <- income_df |>
  left_join(cashflow_df, by = c("symbol", "date", "period_type")) |>
  left_join(balance_df, by = c("symbol", "date", "period_type")) |>
  group_by(symbol) |>
  arrange(date, .by_group = TRUE) |>
  mutate(
    operating_margin = operating_income / total_revenue,
    net_margin       = net_income / total_revenue,
    fcf_conversion   = free_cash_flow / operating_cash_flow,
    debt_to_equity   = total_debt / total_stockholder_equity
  ) |>
  ungroup()

# View the most recent period for each peer
latest_fundamentals <- fundamentals |>
  group_by(symbol) |>
  slice_tail(n = 1) |>
  ungroup() |>
  select(symbol, date, total_revenue, operating_margin, net_margin, fcf_conversion, debt_to_equity)

latest_fundamentals
```

---

## 3. Valuation Measures Across Peers

Valuation multiples allow comparing market pricing against underlying fundamentals. Using the `Tickers` class, we retrieve quarterly valuation measures across the peer group:

```{r fetch-valuation}
stocks <- Tickers$new(peer_tickers)
val_measures <- stocks$valuation_measures

val_measures |>
  group_by(symbol) |>
  slice_tail(n = 1) |>
  ungroup() |>
  select(symbol, date, market_cap, pe_ratio, forward_pe_ratio, peg_ratio, enterprise_value_ebitda_ratio)
#> # A tibble: 3 x 7
#>   symbol date       market_cap pe_ratio forward_pe_ratio peg_ratio enterprise_value_ebitda_ratio
#>   <chr>  <date>          <dbl>    <dbl>            <dbl>     <dbl>                         <dbl>
#> 1 AAPL   2024-06-30    3.45e12     33.2             28.5      2.10                          24.2
#> 2 GOOG   2024-06-30    2.25e12     25.4             21.8      1.45                          17.8
#> 3 MSFT   2024-06-30    3.30e12     36.1             30.2      2.35                          25.6
```

---

## 4. Multi-Factor Stock Screening Scorecard

We combine the latest operational margins with current valuation multiples to create a screening scorecard:

```{r create-screener}
# Extract latest valuation metrics
latest_valuation <- val_measures |>
  group_by(symbol) |>
  slice_tail(n = 1) |>
  ungroup() |>
  select(symbol, pe_ratio, forward_pe_ratio, peg_ratio, enterprise_value_ebitda_ratio)

# Combine fundamentals and valuation
screener_table <- latest_fundamentals |>
  left_join(latest_valuation, by = "symbol") |>
  mutate(
    # Screening criteria flags
    pass_margin    = operating_margin >= 0.25,
    pass_fcf       = fcf_conversion >= 0.70,
    pass_peg       = peg_ratio < 2.5,
    pass_valuation = forward_pe_ratio < 35,
    screen_passed  = pass_margin & pass_fcf & pass_peg & pass_valuation
  )

screener_table |>
  select(symbol, operating_margin, fcf_conversion, forward_pe_ratio, peg_ratio, screen_passed)
```

---

## 5. Visualizing Peer Comparisons

### Operating Margin Trends

```{r plot-margin-trends}
ggplot(fundamentals, aes(x = date, y = operating_margin, color = symbol)) +
  geom_line(linewidth = 1.1) +
  geom_point(size = 2.5) +
  scale_y_continuous(labels = percent_format(accuracy = 1)) +
  scale_x_date(date_labels = "%Y", date_breaks = "1 year") +
  labs(
    title    = "Annual Operating Margin Comparison",
    subtitle = "Operating income as a percentage of total revenue",
    x        = "Fiscal Year",
    y        = "Operating Margin",
    color    = "Company",
    caption  = "Source: Yahoo Finance via yahoofinancer"
  ) +
  theme_minimal(base_size = 12)
```

### Valuation vs. Operating Profitability

```{r plot-val-vs-margin}
ggplot(screener_table, aes(x = operating_margin, y = enterprise_value_ebitda_ratio, label = symbol)) +
  geom_point(aes(color = symbol), size = 4) +
  geom_text(vjust = -1, fontface = "bold") +
  scale_x_continuous(labels = percent_format(accuracy = 1)) +
  labs(
    title    = "EV / EBITDA Multiple vs. Operating Margin",
    subtitle = "Evaluating valuation premium relative to operating efficiency",
    x        = "Operating Margin",
    y        = "Enterprise Value / EBITDA Multiple",
    caption  = "Source: Yahoo Finance via yahoofinancer"
  ) +
  theme_minimal(base_size = 12) +
  theme(legend.position = "none")
```

---

## 6. Minimal Reproducible Example

Below is the complete, self-contained fundamental screening script:

```{r full-workflow}
library(yahoofinancer)
library(dplyr)
library(ggplot2)
library(scales)

# 1. Define peer universe
tickers <- c("AAPL", "MSFT", "GOOG")

# 2. Fetch income statement and cash flow statements
income_df <- yf_get_financials(tickers, statement_type = "income", frequency = "annual")
cashflow_df <- yf_get_financials(tickers, statement_type = "cash-flow", frequency = "annual")

# 3. Retrieve quarterly valuation measures
stocks <- Tickers$new(tickers)
val_measures <- stocks$valuation_measures

# 4. Join and calculate key metrics
latest_income <- income_df |>
  group_by(symbol) |>
  slice_tail(n = 1) |>
  ungroup() |>
  mutate(operating_margin = operating_income / total_revenue) |>
  select(symbol, date, total_revenue, operating_margin)

latest_cf <- cashflow_df |>
  group_by(symbol) |>
  slice_tail(n = 1) |>
  ungroup() |>
  mutate(fcf_conversion = free_cash_flow / operating_cash_flow) |>
  select(symbol, fcf_conversion)

latest_val <- val_measures |>
  group_by(symbol) |>
  slice_tail(n = 1) |>
  ungroup() |>
  select(symbol, pe_ratio, forward_pe_ratio, peg_ratio, enterprise_value_ebitda_ratio)

screener_summary <- latest_income |>
  left_join(latest_cf, by = "symbol") |>
  left_join(latest_val, by = "symbol")

# 5. Display screener table
print(screener_summary)
```

---

## 7. Summary

In this guide, you learned how to:

1. **Retrieve Structured Statements**: Access income, balance sheet, and cash flow data with `yf_get_financials()`.
2. **Compute Standardized Metrics**: Derive operating margins, net margins, and free cash flow conversion.
3. **Extract Valuation Multiples**: Query multi-stock valuation ratios with `Tickers$valuation_measures`.
4. **Screen & Compare Stocks**: Build custom screening rules combining profitability and market valuation.

---

## 8. Going Further

* **Quarterly Trend Analysis**: Switch to `frequency = "quarterly"` to spot inflection points in revenue and margin trends earlier in the fiscal year.
* **Combine with Technicals**: Pair fundamental screening with technical indicator snapshots via `Ticker$technical_insights`.
* **Historical Price Context**: Use `yf_download_prices()` to chart stock price performance against earnings and fundamental milestones.
* **More recipes**: See `vignette("cookbook", package = "yahoofinancer")` for 15 additional recipes spanning portfolios, currency conversion, and technical analysis.
