Loading...
Loading...
Compare original and translation side by side
!`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"`| Condition | Method path |
|---|---|
| Path A (primary): yfinance for financials + peer multiples |
| Path B: delegate to |
| Both missing | Path C: pip-install yfinance, then Path A. |
| Use default |
RF_10Y=rf!`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"`| 条件 | 方法路径 |
|---|---|
| 路径A(首选):使用yfinance获取财务数据和可比公司倍数 |
| 路径B:委托 |
| 两者均缺失 | 路径C:pip安装yfinance,然后使用路径A。 |
| 使用默认值 |
RF_10Y=rf| 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 |
| 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 |
| 公司类型 | DCF | 相对估值 | SOTP | 备选方案 |
|---|---|---|---|---|
| 成熟现金流型(消费品、电信、公用事业) | ✅ 首选 | ✅ | ❌ | — |
| 高增长SaaS/软件 | ✅ 谨慎使用 | ✅ 首选 | ❌ | 使用EV/收入 + 40法则 |
| 多分部企业集团 | ✅ | ✅ | ✅ 首选 | 参见 |
| 银行/保险 | ❌ | ✅(P/B、P/TBV) | ❌ | 股息贴现模型(DDM)或超额收益法;在输出中注明 |
| 未盈利 | ❌ | 仅使用EV/收入 | ❌ | 标记低置信度 |
| 房地产投资信托(REITs) | ❌ | ✅(P/FFO、P/AFFO) | ❌ | 基于资产净值(NAV) |
| 周期性行业(能源、半导体、工业) | ✅ 基于周期中期 | ✅ | 有时适用 | 跨周期标准化 |
| Parameter | Default | Rationale |
|---|---|---|
| Projection horizon | 5 years | Standard explicit forecast window |
Terminal growth | 2.5% | ~ long-run US GDP |
Risk-free rate | Live 10Y UST from Step 1, else 4.5% | Current cost of capital anchor |
Equity risk premium | 5.5% | Damodaran mid-range |
| Beta | | Market-observed levered beta |
Cost of debt | | 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 |
references/wacc_erp_rates.md| 参数 | 默认值 | 依据 |
|---|---|---|
| 预测期限 | 5年 | 标准明确预测窗口 |
终值增长率 | 2.5% | ~美国长期GDP增长率 |
无风险利率 | 步骤1获取的实时10年期美国国债收益率,否则为4.5% | 当前资本成本锚点 |
股权风险溢价 | 5.5% | Damodaran中位数区间 |
| Beta值 | yfinance的 | 市场观测的杠杆Beta |
债务成本 | | 有效利率;备选为投资级利差 |
| 税率 | 3年中位数有效税率,下限15%,上限30% | 剔除一次性因素 |
| 利润率假设 | 各比率的3年中位数 | 平滑周期性波动 |
| 股权激励(SBC)处理 | 软件/SaaS视为现金支出;工业/消费品视为非现金支出 | 行业惯例 |
| 可比公司数量 | 4-6家 | 平衡信号与噪音 |
| 可比公司倍数 | 中位数(而非均值) | 对异常值更稳健 |
| 方法权重(无SOTP) | DCF 50% / 相对估值 50% | 均等交叉验证 |
| 方法权重(含SOTP) | DCF 40% / 相对估值 30% / SOTP 30% | 适用时给予SOTP相应权重 |
| 敏感性分析网格 | WACC ±1%,步长0.5% × 增长率1.5-3.5%,步长0.5% | 5×5矩阵 |
references/wacc_erp_rates.mdimport 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")| Need | Row |
|---|---|
| Revenue | |
| EBIT | |
| Net income | |
| D&A | |
| CapEx | |
| ΔNWC | |
| SBC | |
import yfinance as yf
import numpy as np
import pandas as pd
TICKER = "AAPL" # 替换为目标股票代码
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")| 需求 | 行标签 |
|---|---|
| 收入 | |
| EBIT(息税前利润) | |
| 净利润 | |
| 折旧与摊销 | |
| 资本支出 | |
| 营运资金变化 | |
| 股权激励 | |
references/dcf.mdundefinedreferences/dcf.mdundefined
**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.
---
**校验规则**:(a) 如果`wacc <= g_terminal` → 终止,增长率过于激进;(b) 如果`pv_tv / ev > 0.85`或`< 0.45` → 标记并展示两种终值计算方法;(c) 如果`wacc`超出`references/wacc_erp_rates.md`中的行业合理区间 → 注明。
---references/relative_valuation.mdPEERS = ["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])references/relative_valuation.mdreferences/relative_valuation.mdPEERS = ["MSFT", "ORCL", "CRM", "NOW", "SAP", "WDAY"] # 按行业选择
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])references/relative_valuation.mdreferences/sotp.mdreferences/sotp.mdundefinedundefined
Also produce Bull / Base / Bear: shift revenue growth ±300bps, EBIT margin ±200bps, WACC ∓100bps, terminal g 3.0% / 2.5% / 1.5%.
---
同时生成乐观/基准/悲观场景:收入增长率±300个基点,EBIT利润率±200个基点,WACC∓100个基点,终值增长率3.0% / 2.5% / 1.5%。
---| Missing / edge case | Action |
|---|---|
yfinance returns | Use sector-default beta from |
| 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 |
| 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 |
| 缺失/边缘情况 | 操作 |
|---|---|
yfinance返回beta为 | 使用 |
| 过去12个月EBITDA为负 | 跳过EV/EBITDA倍数;依赖EV/收入 + DCF模型 |
| 过去12个月EPS为负 | 跳过P/E倍数;如预期P/E为正则使用,否则跳过 |
| 戈登模型中增长率>WACC | 将 |
| 历史数据不足3年 | 使用可用数据;标记数据置信度为“低” |
| 可比公司数据拉取失败 | 将该公司从中位数计算中剔除;在输出中注明 |
| SOTP估值无分部数据 | 跳过第6节;仅使用DCF + 相对估值继续 |
references/dcf.mdreferences/relative_valuation.mdreferences/sotp.mdreferences/wacc_erp_rates.mdreferences/dcf.mdreferences/relative_valuation.mdreferences/sotp.mdreferences/wacc_erp_rates.md