Generated banner for Company Valuation
Generated logo for Company Valuation

Company Valuation

Alex YangCommunityCreated by Alex Yang

  • Skill
  • Workflow
  • Business and productivity
  • MIT
  • Low risk

From the author

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.
— the description by Alex Yang

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

Company Valuation provides a structured, multi-method approach to determining the fair value of a public company. It triangulates results from Discounted Cash Flow (DCF), relative peer multiples, and Sum-of-the-Parts (SOTP) analysis to derive an implied share price. The skill includes automated data fetching, sensitivity analysis, and scenario modeling to help users assess whether a stock is overvalued or undervalued based on fundamental data.

What it does

  • Performs a 5-year DCF projection using WACC and terminal value calculations.
  • Conducts relative valuation by comparing the target to a peer group using P/E, EV/Revenue, and EV/EBITDA multiples.
  • Executes SOTP analysis for multi-segment conglomerates.
  • Generates a 5x5 sensitivity grid for WACC and terminal growth rates.
  • Produces Bull, Base, and Bear case scenarios for valuation ranges.
  • Calculates an implied share price by blending results from the chosen methods.

When to use it

  • When you need to determine the intrinsic or fair value of a public company.
  • When you want to assess if a stock is currently overvalued or undervalued.
  • When you need to build a fundamental price target based on financial projections.
  • When comparing a company's valuation against its industry peers.
  • When analyzing a complex conglomerate that requires segment-level valuation.

Advantages

  • Triangulates value using multiple industry-standard methodologies.
  • Provides sensitivity and scenario analysis to account for assumption uncertainty.
  • Automates the retrieval of financial data and peer multiples.
  • Includes industry-specific guidance for DCF and relative valuation.
  • Forces a disciplined, model-driven approach rather than relying on memory.

Usage examples

“What is the fair value of AAPL based on a DCF and peer analysis?”
The agent will fetch AAPL's financial data, run a 5-year DCF model, compare it against a peer group, and output a blended implied share price with sensitivity and scenario tables.
“Is NVDA overvalued right now?”
The agent will perform a relative valuation against semiconductor peers and a DCF model to compare the calculated intrinsic value against the current market price, providing a verdict.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/himself65/company-valuation/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip company-valuation.zip -d .agents/skills

Documentation by Alex Yang

Company Valuation

If your host has not already executed the shell probes below (for example, in Codex), run the commands inside the ! wrappers with its shell tool before choosing a setup path. Use the actual output; if shell access is unavailable, report that limitation.

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 2 method paths — pick the richest one available.

Environment status:

!`python3 -c "exec('try:\n import yfinance, numpy, pandas\n print(\'YFIN_OK\')\nexcept Exception:\n print(\'YFIN_MISSING\')')"`
!`python3 -c "exec('try:\n import yfinance as yf\n t=yf.Ticker(\'^TNX\')\n p=t.fast_info.last_price\n print(f\'RF_10Y={p/100:.4f}\')\nexcept Exception:\n print(\'RF_FETCH_FAIL\')')"`

Decision tree:

ConditionMethod path
YFIN_OKPath A (primary): yfinance for financials + peer multiples
YFIN_MISSINGPath B: pip-install yfinance, then Path A. python3 -m pip install -q yfinance numpy pandas
RF_FETCH_FAILUse 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 typeDCFRelativeSOTPFallback
Mature cash-flow (CPG, telecom, utilities)✅ primary✅❌—
High-growth SaaS / software✅ with care✅ primary❌Use EV/Revenue + Rule of 40
Multi-segment conglomerate✅✅✅ primarySee 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✅sometimesNormalize through-cycle
Defaults table

Settle every parameter before pulling data — these defaults apply unless the user overrides them.

ParameterDefaultRationale
Projection horizon5 yearsStandard explicit forecast window
Terminal growth g2.5%~ long-run US GDP
Risk-free rate rfLive 10Y UST from Step 1, else 4.5%Current cost of capital anchor
Equity risk premium erp5.5%Damodaran mid-range
Betainfo['beta'] from yfinanceMarket-observed levered beta
Cost of debt kdinterest_expense / total_debt, else 5.5%Effective rate; fallback to IG spread
Tax rate3-yr median effective rate, floored 15%, capped 30%Strips out one-offs
Margin assumptions3-yr median of each ratioSmooths cyclical noise
SBC treatmentCash for software/SaaS; non-cash for industrials/CPGIndustry convention
Peer count4-6Balances signal vs noise
Peer multipleMedian (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 gridWACC ±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):

