07 · 实战:完整分析一只股票¶
长期投资教程 · 第 7 章(终章)
免责声明:本教程为投资教育内容,所有分析与示例仅为方法演示,不构成任何投资建议。文中涉及的公司与数据仅用于教学举例,不代表推荐。市场有风险,决策需自负。
本章学什么 / 读完会什么¶
这是总复习 + 实战。我们把前六章的工具串成一套「该不该长期持有」的分析框架, 并用它真刀真枪分析两家公司:贵州茅台(A股)和苹果(美股)。
分析五步走(对应前面章节):
- 生意懂不懂 —— 它靠什么赚钱(定性,第2章)
- 赚钱能力强不强 —— ROE / 毛利率 / 净利率(第3章)
- 财务健不健康 —— 负债率 / 经营现金流 vs 利润 / 自由现金流(第2-3章)
- 成长性如何 —— 营收/利润增速(第2-3章)
- 现在贵不贵 —— 估值分位 + 趋势(第3-5章)
⚠️ 重要:本章给的是分析框架和方法,最后的「评分」只是把客观指标量化呈现,绝不是买入/卖出建议。真实投资决策要结合宏观、行业、公司治理、你自己的风险偏好等无数因素。框架帮你思考,但替不了你做决定,更不构成投资建议。
import sys, os
sys.path.insert(0, os.path.abspath('.'))
import warnings; warnings.filterwarnings('ignore')
import numpy as np, pandas as pd
import matplotlib.pyplot as plt
import invest_data as D
FONT = D.setup_matplotlib()
np.random.seed(D.SEED)
print('中文字体:', FONT, '| 数据目录:', D.DATA_DIR)
中文字体: Noto Sans CJK SC | 数据目录: /data/docs/investing/long-term-investing/data
7.1 搭一套通用的「体检」函数¶
先写两个分析函数:A股走 akshare 摘要表,美股走 yfinance 三表。它们都产出同一套指标,方便横向对比。
def analyze_a(symbol, name):
"""分析A股:返回最近年度的核心指标 dict。"""
ab = D.load_a_abstract(symbol)
price = D.load_a_price(symbol)
inc = D.load_a_report(symbol, "income")
cf = D.load_a_report(symbol, "cashflow")
def y(metric):
s = ab.loc[metric].dropna(); s = s[s.index.month == 12]; return s
rev = y("营业总收入"); ni = y("归母净利润")
roe = y("净资产收益率(ROE)"); gm = y("毛利率")
nm = y("销售净利率") if "销售净利率" in ab.index else y("净利率")
dr = y("资产负债率"); ocf = y("经营现金流量净额")
# 自由现金流
def ann(df, col):
s = df[df.index.month == 12][col].dropna(); return s
ocf_r = ann(cf, "经营活动产生的现金流量净额")
capex = ann(cf, "购建固定资产、无形资产和其他长期资产所支付的现金")
fcf = (ocf_r - capex)
# 估值:PE 历史分位
eps = ab.loc["基本每股收益"].dropna(); eps_a = eps[eps.index.month==12].sort_index()
px = price["close"]
eps_al = px.index.to_series().apply(lambda d: eps_a[eps_a.index<=d].iloc[-1] if len(eps_a[eps_a.index<=d]) else np.nan)
pe_hist = (px/eps_al).dropna()
return {
"name": name, "market": "A股", "price": px.iloc[-1], "src": D.source_tag(price),
"ROE": roe.iloc[-1], "毛利率": gm.iloc[-1], "净利率": nm.iloc[-1],
"资产负债率": dr.iloc[-1], "营收增速": (rev.iloc[-1]/rev.iloc[-2]-1)*100,
"利润增速": (ni.iloc[-1]/ni.iloc[-2]-1)*100,
"现金流利润比": ocf.iloc[-1]/ni.iloc[-1],
"FCF最新(亿)": fcf.iloc[-1]/1e8, "FCF为正年数": int((fcf.dropna().tail(5)>0).sum()),
"FCF统计年数": int(len(fcf.dropna().tail(5))),
"PE当前": pe_hist.iloc[-1], "PE分位%": (pe_hist<pe_hist.iloc[-1]).mean()*100,
"price_series": px, "roe_series": roe, "rev_series": rev,
}
def _pick(df, keys):
for k in keys:
for idx in df.index:
if k.lower() == str(idx).lower():
return df.loc[idx]
for k in keys:
for idx in df.index:
if k.lower() in str(idx).lower():
return df.loc[idx]
return None
def analyze_us(ticker, name):
"""分析美股:用 yfinance 三表。"""
inc = D.load_us_stmt(ticker, "income")
bal = D.load_us_stmt(ticker, "balance")
cf = D.load_us_stmt(ticker, "cashflow")
price = D.load_us_price(ticker)
rev = _pick(inc, ["Total Revenue"])
ni = _pick(inc, ["Net Income"])
gp = _pick(inc, ["Gross Profit"])
eq = _pick(bal, ["Stockholders Equity"])
ocf = _pick(cf, ["Operating Cash Flow"])
fcf = _pick(cf, ["Free Cash Flow"])
roe = (ni / eq * 100)
gm = (gp / rev * 100); nm = (ni / rev * 100)
px = price["close"]
return {
"name": name, "market": "美股", "price": px.iloc[-1], "src": D.source_tag(price),
"ROE": roe.iloc[-1], "毛利率": gm.iloc[-1], "净利率": nm.iloc[-1],
"资产负债率": np.nan, # yfinance 口径需另算,这里聚焦现金流与盈利
"营收增速": (rev.iloc[-1]/rev.iloc[-2]-1)*100,
"利润增速": (ni.iloc[-1]/ni.iloc[-2]-1)*100,
"现金流利润比": ocf.iloc[-1]/ni.iloc[-1],
"FCF最新(亿)": fcf.iloc[-1]/1e8, "FCF为正年数": int((fcf.dropna()>0).sum()),
"FCF统计年数": int(len(fcf.dropna())),
"PE当前": np.nan, "PE分位%": np.nan,
"price_series": px, "roe_series": roe, "rev_series": rev,
}
print("分析函数就绪")
分析函数就绪
7.2 分析对象一:贵州茅台(A股)¶
茅台的生意:高端白酒龙头。靠极强的品牌力和稀缺性获得定价权,几乎是「印钞机」型生意——这是我们在第2、3章已经验证过的。现在跑一遍完整体检:
mt = analyze_a("600519", "贵州茅台")
print(f"【{mt['name']}】{mt['market']} 当前股价 {mt['price']:.1f} 元 {mt['src']}\n")
print(f" 盈利能力: ROE {mt['ROE']:.1f}% | 毛利率 {mt['毛利率']:.1f}% | 净利率 {mt['净利率']:.1f}%")
print(f" 财务健康: 资产负债率 {mt['资产负债率']:.1f}% | 经营现金流/净利润 {mt['现金流利润比']:.2f}")
print(f" 自由现金流: 最新 {mt['FCF最新(亿)']:.0f} 亿 | 近年为正 {mt['FCF为正年数']}/{mt['FCF统计年数']} 年")
print(f" 成长性: 营收增速 {mt['营收增速']:.1f}% | 利润增速 {mt['利润增速']:.1f}%")
print(f" 估值: PE {mt['PE当前']:.0f}x,处于近几年 {mt['PE分位%']:.0f}% 分位")
【贵州茅台】A股 当前股价 1215.0 元 (真实数据·本地缓存) 盈利能力: ROE 32.5% | 毛利率 91.2% | 净利率 50.5% 财务健康: 资产负债率 16.4% | 经营现金流/净利润 0.75 自由现金流: 最新 584 亿 | 近年为正 5/5 年 成长性: 营收增速 -1.2% | 利润增速 -4.5% 估值: PE 19x,处于近几年 0% 分位
7.3 分析对象二:苹果(美股)¶
苹果的生意:消费电子 + 服务生态。靠 iPhone 硬件 + App Store/服务的高粘性生态赚钱,品牌溢价 + 用户锁定构成护城河。跑体检:
ap = analyze_us("AAPL", "苹果")
print(f"【{ap['name']}】{ap['market']} 当前股价 ${ap['price']:.1f} {ap['src']}\n")
print(f" 盈利能力: ROE {ap['ROE']:.1f}% | 毛利率 {ap['毛利率']:.1f}% | 净利率 {ap['净利率']:.1f}%")
print(f" 财务健康: 经营现金流/净利润 {ap['现金流利润比']:.2f}")
print(f" 自由现金流: 最新 {ap['FCF最新(亿)']:.0f} 亿美元 | 近年为正 {ap['FCF为正年数']}/{ap['FCF统计年数']} 年")
print(f" 成长性: 营收增速 {ap['营收增速']:.1f}% | 利润增速 {ap['利润增速']:.1f}%")
print(" 注:苹果 ROE 极高部分源于大额回购缩减了净资产分母,需结合负债结构理解。")
【苹果】美股 当前股价 $298.0 (真实数据·本地缓存) 盈利能力: ROE 151.9% | 毛利率 46.9% | 净利率 26.9% 财务健康: 经营现金流/净利润 1.00 自由现金流: 最新 988 亿美元 | 近年为正 4/4 年 成长性: 营收增速 6.4% | 利润增速 19.5% 注:苹果 ROE 极高部分源于大额回购缩减了净资产分母,需结合负债结构理解。
7.4 横向对比 + 雷达图¶
把两家公司的核心维度画成雷达图,直观对比「体格」。我们把几个指标统一归一化到 0~100 分(仅为可视化对比,非绝对评分):
def score_card(a):
"""把原始指标映射到0~100直观分(阈值为教学设定,非投资标准)。"""
def clip(x, lo, hi): return max(0, min(100, (x-lo)/(hi-lo)*100))
return {
"盈利能力(ROE)": clip(a["ROE"], 5, 35),
"毛利率": clip(a["毛利率"], 20, 90),
"现金含量": clip(a["现金流利润比"]*100, 60, 130),
"成长性": clip(a["利润增速"], -10, 40),
"FCF稳健": (a["FCF为正年数"]/max(a["FCF统计年数"],1))*100,
}
sc_mt = score_card(mt); sc_ap = score_card(ap)
dims = list(sc_mt.keys())
ang = np.linspace(0, 2*np.pi, len(dims), endpoint=False).tolist(); ang += ang[:1]
fig, ax = plt.subplots(figsize=(7,7), subplot_kw=dict(polar=True))
for sc, name, color in [(sc_mt,"贵州茅台","#c0392b"), (sc_ap,"苹果","#2c3e50")]:
vals = [sc[d] for d in dims]; vals += vals[:1]
ax.plot(ang, vals, lw=2, label=name, color=color)
ax.fill(ang, vals, alpha=0.12, color=color)
ax.set_xticks(ang[:-1]); ax.set_xticklabels(dims)
ax.set_ylim(0,100); ax.set_title("茅台 vs 苹果 · 多维体检雷达图(归一化分,仅作对比)")
ax.legend(loc="upper right", bbox_to_anchor=(1.25,1.1))
plt.tight_layout(); plt.show()
cmp = pd.DataFrame({"贵州茅台": sc_mt, "苹果": sc_ap}).round(0)
print(cmp.to_string())
贵州茅台 苹果 盈利能力(ROE) 92.0 100.0 毛利率 100.0 38.0 现金含量 21.0 56.0 成长性 11.0 59.0 FCF稳健 100.0 100.0
这张图在说什么:雷达图覆盖面积越大、越饱满,说明这家公司在这几个维度上整体越强。茅台和苹果都是各自市场的顶级公司,盈利能力、现金含量都很突出,但「形状」不同——这正反映了不同生意模式的特点(高毛利稳健型 vs 高 ROE 强生态型)。注意:这里的归一化评分阈值是教学设定,不同行业不能简单套用同一把尺子。
7.5 趋势与估值快照:现在是什么位置¶
最后看「市场先生」当前给的报价处在什么位置——把价格走势和(A股的)估值分位放一起。好公司 + 不贵的价格 = 长期投资者真正想要的组合。
fig, axes = plt.subplots(1, 2, figsize=(13, 5))
# 茅台:价格 + 年线
mtpx = mt["price_series"].iloc[-750:]
ma250 = mtpx.rolling(250).mean()
axes[0].plot(mtpx.index, mtpx.values, color="#c0392b", lw=1.2, label="茅台收盘")
axes[0].plot(ma250.index, ma250.values, color="gray", lw=1.5, label="MA250(年线)")
axes[0].set_title(f"茅台 价格 vs 年线 (PE分位 {mt['PE分位%']:.0f}%)"); axes[0].legend()
# 苹果:价格 + 年线
appx = ap["price_series"].iloc[-750:]
ma250b = appx.rolling(250).mean()
axes[1].plot(appx.index, appx.values, color="#2c3e50", lw=1.2, label="苹果收盘")
axes[1].plot(ma250b.index, ma250b.values, color="gray", lw=1.5, label="MA250(年线)")
axes[1].set_title("苹果 价格 vs 年线"); axes[1].legend()
plt.tight_layout(); plt.show()
print(f"茅台:价格 {'在年线上方(长期偏多)' if mtpx.iloc[-1]>ma250.iloc[-1] else '在年线下方(长期偏弱)'},PE 分位 {mt['PE分位%']:.0f}%")
print(f"苹果:价格 {'在年线上方(长期偏多)' if appx.iloc[-1]>ma250b.iloc[-1] else '在年线下方(长期偏弱)'}")
茅台:价格 在年线下方(长期偏弱),PE 分位 0% 苹果:价格 在年线上方(长期偏多)
这张图在说什么:把第4章学的年线趋势和第3章学的估值分位合在一起看——价格相对年线的位置告诉你长期趋势方向,估值分位告诉你贵贱。理想的长期买点是「好公司 + 估值分位低 + 趋势没破坏」;要警惕的是「估值分位很高 + 增速放缓」。但这些都只是参考信号,不是机械的买卖指令。
7.6 「该不该长期持有」分析框架(总结)¶
把全部串起来,一只股票值不值得长期持有,依次问自己五个问题:
| 步骤 | 问题 | 看什么(章节) | 红旗信号 |
|---|---|---|---|
| ① 生意 | 它靠什么赚钱?护城河在哪? | 定性理解(第2章) | 看不懂的生意、护城河被侵蚀 |
| ② 盈利 | 赚钱效率高吗? | ROE>15%、高毛利净利(第3章) | ROE 长期低或剧烈波动 |
| ③ 健康 | 财务稳吗?赚的是真钱吗? | 负债率、经营现金流≥净利润、FCF为正(第2-3章) | 高利润低现金流、负债飙升 |
| ④ 成长 | 还能增长吗? | 营收/利润增速(第2-3章) | 增速持续转负 |
| ⑤ 估值 | 现在买贵不贵? | PE/PB 分位、年线趋势(第3-5章) | 估值历史高位 + 增速放缓 |
用法:①是前提(看不懂就不碰);②③④判断「是不是好公司」;⑤判断「是不是好价格」。好公司 + 好价格 + 长期持有 + 适当分散(第6章)= 长期投资的朴素答案。
再次强调(也是整套教程的结尾):
🔚 教程结语与免责声明¶
恭喜你走完了从入门到精通的全程!你现在拥有了一套可复用的分析框架:会读三张表、会算关键指标、会做简化估值、会看 K 线趋势、懂定投与组合。把本章的 analyze_a / analyze_us 换成任何你感兴趣的股票代码,就能跑一遍属于你自己的分析。
但请永远记住三件事:
- 框架不是水晶球。所有指标都是「后视镜」,反映过去,不保证未来。真实世界还有宏观、政策、行业变迁、黑天鹅、公司治理等无数变量。
- 认知决定收益。别人推荐的「好股票」不是你的,只有自己研究透、看得懂、拿得住的,才是你的。
- 活下来最重要。分散、仓位、不上杠杆、不借钱炒股——先保证不出局,复利才有机会发酵。
免责声明:本教程为投资教育内容,所有分析、指标、评分与示例仅为方法演示,使用的真实公司数据仅用于教学举例,不构成任何投资建议,也不代表对任何证券的推荐。投资有风险,过往业绩不预示未来表现,任何决策请基于你自己的独立判断并自行承担后果。
免责声明:本教程为投资教育内容,所有分析与示例仅为方法演示,不构成任何投资建议。文中涉及的公司与数据仅用于教学举例,不代表推荐。市场有风险,决策需自负。
—— 教程完 ——