Skill2.8k repo starsupdated 5d ago
company-valuation
The company-valuation Claude Code skill triangulates intrinsic value using three methods: discounted cash flow (DCF) with five-year free cash flow projections, relative valuation applying peer multiples, and sum-of-the-parts (SOTP) for multi-segment businesses. Use this skill when you need to estimate a company's share price through multiple approaches, present sensitivity analysis across discount rates and terminal growth assumptions, and generate bull, base, and bear case scenarios for investment analysis or financial research.
Install in Claude Code
Copygit clone --depth 1 https://github.com/himself65/finance-skills /tmp/company-valuation && cp -r /tmp/company-valuation/plugins/market-analysis/skills/company-valuation ~/.claude/skills/company-valuationThen start a new Claude Code session; the skill loads automatically.
Definition
SKILL.md
# Company Valuation
Triangulates intrinsic value via three methods, then blends them to an implied share price:
1. **DCF** — 5-year FCFF projection, discount at WACC, terminal value.
2. **Relative** — apply peer median P/E, EV/Revenue, EV/EBITDA.
3. **SOTP** — when 2+ distinct reporting segments exist, value each at pure-play peer multiples.
Always present a WACC × terminal-growth sensitivity table and Bull/Base/Bear scenarios.
**Disclaimer**: Research/educational output. Not financial advice.
---
## Step 1: Detection Flow
Detect data source and runtime deps. The skill supports 3 method paths — pick the richest one available.
**Environment status:**
```
!`python3 -c "import yfinance, numpy, pandas; print('YFIN_OK')" 2>/dev/null || echo "YFIN_MISSING"`
```
```
!`(command -v funda && funda --version) 2>/dev/null || echo "FUNDA_CLI_MISSING"`
```
```
!`python3 -c "import yfinance as yf; t=yf.Ticker('^TNX'); p=t.fast_info.last_price; print(f'RF_10Y={p/100:.4f}')" 2>/dev/null || echo "RF_FETCH_FAIL"`
```
**Decision tree:**
| Condition | Method path |
|---|---|
| `YFIN_OK` | **Path A** (primary): yfinance for financials + peer multiples |
| `YFIN_MISSING` but `FUNDA_CLI_MISSING` is not set | **Path B**: delegate to `finance-data-providers:funda-data` skill for fundamentals |
| Both missing | **Path C**: pip-install yfinance, then Path A. `python3 -m pip install -q yfinance numpy pandas` |
| `RF_FETCH_FAIL` | Use default `rf = 0.045` and note stale risk-free rate in output |
If `RF_10Y=` printed, use that value as `rf` in Step 4d instead of the hardcoded 4.5%.
---
## Step 2: Choose Methods & Set Defaults
### Method applicability
| Company type | DCF | Relative | SOTP | Fallback |
|---|---|---|---|---|
| Mature cash-flow (CPG, telecom, utilities) | ✅ primary | ✅ | ❌ | — |
| High-growth SaaS / software | ✅ with care | ✅ primary | ❌ | Use EV/Revenue + Rule of 40 |
| Multi-segment conglomerate | ✅ | ✅ | ✅ primary | See `references/sotp.md` |
| Banks / insurance | ❌ | ✅ (P/B, P/TBV) | ❌ | DDM or excess return; note in output |
| Pre-revenue | ❌ | EV/Revenue only | ❌ | Flag low confidence |
| REITs | ❌ | ✅ (P/FFO, P/AFFO) | ❌ | NAV-based |
| Cyclicals (energy, semis, industrials) | ✅ on mid-cycle | ✅ | sometimes | Normalize through-cycle |
### Defaults table
Every parameter below MUST have a value before moving to Step 3. Use these unless the user overrides.
| Parameter | Default | Rationale |
|---|---|---|
| Projection horizon | 5 years | Standard explicit forecast window |
| Terminal growth `g` | 2.5% | ~ long-run US GDP |
| Risk-free rate `rf` | Live 10Y UST from Step 1, else 4.5% | Current cost of capital anchor |
| Equity risk premium `erp` | 5.5% | Damodaran mid-range |
| Beta | `info['beta']` from yfinance | Market-observed levered beta |
| Cost of debt `kd` | `interest_expense / total_debt`, else 5.5% | Effective rate; fallback to IG spread |
| Tax rate | 3-yr median effective rate, floored 15%, capped 30% | Strips out one-offs |
| Margin assumptions | 3-yr median of each ratio | Smooths cyclical noise |
| SBC treatment | Cash for software/SaaS; non-cash for industrials/CPG | Industry convention |
| Peer count | 4-6 | Balances signal vs noise |
| Peer multiple | Median (not mean) | Robust to outliers |
| Method weights (no SOTP) | DCF 50% / Relative 50% | Equal triangulation |
| Method weights (with SOTP) | DCF 40% / Relative 30% / SOTP 30% | SOTP gets weight when applicable |
| Sensitivity grid | WACC ±1% in 0.5% steps × g from 1.5-3.5% in 0.5% | 5×5 matrix |
See `references/wacc_erp_rates.md` for current risk-free rates, ERP tables, and sector WACC benchmarks.
---
## Step 3: Pull Data
```python
import yfinance as yf
import numpy as np
import pandas as pd
TICKER = "AAPL" # replace
t = yf.Ticker(TICKER)
info = t.info
income_a = t.income_stmt
cashflow_a = t.cashflow
balance_a = t.balance_sheet
income_q = t.quarterly_income_stmt
cashflow_q = t.quarterly_cashflow
earnings_est = t.earnings_estimate
revenue_est = t.revenue_estimate
price = info.get("currentPrice") or info.get("regularMarketPrice")
market_cap = info.get("marketCap")
shares_out = info.get("sharesOutstanding")
total_debt = info.get("totalDebt") or 0
cash = info.get("totalCash") or 0
beta = info.get("beta") or 1.0
sector = info.get("sector")
industry = info.get("industry")
```
Key financial statement rows (yfinance labels):
| Need | Row |
|---|---|
| Revenue | `Total Revenue` |
| EBIT | `Operating Income` |
| Net income | `Net Income` |
| D&A | `Depreciation And Amortization` (in cashflow) |
| CapEx | `Capital Expenditure` (negative) |
| ΔNWC | `Change In Working Capital` (cashflow) |
| SBC | `Stock Based Compensation` (cashflow) |
---
## Step 4: DCF Build
Full methodology + industry-specific tweaks in `references/dcf.md`. Quick skeleton:
```python
# 4a. Revenue growth path — fade from Y1 (consensus or hist CAGR) to terminal g
hist_cagr = (rev[-1] / rev[0]) ** (1 / (len(rev)-1)) - 1
y1 = float(revenue_est.loc["+1y", "growth"]) if "+1y" in revenue_est.index else hist_cagr
g_terminal = 0.025
growth_path = np.linspace(y1, g_terminal + 0.01, 5)
# 4b. Margins — 3y median
ebit_margin = float((income_a.loc["Operating Income"] / income_a.loc["Total Revenue"]).iloc[:3].median())
da_pct = float((cashflow_a.loc["Depreciation And Amortization"] / income_a.loc["Total Revenue"]).iloc[:3].median())
capex_pct = float((cashflow_a.loc["Capital Expenditure"].abs() / income_a.loc["Total Revenue"]).iloc[:3].median())
nwc_pct = float((cashflow_a.loc["Change In Working Capital"].abs() / income_a.loc["Total Revenue"]).iloc[:3].median())
tax_rate = max(0.15, min(0.30, 0.21)) # use effective if available
# 4c. FCFF per year
rev_t = [float(income_a.loc["Total Revenue"].iloc[0])]
fcff = []
for g in growth_path:
rev_t.append(rev_t[-1] * (1 + g))
ebit = rev_t[-1] * ebit_margin
nopat = ebit * (1 - tax_rate)
fcff.append(nopat + rev_t[-1]*da_pct - rev_t[-1