NeedRow
RevenueTotal Revenue
EBITOperating Income
Net incomeNet Income
D&ADepreciation And Amortization (in cashflow)
CapExCapital Expenditure (negative)
ΔNWCChange In Working Capital (cashflow)
SBCStock 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:

  1. Headline verdict — one sentence with the blended fair value, the current price, the % upside or downside, and which method is most bullish or bearish.

  2. Snapshot — sector, industry, market cap, current price, 3M / 12M price change, LTM revenue growth.

  3. Three-method summary — 3-column table: method | implied price | weight | brief rationale.

  4. DCF build — assumptions table (growth path, margins, WACC components, terminal method) + 5-yr FCFF projection table + EV-to-equity bridge.

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

  6. SOTP (if applicable) — segment table + adjustments + equity value.

  7. Sensitivity matrix — WACC × g grid (5×5), base case highlighted.

  8. Scenarios — Bull / Base / Bear table with levers + implied price.

  9. Key risks — which assumptions move the answer most, and what could break the thesis.

Error handling
Missing / edge caseAction
yfinance returns None for betaUse sector-default beta from references/wacc_erp_rates.md
Negative LTM EBITDASkip EV/EBITDA multiple; rely on EV/Revenue + DCF
Negative LTM EPSSkip P/E multiple; use forward P/E if positive, else skip
Growth > WACC in GordonCap g = wacc − 0.5% and flag
Fewer than 3 years historyUse what's available; flag data confidence as "low"
Peer data fetch failsDrop that peer from median; note in output
No segment data for SOTPSkip 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 theme

  • references/sotp.md — Sum-of-parts methodology, conglomerate discount detection, catalysts

  • references/wacc_erp_rates.md — Risk-free rates, equity risk premiums, sector WACC benchmarks, sector-default betas

Files

references/sotp.md

Sum-of-the-Parts (SOTP) Valuation

For companies with 2+ reporting segments, SOTP values each segment using pure-play peer multiples, sums them, and compares to market cap to detect conglomerate discount.

When to Use SOTP

Triggers:

  • Company has 2+ reportable operating segments in 10-K / 20-F

  • Segments operate in materially different industries (e.g., tech + retail, media + theme parks)

  • One segment appears to grow faster or be more valuable than blended multiple suggests

  • SOTP analysis suggests >20% upside vs current market cap (meaningful conglomerate discount)

  • Plausible catalyst within 12-24 months: activist, strategic review, rumored spin-off, board pressure

Do not force SOTP when:

  • Segments share heavy operational integration (e.g., vertically integrated manufacturers) — synergies would be destroyed by separation

  • Segment disclosures are too coarse to model independently

  • No realistic path to value realization (management opposed, no activists)

Workflow

Step 1: Extract Segment Financials

From latest 10-K / 10-Q segment disclosure, pull per segment:

  • Revenue

  • Operating income (EBIT)

  • EBITDA (if disclosed, else EBIT + allocated D&A)

  • Revenue growth YoY

  • Operating margin

Track inter-segment eliminations and unallocated corporate expenses separately.

Step 2: Identify Pure-Play Peers

For each segment, find 3-5 listed pure-play peers in the same industry. Examples:

Segment typePure-play peers
Cloud infrastructureMSFT (Azure), AMZN (AWS), GOOGL (GCP) — for growth multiples
Digital advertisingMETA, GOOGL, TTD, PINS
StreamingNFLX, DIS (DTC), WBD (DTC)
Theme parksSIX, FUN, CCL-adjacent leisure
Retail (physical)WMT, TGT, COST, HD
Semiconductors (design)NVDA, AMD, AVGO, MRVL
Semiconductor fabTSM, INTC (IFS), GFS
Auto (legacy)F, GM, STLA
Auto (EV)TSLA, RIVN, LCID
Insurance (P&C)TRV, CB, ALL, PGR
Insurance (life)MET, PRU, LNC
Utility (regulated)DUK, SO, AEP
Pharma / biotechPFE, MRK, LLY, ABBV

