New: Earn 20% as an AgentAlley affiliate. Share your link and earn on every sale you refer. Join now New: Earn 20% as an affiliate. Join now

Estimate the intrinsic value of a public company using DCF

Company valuation

by himself65 · MIT license · ★ 3,347 on GitHub · updated Aug 27

Company valuation cover

Estimate the intrinsic value of a public company using DCF, relative (peer multiple) and sum-of-parts (SOTP) methods, then triangulate to an implied share price with upside/downside versus the current market price. Use this skill…

---
name: company-valuation
description: >
  Estimate the intrinsic value of a public company using DCF, relative (peer multiple)
  and sum-of-parts (SOTP) methods, then triangulate to an implied share price with
  upside/downside versus the current market price. Use this skill whenever the user asks:
  "what is AAPL worth", "valuation of NVDA", "fair value of TSLA", "intrinsic value",
  "DCF for MSFT", "build a DCF", "discounted cash flow", "WACC", "terminal value",
  "implied share price", "upside to fair value", "is X overvalued/undervalued",
  "relative valuation", "peer comparison valuation", "EV/EBITDA target", "SOTP",
  "sum of the parts", "how much is [company] worth", "price target from fundamentals",
  "value this company", or any ticker in the context of computing intrinsic or
  relative valuation. Default to running ALL three methods
  (DCF + relative + SOTP-if-applicable) and presenting a blended implied price with a
  sensitivity table. Do not answer valuation questions from memory — always run the workflow.
---

# Company Valuation

Overview

Triangulates intrinsic value via three methods, then blends them to an implied share price:

Manual install (npx, ZIP)
Claude Codenpx skills add himself65/finance-skills --skill company-valuation -g -a claude-code
Claude Code (manual)mkdir -p ~/.claude/skills && curl -sL https://codeload.github.com/himself65/finance-skills/tar.gz/0a5759bca1ea \ | tar -xz -C ~/.claude/skills --strip-components=4 finance-skills-0a5759bca1ea/plugins/market-analysis/skills/company-valuation
Windows (PowerShell)New-Item -ItemType Directory -Force "$HOME\.claude\skills" | Out-Null; Invoke-WebRequest "https://m.agentalley.io/zip/727fb7687f98c399b03d/company-valuation.zip" -OutFile "$env:TEMP\company-valuation.zip"; Expand-Archive "$env:TEMP\company-valuation.zip" -DestinationPath "$HOME\.claude\skills" -Force
Claude.ai / desktopDownload the ZIP and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md12.9 KB
  • README.md2.1 KB
  • references/4 files · 25.0 KB
Read the files here
himself65/0a5759b6 files
SKILL.md
Show the full text302 lines

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 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:

Condition Method path
YFIN_OK 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

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:

  1. 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."
  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 — 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 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
