company-valuation
该技能通过DCF、相对估值和分部加总三种方法,自动计算公司隐含股价,生成WACC-增长率敏感度表和牛/基准/熊情景,适合投资分析和财务建模,大幅提升估值效率。
npx skills add https://github.com/himself65/finance-skills --skill company-valuationBefore / After 效果对比
1 组在没有这个技能之前,用户需要手动收集财报数据、计算WACC、搭建DCF模型、查找可比公司并计算中位数倍数,整个过程通常需要8小时以上,且容易出错。
此技能自动拉取数据、执行三种估值方法并生成完整报告,用户只需输入股票代码,几分钟即可获得专业级别的估值结果。
Company Valuation
Triangulates intrinsic value via three methods, then blends them to an implied share price:
- DCF — 5-year FCFF projection, discount at WACC, terminal value.
- Relative — apply peer median P/E, EV/Revenue, EV/EBITDA.
- 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
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:
# 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]*capex_pct - rev_t[-1]*nwc_pct)
# 4d. WACC
rf, erp, kd = 0.045, 0.055, 0.055 # override rf with live value from Step 1
ke = rf + beta * erp
e_v = market_cap / (market_cap + total_debt)
d_v = 1 - e_v
wacc = e_v*ke + d_v*kd*(1 - tax_rate)
# 4e. Terminal value — compute both, use midpoint
tv_gordon = fcff[-1] * (1 + g_terminal) / (wacc - g_terminal)
tv_exit = (rev_t[-1] * ebit_margin + rev_t[-1] * da_pct) * 15 # peer median EV/EBITDA
tv_base = 0.5 * (tv_gordon + tv_exit)
# 4f. Bridge to equity
pv_fcff = sum(f / (1+wacc)**(i+1) for i, f in enumerate(fcff))
pv_tv = tv_base / (1+wacc)**5
ev = pv_fcff + pv_tv
equity = ev + cash - total_debt
implied_price_dcf = equity / shares_out
Gates: (a) if wacc <= g_terminal → stop, g too aggressive; (b) if pv_tv / ev > 0.85 or < 0.45 → flag and show both TV methods; (c) if wacc is outside the sector sanity band in references/wacc_erp_rates.md → note.
Step 5: Relative Valuation
Select 4-6 peers. Peer map and adjustment rules in references/relative_valuation.md.
PEERS = ["MSFT", "ORCL", "CRM", "NOW", "SAP", "WDAY"] # pick by industry
multiples = {}
for p in PEERS:
pi = yf.Ticker(p).info
multiples[p] = {
"pe_fwd": pi.get("forwardPE"),
"ev_rev": pi.get("enterpriseToRevenue"),
"ev_ebitda": pi.get("enterpriseToEbitda"),
"ps": pi.get("priceToSalesTrailing12Months"),
}
med_pe = np.nanmedian([v["pe_fwd"] for v in multiples.values()])
med_ev_rev = np.nanmedian([v["ev_rev"] for v in multiples.values()])
med_ev_eb = np.nanmedian([v["ev_ebitda"] for v in multiples.values()])
eps_ttm = float(income_q.loc["Diluted EPS"].iloc[:4].sum())
rev_ttm = float(income_q.loc["Total Revenue"].iloc[:4].sum())
ebitda_ttm = float(income_q.loc["EBIT"].iloc[:4].sum()) + float(cashflow_q.loc["Depreciation And Amortization"].iloc[:4].sum())
net_debt = total_debt - cash
implied_pe = med_pe * eps_ttm
implied_ev_rev = (med_ev_rev * rev_ttm - net_debt) / shares_out
implied_ev_ebit = (med_ev_eb * ebitda_ttm - net_debt) / shares_out
implied_price_rel = np.nanmedian([implied_pe, implied_ev_rev, implied_ev_ebit])
Adjust peer median ±10-30% if target's growth or margin profile diverges materially. Always state the adjustment and reason. Rule of 40 anchor for SaaS in references/relative_valuation.md.
Step 6: SOTP (multi-segment only)
Skip unless the 10-K reports 2+ operating segments with distinct economics. yfinance does NOT expose segment data — user must supply or parse from filings. Full methodology in references/sotp.md:
- Identify segments + pure-play peer for each
- Apply peer median EV/EBITDA (or EV/Rev for growth segments)
- Subtract unallocated corporate costs (cap 2-5% of revenue if unknown)
- Subtract net debt, minority interest; divide by shares
SOTP discount = (SOTP price − market price) / SOTP price. Flag if >20% (conglomerate discount).
Step 7: Triangulate, Sensitivity, Scenarios
# Blended implied price
if sotp_price is None:
blended = 0.5*implied_price_dcf + 0.5*implied_price_rel
else:
blended = 0.4*implied_price_dcf + 0.3*implied_price_rel + 0.3*sotp_price
# 5x5 sensitivity grid
wacc_grid = [wacc + dx for dx in (-0.01, -0.005, 0, 0.005, 0.01)]
g_grid = [0.015, 0.020, 0.025, 0.030, 0.035]
sens = {}
for w in wacc_grid:
for g in g_grid:
tv = fcff[-1]*(1+g)/(w-g)
pv = sum(f/(1+w)**(i+1) for i,f in enumerate(fcff)) + tv/(1+w)**5
sens[(w,g)] = (pv + cash - total_debt) / shares_out
Also produce Bull / Base / Bear: shift revenue growth ±300bps, EBIT margin ±200bps, WACC ∓100bps, terminal g 3.0% / 2.5% / 1.5%.
Step 8: Respond to the User
Output in this order:
- Headline verdict — one sentence: blended fair value, vs. current, % upside/downside, most bullish/bearish method. Example: "AAPL fair value ≈ $215 (blended), vs. current $198 → ~9% upside; DCF is most bullish at $228."
- Snapshot — sector, industry, market cap, current price, 3M / 12M price change, LTM revenue growth.
- Three-method summary — 3-column table: method | implied price | weight | brief rationale.
- DCF build — assumptions table (growth path, margins, WACC components, terminal method) + 5-yr FCFF projection table + EV-to-equity bridge.
- Peer comparison — table of peers with P/E fwd, EV/Rev, EV/EBITDA, gross margin, rev growth; bottom row = median; flag target's premium/discount.
- SOTP (if applicable) — segment table + adjustments + equity value.
- Sensitivity matrix — WACC × g grid (5×5), base case highlighted.
- Scenarios — Bull / Base / Bear table with levers + implied price.
- Key risks — 3-5 bullets: which assumption moves the answer most; what could break the thesis.
Error handling
| Missing / edge case | Action |
|---|---|
yfinance returns None for beta | Use sector-default beta from references/wacc_erp_rates.md |
| Negative LTM EBITDA | Skip EV/EBITDA multiple; rely on EV/Revenue + DCF |
| Negative LTM EPS | Skip P/E multiple; use forward P/E if positive, else skip |
| Growth > WACC in Gordon | Cap g = wacc − 0.5% and flag |
| Fewer than 3 years history | Use what's available; flag data confidence as "low" |
| Peer data fetch fails | Drop that peer from median; note in output |
| No segment data for SOTP | Skip Section 6; proceed with DCF + Relative only |
Caveats to include
- TTM data lags real-time; peer multiples reflect market sentiment (can overshoot)
- DCF is garbage-in/garbage-out; sensitivity matters more than a point estimate
- yfinance data is unofficial; cross-check any decision with primary filings
- Not financial advice
Reference Files
references/dcf.md— DCF methodology + industry-specific guidance (software, retail, financials, healthcare, energy, manufacturing, CPG, telecom, REITs, streaming)references/relative_valuation.md— Peer selection, multiple adjustment rules, Rule of 40, peer sets by themereferences/sotp.md— Sum-of-parts methodology, conglomerate discount detection, catalystsreferences/wacc_erp_rates.md— Risk-free rates, equity risk premiums, sector WACC benchmarks, sector-default betas
Company Valuation
Estimate the intrinsic value of a public company via DCF, relative (peer multiple), and sum-of-parts (SOTP) methods, and blend into a triangulated implied share price with sensitivity tables.
What it does
- Pulls 5 years of financials + analyst estimates via yfinance
- Builds a 5-year DCF with explicit revenue / margin / WACC / terminal-value assumptions
- Applies peer median P/E, EV/Revenue, EV/EBITDA multiples across 4-6 peers
- Runs SOTP when the company has 2+ distinct reporting segments
- Presents a blended implied price with method weights, WACC × g sensitivity matrix, and Bull/Base/Bear scenarios
- Handles banks/REITs/pre-revenue/cyclical edge cases with appropriate fallbacks
Triggers
what is AAPL worth, valuation of NVDA, fair value of TSLA, DCF for MSFT, build a DCF, intrinsic value, implied share price, is X overvalued/undervalued, relative valuation, EV/EBITDA target, SOTP, sum of the parts, price target from fundamentals, value this company
Prerequisites
- Python 3.8+
yfinance,numpy,pandas(auto-installed if missing)
Optional: finance-data-providers:funda-data skill as a fallback data source.
Platform
CLI-based agents (Claude Code). Requires shell + pip.
Setup
No authentication required. First run will auto-install dependencies.
Reference Files
references/dcf.md— DCF methodology, industry-specific guidance (software, retail, financials, healthcare, energy, manufacturing, CPG, telecom, REITs, streaming), common pitfallsreferences/relative_valuation.md— Peer selection heuristics, multiple adjustment rules, Rule of 40 for SaaS, default peer sets by themereferences/sotp.md— Sum-of-parts methodology, conglomerate discount detection, catalyst framework, position sizingreferences/wacc_erp_rates.md— Risk-free rates (live + default), equity risk premiums, sector WACC bands, sector-default betas, terminal growth ceilings
Output
Structured briefing with: headline verdict, snapshot, three-method summary, DCF build, peer comparison, SOTP (if applicable), sensitivity matrix, scenarios, key risks, and caveats.
Disclaimer
For research and educational purposes only. Not financial advice.
用户评价 (0)
发表评价
暂无评价
统计数据
用户评分
为此 Skill 评分