Record peer median EV/EBITDA, EV/Revenue (for growth segments), and P/E.

Step 3: Apply Multiples
segment_EV_i = segment_EBITDA_i × peer_median_EV/EBITDA_i

Use EV/EBITDA as default. For high-growth or pre-profit segments, use EV/Revenue.

Step 4: Adjust for Corporate-Level Items
Total EV from segments
− Unallocated corporate costs (cap at 2-5% of revenue, or discount at 8x the ongoing cost)
− Minority interest
− Total debt
− Preferred stock
− Pension underfunding
+ Cash & equivalents
+ Non-operating assets (excess real estate, investments, NOLs)
= Equity Value

Implied price = Equity Value / diluted shares
Step 5: Compute Conglomerate Discount
discount_pct = (SOTP_price − market_price) / SOTP_price × 100

Thresholds:

  • >30%: compelling; likely actionable

  • 20-30%: meaningful; need catalyst

  • 10-20%: narrow; requires catalyst + technicals

  • <10%: no opportunity

Step 6: Identify Catalyst

Conglomerate discount can persist indefinitely without a catalyst. Require at least one of:

  • Activist investor filed 13D pushing for breakup

  • Management publicly discussed "strategic alternatives" or "portfolio simplification"

  • Rumored or announced spin-off / divestiture

  • CEO change (new CEOs often simplify)

  • Peer transaction highlighting valuation gap

  • Board refresh with activist nominees

Example

DiverseTech Corp (DVTK) — two segments:

  • Cloud Platform: $3B rev, 30% growth, 25% EBITDA margin → $0.75B EBITDA

  • Legacy Hardware: $5B rev, flat, 15% EBITDA margin → $0.75B EBITDA

Peer multiples:

  • Cloud peers median EV/EBITDA: 20x → cloud EV = $15B

  • Hardware peers median EV/EBITDA: 8x → hardware EV = $6B

Total segment EV = $21B
− Corporate costs  = $2B
− Net debt         = $2B
= Equity value     = $17B
Shares out         = 250M
Implied SOTP price = $68
Market price       = $42
Discount           = 38% — compelling

Catalyst: Activist filed 13D demanding cloud spin-off. Enter position at $42.

Edge Cases & Traps

IssueHandling
Shared costs allocated inconsistentlyRead 10-K segment footnote; recalculate if allocation is arbitrary
Synergy destructionDeduct 5-15% of segment EV for operational coupling (shared sales, shared R&D)
Tax leakage on spin-off / divestitureFactor 10-20% of realized value as tax cost
Minority interest in a segmentMultiply segment EV by parent's ownership %
Hidden liabilities (env, pension, litigation)Review 10-K footnotes; subtract estimated NPV
Persistent discount with no catalystDon't invest — "dead money" until catalyst materializes
Peer group too narrowUse broader set to avoid anchoring on inflated comps
Segment EBITDA before stock compReconcile — SaaS peers may be post-SBC, industrial peers pre-SBC

Position Sizing (if SOTP feeds into a trade)

  • 4-6% of portfolio per SOTP position (value trades with identified catalyst)

  • Stop-loss: −15% from entry (wider stop because discount can widen before closing)

  • Time stop: 12 months with no catalyst progress → reassess

  • Portfolio cap: 15% of capital in SOTP / conglomerate-discount trades (correlated risk)

  • Trim when discount narrows to <10%; add when it widens to >35% with no thesis break

Performance Expectations

  • Win rate with catalyst: 55-65%

  • Win rate without catalyst: 40-45%

  • Average winner: +20% to +40% over 12-24 months

  • Average loser: −10% to −15%

  • Risk/reward with catalyst: 2:1 to 3:1

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs Python

Security

What our scanner noticed· Low risk

  • Instructions that use the network

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
Alex Yang
Publisher
Alex Yang (Community)
Source
himself65/finance-skills · plugins/market-analysis/skills/company-valuation · commit a085078
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Alex Yang or Alex Yang.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download company-valuation.zip