1---
2name: company-valuation
3description: >
4 Estimate the intrinsic value of a public company using DCF, relative (peer multiple)
5 and sum-of-parts (SOTP) methods, then triangulate to an implied share price with
6 upside/downside versus the current market price. Use this skill whenever the user asks:
7 "what is AAPL worth", "valuation of NVDA", "fair value of TSLA", "intrinsic value",
8 "DCF for MSFT", "build a DCF", "discounted cash flow", "WACC", "terminal value",
9 "implied share price", "upside to fair value", "is X overvalued/undervalued",
10 "relative valuation", "peer comparison valuation", "EV/EBITDA target", "SOTP",
11 "sum of the parts", "how much is [company] worth", "price target from fundamentals",
12 "value this company", or any ticker in the context of computing intrinsic or
13 relative valuation. Default to running ALL three methods
14 (DCF + relative + SOTP-if-applicable) and presenting a blended implied price with a
15 sensitivity table. Do not answer valuation questions from memory — always run the workflow.
16---
17 
18# Company Valuation
19 
20Triangulates intrinsic value via three methods, then blends them to an implied share price:
21 
221. **DCF** — 5-year FCFF projection, discount at WACC, terminal value.
232. **Relative** — apply peer median P/E, EV/Revenue, EV/EBITDA.
243. **SOTP** — when 2+ distinct reporting segments exist, value each at pure-play peer multiples.
25 
26Always present a WACC × terminal-growth sensitivity table and Bull/Base/Bear scenarios.
27 
28**Disclaimer**: Research/educational output. Not financial advice.
29 
30---
31 
32## Step 1: Detection Flow
33 
34Detect data source and runtime deps. The skill supports 2 method paths — pick the richest one available.
35 
36**Environment status:**
37 
38```
39!`python3 -c "exec('try:\n import yfinance, numpy, pandas\n print(\'YFIN_OK\')\nexcept Exception:\n print(\'YFIN_MISSING\')')"`
40```
41 
42```
43!`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\')')"`
44```
45 
46**Decision tree:**
47 
48| Condition | Method path |
49|---|---|
50| `YFIN_OK` | **Path A** (primary): yfinance for financials + peer multiples |
51| `YFIN_MISSING` | **Path B**: pip-install yfinance, then Path A. `python3 -m pip install -q yfinance numpy pandas` |
52| `RF_FETCH_FAIL` | Use default `rf = 0.045` and note stale risk-free rate in output |
53 
54If `RF_10Y=` printed, use that value as `rf` in Step 4d instead of the hardcoded 4.5%.
55 
56---
57 
58## Step 2: Choose Methods & Set Defaults
59 
60### Method applicability
61 
62| Company type | DCF | Relative | SOTP | Fallback |
63|---|---|---|---|---|
64| Mature cash-flow (CPG, telecom, utilities) | ✅ primary | ✅ | ❌ | — |
65| High-growth SaaS / software | ✅ with care | ✅ primary | ❌ | Use EV/Revenue + Rule of 40 |
66| Multi-segment conglomerate | ✅ | ✅ | ✅ primary | See `references/sotp.md` |
67| Banks / insurance | ❌ | ✅ (P/B, P/TBV) | ❌ | DDM or excess return; note in output |
68| Pre-revenue | ❌ | EV/Revenue only | ❌ | Flag low confidence |
69| REITs | ❌ | ✅ (P/FFO, P/AFFO) | ❌ | NAV-based |
70| Cyclicals (energy, semis, industrials) | ✅ on mid-cycle | ✅ | sometimes | Normalize through-cycle |
71 
72### Defaults table
73 
74Every parameter below MUST have a value before moving to Step 3. Use these unless the user overrides.
75 
76| Parameter | Default | Rationale |
77|---|---|---|
78| Projection horizon | 5 years | Standard explicit forecast window |
79| Terminal growth `g` | 2.5% | ~ long-run US GDP |
80| Risk-free rate `rf` | Live 10Y UST from Step 1, else 4.5% | Current cost of capital anchor |
81| Equity risk premium `erp` | 5.5% | Damodaran mid-range |
82| Beta | `info['beta']` from yfinance | Market-observed levered beta |
83| Cost of debt `kd` | `interest_expense / total_debt`, else 5.5% | Effective rate; fallback to IG spread |
84| Tax rate | 3-yr median effective rate, floored 15%, capped 30% | Strips out one-offs |
85| Margin assumptions | 3-yr median of each ratio | Smooths cyclical noise |
86| SBC treatment | Cash for software/SaaS; non-cash for industrials/CPG | Industry convention |
87| Peer count | 4-6 | Balances signal vs noise |
88| Peer multiple | Median (not mean) | Robust to outliers |
89| Method weights (no SOTP) | DCF 50% / Relative 50% | Equal triangulation |
90| Method weights (with SOTP) | DCF 40% / Relative 30% / SOTP 30% | SOTP gets weight when applicable |
91| Sensitivity grid | WACC ±1% in 0.5% steps × g from 1.5-3.5% in 0.5% | 5×5 matrix |
92 
93See `references/wacc_erp_rates.md` for current risk-free rates, ERP tables, and sector WACC benchmarks.
94 
95---
96 
97## Step 3: Pull Data
98 
99```python
100import yfinance as yf
101import numpy as np
102import pandas as pd
103 
104TICKER = "AAPL" # replace
105t = yf.Ticker(TICKER)
106 
107info = t.info
108income_a = t.income_stmt
109cashflow_a = t.cashflow
110balance_a = t.balance_sheet
111income_q = t.quarterly_income_stmt
112cashflow_q = t.quarterly_cashflow
113 
114earnings_est = t.earnings_estimate
115revenue_est = t.revenue_estimate
116 
117price = info.get("currentPrice") or info.get("regularMarketPrice")
118market_cap = info.get("marketCap")
119shares_out = info.get("sharesOutstanding")
120total_debt = info.get("totalDebt") or 0
121cash = info.get("totalCash") or 0
122beta = info.get("beta") or 1.0
123sector = info.get("sector")
124industry = info.get("industry")
125```
126 
127Key financial statement rows (yfinance labels):
128 
129| Need | Row |
130|---|---|
131| Revenue | `Total Revenue` |
132| EBIT | `Operating Income` |
133| Net income | `Net Income` |
134| D&A | `Depreciation And Amortization` (in cashflow) |
135| CapEx | `Capital Expenditure` (negative) |
136| ΔNWC | `Change In Working Capital` (cashflow) |
137| SBC | `Stock Based Compensation` (cashflow) |
138 
139---
140 
141## Step 4: DCF Build
142 
143Full methodology + industry-specific tweaks in `references/dcf.md`. Quick skeleton:
144 
145```python
146# 4a. Revenue growth path — fade from Y1 (consensus or hist CAGR) to terminal g
147hist_cagr = (rev[-1] / rev[0]) ** (1 / (len(rev)-1)) - 1
148y1 = float(revenue_est.loc["+1y", "growth"]) if "+1y" in revenue_est.index else hist_cagr
149g_terminal = 0.025
150growth_path = np.linspace(y1, g_terminal + 0.01, 5)
151 
152# 4b. Margins — 3y median
153ebit_margin = float((income_a.loc["Operating Income"] / income_a.loc["Total Revenue"]).iloc[:3].median())
154da_pct = float((cashflow_a.loc["Depreciation And Amortization"] / income_a.loc["Total Revenue"]).iloc[:3].median())
155capex_pct = float((cashflow_a.loc["Capital Expenditure"].abs() / income_a.loc["Total Revenue"]).iloc[:3].median())
156nwc_pct = float((cashflow_a.loc["Change In Working Capital"].abs() / income_a.loc["Total Revenue"]).iloc[:3].median())
157tax_rate = max(0.15, min(0.30, 0.21)) # use effective if available
158 
159# 4c. FCFF per year
160rev_t = [float(income_a.loc["Total Revenue"].iloc[0])]
161fcff = []
162for g in growth_path:
163 rev_t.append(rev_t[-1] * (1 + g))
164 ebit = rev_t[-1] * ebit_margin
165 nopat = ebit * (1 - tax_rate)
166 fcff.append(nopat + rev_t[-1]*da_pct - rev_t[-1]*capex_pct - rev_t[-1]*nwc_pct)
167 
168# 4d. WACC
169rf, erp, kd = 0.045, 0.055, 0.055 # override rf with live value from Step 1
170ke = rf + beta * erp
171e_v = market_cap / (market_cap + total_debt)
172d_v = 1 - e_v
173wacc = e_v*ke + d_v*kd*(1 - tax_rate)
174 
175# 4e. Terminal value — compute both, use midpoint
176tv_gordon = fcff[-1] * (1 + g_terminal) / (wacc - g_terminal)
177tv_exit = (rev_t[-1] * ebit_margin + rev_t[-1] * da_pct) * 15 # peer median EV/EBITDA
178tv_base = 0.5 * (tv_gordon + tv_exit)
179 
180# 4f. Bridge to equity
181pv_fcff = sum(f / (1+wacc)**(i+1) for i, f in enumerate(fcff))
182pv_tv = tv_base / (1+wacc)**5
183ev = pv_fcff + pv_tv
184equity = ev + cash - total_debt
185implied_price_dcf = equity / shares_out
186```
187 
188**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.
189 
190---
191 
192## Step 5: Relative Valuation
193 
194Select 4-6 peers. Peer map and adjustment rules in `references/relative_valuation.md`.
195 
196```python
197PEERS = ["MSFT", "ORCL", "CRM", "NOW", "SAP", "WDAY"] # pick by industry
198multiples = {}
199for p in PEERS:
200 pi = yf.Ticker(p).info
201 multiples[p] = {
202 "pe_fwd": pi.get("forwardPE"),
203 "ev_rev": pi.get("enterpriseToRevenue"),
204 "ev_ebitda": pi.get("enterpriseToEbitda"),
205 "ps": pi.get("priceToSalesTrailing12Months"),
206 }
207med_pe = np.nanmedian([v["pe_fwd"] for v in multiples.values()])
208med_ev_rev = np.nanmedian([v["ev_rev"] for v in multiples.values()])
209med_ev_eb = np.nanmedian([v["ev_ebitda"] for v in multiples.values()])
210 
211eps_ttm = float(income_q.loc["Diluted EPS"].iloc[:4].sum())
212rev_ttm = float(income_q.loc["Total Revenue"].iloc[:4].sum())
213ebitda_ttm = float(income_q.loc["EBIT"].iloc[:4].sum()) + float(cashflow_q.loc["Depreciation And Amortization"].iloc[:4].sum())
214net_debt = total_debt - cash
215 
216implied_pe = med_pe * eps_ttm
217implied_ev_rev = (med_ev_rev * rev_ttm - net_debt) / shares_out
218implied_ev_ebit = (med_ev_eb * ebitda_ttm - net_debt) / shares_out
219implied_price_rel = np.nanmedian([implied_pe, implied_ev_rev, implied_ev_ebit])
220```
221 
222Adjust 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`.
223 
224---
225 
226## Step 6: SOTP (multi-segment only)
227 
228Skip 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`:
229- Identify segments + pure-play peer for each
230- Apply peer median EV/EBITDA (or EV/Rev for growth segments)
231- Subtract unallocated corporate costs (cap 2-5% of revenue if unknown)
232- Subtract net debt, minority interest; divide by shares
233 
234SOTP discount = (SOTP price − market price) / SOTP price. Flag if >20% (conglomerate discount).
235 
236---
237 
238## Step 7: Triangulate, Sensitivity, Scenarios
239 
240```python
241# Blended implied price
242if sotp_price is None:
243 blended = 0.5*implied_price_dcf + 0.5*implied_price_rel
244else:
245 blended = 0.4*implied_price_dcf + 0.3*implied_price_rel + 0.3*sotp_price
246 
247# 5x5 sensitivity grid
248wacc_grid = [wacc + dx for dx in (-0.01, -0.005, 0, 0.005, 0.01)]
249g_grid = [0.015, 0.020, 0.025, 0.030, 0.035]
250sens = {}
251for w in wacc_grid:
252 for g in g_grid:
253 tv = fcff[-1]*(1+g)/(w-g)
254 pv = sum(f/(1+w)**(i+1) for i,f in enumerate(fcff)) + tv/(1+w)**5
255 sens[(w,g)] = (pv + cash - total_debt) / shares_out
256```
257 
258Also produce Bull / Base / Bear: shift revenue growth ±300bps, EBIT margin ±200bps, WACC ∓100bps, terminal g 3.0% / 2.5% / 1.5%.
259 
260---
261 
262## Step 8: Respond to the User
263 
264Output in this order:
265 
2661. **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."
2672. **Snapshot** — sector, industry, market cap, current price, 3M / 12M price change, LTM revenue growth.
2683. **Three-method summary** — 3-column table: method | implied price | weight | brief rationale.
2694. **DCF build** — assumptions table (growth path, margins, WACC components, terminal method) + 5-yr FCFF projection table + EV-to-equity bridge.
2705. **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.
2716. **SOTP** (if applicable) — segment table + adjustments + equity value.
2727. **Sensitivity matrix** — WACC × g grid (5×5), base case highlighted.
2738. **Scenarios** — Bull / Base / Bear table with levers + implied price.
2749. **Key risks** — 3-5 bullets: which assumption moves the answer most; what could break the thesis.
275 
276### Error handling
277 
278| Missing / edge case | Action |
279|---|---|
280| yfinance returns `None` for beta | Use sector-default beta from `references/wacc_erp_rates.md` |
281| Negative LTM EBITDA | Skip EV/EBITDA multiple; rely on EV/Revenue + DCF |
282| Negative LTM EPS | Skip P/E multiple; use forward P/E if positive, else skip |
283| Growth > WACC in Gordon | Cap `g = wacc − 0.5%` and flag |
284| Fewer than 3 years history | Use what's available; flag data confidence as "low" |
285| Peer data fetch fails | Drop that peer from median; note in output |
286| No segment data for SOTP | Skip Section 6; proceed with DCF + Relative only |
287 
288### Caveats to include
289- TTM data lags real-time; peer multiples reflect market sentiment (can overshoot)
290- DCF is garbage-in/garbage-out; sensitivity matters more than a point estimate
291- yfinance data is unofficial; cross-check any decision with primary filings
292- Not financial advice
293 
294---
295 
296## Reference Files
297 
298- `references/dcf.md` — DCF methodology + industry-specific guidance (software, retail, financials, healthcare, energy, manufacturing, CPG, telecom, REITs, streaming)
299- `references/relative_valuation.md` — Peer selection, multiple adjustment rules, Rule of 40, peer sets by theme
300- `references/sotp.md` — Sum-of-parts methodology, conglomerate discount detection, catalysts
301- `references/wacc_erp_rates.md` — Risk-free rates, equity risk premiums, sector WACC benchmarks, sector-default betas
302 
View all files on GitHub →

Details

Updated
Aug 27, 2026
License
MIT
Stars on the repo
★ 3,347
Checked
Source
himself65/finance-skills ↗
Creator
himself65 · 24 listings
View creator

Similar skills

See all →
SkillFind keywords a competitor ranks for that the user's siteCompetitor gapRyze-AI-Adgent/open-seo-mcp-skills · by Ryze-AI-AdgentFind keywords a competitor ranks for that the user's site doesn't — the content gap, prioritized by volume and winnability. Use when asked "what does competitor.com rank for", "keyword gap vs X", "steal competitor keywords", or "why do they outrank us".★ 3.1k GitHub starsSkillMine the highest-converting ad angles from customer reviewsAd angle minergooseworks-ai/goose-skills · by gooseworks-aiMine the highest-converting ad angles from customer reviews, Reddit complaints, support tickets, and competitor ads. Extracts actual pain language, competitor weaknesses, and outcome phrases that real buyers use. Outputs a ranked angle bank with proof quotes and recommended ad formats per angle.★ 1.2k GitHub starsSkillAnalyze competitor content coverageCompetitor content intelligencesandbaseai/sandbase-skills · by sandbaseaiAnalyze competitor content coverage and uncover differentiated content opportunities using web search, page extraction, and DataForSEO content analysis. Use when asked for competitor content research, editorial gap analysis, content brief inputs, or topic whitespace.★ 203 GitHub starsSkillCreates competitive battlecards for sales deal conversationsgrowthack88/growth-marketing-os · by growthack88Creates competitive battlecards for sales deal conversations. Produces win themes, landmines to plant, objection handlers, and competitive positioning per competitor. Outputs a structured markdown battlecard with quick-reference sections for live sales calls. Depends on competitor-research for competitive intelligence and consumes product-messaging, win-loss-analysis, and positioning for framing. Feeds into sales-deck, outreach-emails, and demo-script. Triggered by "battlecard", "competitive intel", "win against [competitor]", or "how do we beat [competitor]".★ 117 GitHub starsSkillRead your X audience and niche from real dataX audience insightssergebulaev/x-skills · by sergebulaevRead your X (Twitter) audience and niche from real data. Pull a handle's recent tweets (yours or a competitor's) with likes, replies, and views, see which formats and hooks are working, read the repliers on a tweet (X gates likers, so repliers are the signal), and scan a niche query for top tweets. Powered by Apify, no login. Triggers on "analyze my tweets", "what is working on X", "read the replies", "competitor tweets", "who is engaging". Not for writing a tweet (use x-post-writer).★ 95 GitHub starsSkillRead a Facebook Page and its audience from real dataFacebook Audience Insightssergebulaev/facebook-skills · by sergebulaevRead a Facebook Page and its audience from real data. Pull any Page's public stats (yours or a competitor's): followers, likes, categories, intro, websites. And pull the commenters on a public Page post, since Facebook hides the reactor and liker roster and shows counts only, so commenters are the signal. Powered by Apify, no login. Triggers on "analyze my Page", "competitor Page stats", "who is commenting", "read the comments", "audience insights". Not for writing Page posts (use fb-post-writer).★ 49 GitHub stars

More from himself65

SkillRead Discord for financial research using opencliDiscord Skill (Read-Only)himself65/finance-skills · by himself65Read Discord for financial research using opencli (read-only). Use this skill whenever the user wants to read Discord channels, search for messages in trading servers, view guild/channel info, monitor crypto or market discussion groups, or gather financial sentiment from Discord. Triggers include: "check my Discord", "search Discord for", "read Discord messages", what's happening in the trading Discord", "show Discord channels", "list my servers", Discord sentiment on BTC", "what are people saying in Discord about AAPL", monitor crypto Discord", any mention of Discord in context of reading financial news, market research, or trading community discussions. This skill is READ-ONLY — it does NOT support sending messages, reacting, or any write operations.★ 3.3k GitHub starsSkillGenerate a pre-earnings briefing for any stock using YahooEarnings Preview Skillhimself65/finance-skills · by himself65Generate a pre-earnings briefing for any stock using Yahoo Finance data. Use this skill whenever the user wants to prepare for an upcoming earnings report, understand what analysts expect, review a company's beat/miss track record, or get a quick overview before an earnings call. Triggers include: "earnings preview for AAPL", "what to expect from TSLA earnings", MSFT reports next week", "earnings preview", "pre-earnings analysis", what are analysts expecting for NVDA", "earnings estimates for", will GOOGL beat earnings", "earnings beat/miss history", upcoming earnings", "before earnings", "earnings setup", consensus estimates", "earnings whisper", "EPS expectations", what's the street expecting", "earnings season preview", any mention of preparing for or previewing an earnings report, or any request to understand expectations ahead of a company's earnings date. Always use this skill when the user mentions a ticker in context of upcoming earnings, even if they don't say "preview" explicitly.★ 3.3k GitHub starsSkillGenerate a post-earnings analysis for any stock using YahooEarnings Recap Skillhimself65/finance-skills · by himself65Generate a post-earnings analysis for any stock using Yahoo Finance data. Use when the user wants to review what happened after earnings, understand beat/miss results, see stock reaction, or get an earnings recap. Triggers: "AAPL earnings recap", "how did TSLA earnings go", "MSFT earnings results", did NVDA beat earnings", "post-earnings analysis", "earnings surprise", what happened with GOOGL earnings", "earnings reaction", stock moved after earnings", "EPS beat or miss", "revenue beat or miss", quarterly results for", "how were earnings", "AMZN reported last night", earnings call recap", or any request about a company's recent earnings outcome. Use this skill when the user references a past earnings event, even if they just say "AAPL reported" or "how did they do".★ 3.3k GitHub starsSkillDeep-dive into analyst estimates and revision trends for anyEstimate Analysis Skillhimself65/finance-skills · by himself65Deep-dive into analyst estimates and revision trends for any stock using Yahoo Finance data. Use when the user wants to understand analyst estimate direction, how EPS or revenue forecasts changed over time, compare estimate distributions, or analyze growth projections across periods. Triggers: "estimate analysis for AAPL", "analyst estimate trends for NVDA", EPS revisions for TSLA", "how have estimates changed for MSFT", estimate revisions", "EPS trend", "revenue estimates", consensus changes", "analyst estimates", "estimate distribution", growth estimates for", "estimate momentum", "revision trend", forward estimates", "next quarter estimates", "annual estimates", estimate spread", "bull vs bear estimates", "estimate range", or any request about tracking or comparing analyst estimates/revisions. Use this skill when the user asks about estimates beyond a simple lookup — if they want context, trends, or analysis, this is the right skill.★ 3.3k GitHub starsSkillCalculate ETF premium/discount vs NAV via Yahoo FinanceETF Premium/Discount Analysis Skillhimself65/finance-skills · by himself65Calculate ETF premium/discount vs NAV via Yahoo Finance, and decompose single-day surges into NAV-driven vs structural components (gamma squeeze, dealer hedging, blocked AP arbitrage). Use whenever the user asks about an ETF's premium or discount, NAV comparison, why an ETF diverged from its holdings, or how much of a move is dealer-hedging-driven. Triggers: "ETF premium", "ETF discount", "NAV premium", "is SPY at a premium", "BITO premium", IBIT premium", "bond ETF discount", "trading above/below NAV", "ETF premium screener", biggest discount", "compare ETF NAV", "ETF arbitrage", "ETF gamma squeeze", ETF premium surge", "decompose ETF move", "dealer gamma exposure", "GEX for ETF", why did this ETF jump", "premium convergence", "AP arbitrage blocked", or any request about the gap between an ETF's price and underlying value. Especially relevant for leveraged, inverse, international, bond, commodity, and crypto ETFs.★ 3.3k GitHub starsSkillDesign system and guidelines for Claude's built-inGenerative UI Skillhimself65/finance-skills · by himself65Design system and guidelines for Claude's built-in generative UI — the show_widget tool that renders interactive HTML/SVG widgets inline in claude.ai conversations. This skill provides the complete Anthropic "Imagine" design system so Claude produces high-quality widgets without needing to call read_me first. Use this skill whenever the user asks to visualize data, create an interactive chart, build a dashboard, render a diagram, draw a flowchart, show a mockup, create an interactive explainer, or produce any visual content beyond plain text or markdown. Triggers include: "show me", "visualize", draw", "chart", "dashboard", "diagram", "flowchart", "widget", "interactive", "mockup", "illustrate", explain how X works" (with visual), or any request for visual/interactive output. Also triggers when the user wants to display financial data visually, create comparison grids, or build tools with sliders, toggles, or live-updating displays.★ 3.3k GitHub stars