Download plugins/market-analysis/skills/company-valuation/SKILL.md from the publisher, or copy the path and open the repository. PlugMCP lists the skill and does not host the file.
Where does company-valuation live?
The publisher keeps it at https://github.com/himself65/finance-skills.
Which agents can use company-valuation?
Claude, Cursor, and Codex can read a SKILL.md you add from the publisher's repository.
>
name: company-valuation
description: >
Estimate a public company's intrinsic value with DCF, relative (peer multiple), and
sum-of-the-parts (SOTP) methods, then blend them into an implied share price with
upside/downside vs the market price, a WACC and terminal-growth sensitivity grid,
and bull/base/bear scenarios. Use this skill whenever the user asks what a company
or ticker is worth: fair value, intrinsic value, implied share price, a price target
from fundamentals, whether it is overvalued or undervalued, building a DCF (WACC,
terminal value, discounted cash flow), EV/EBITDA or P/E based targets, peer
comparison valuation, or SOTP and conglomerate discounts. Run the model rather than
answering valuation questions from memory.
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 2 method paths — pick the richest one available.
Path A (primary): yfinance for financials + peer multiples
YFIN_MISSING
Path B: 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
Settle every parameter before pulling data — these defaults apply unless the user overrides them.
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
rev = income_a.loc["Total Revenue"].dropna().iloc[::-1].values # yfinance columns are newest-first; reverse to oldest -> newest
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())
eff_tax = (income_a.loc["Tax Provision"] / income_a.loc["Pretax Income"]).iloc[:3].median()
tax_rate = float(min(0.30, max(0.15, eff_tax))) if pd.notna(eff_tax) else 0.21 # 3y median effective, floored 15%, capped 30%
# 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
Present the valuation in this order:
Headline verdict — one sentence with the blended fair value, the current price, the % upside or downside, and which method is most bullish or bearish.
Download plugins/market-analysis/skills/company-valuation/SKILL.md from the publisher, or copy the path and open the repository. PlugMCP lists the skill and does not host the file.
Where does company-valuation live?
The publisher keeps it at https://github.com/himself65/finance-skills.
Which agents can use company-valuation?
Claude, Cursor, and Codex can read a SKILL.md you add from the publisher's repository.