00 · 导读与环境¶

长期投资「从入门到精通」交互式教程 · 第 0 章

免责声明:本教程为投资教育内容,所有分析与示例仅为方法演示,不构成任何投资建议。文中涉及的公司与数据仅用于教学举例,不代表推荐。市场有风险,决策需自负。


这套教程是给谁的¶

如果你会写代码、看得懂 Python,但一提到「市盈率」「自由现金流」「ROE」就头大,那这套教程就是为你写的。

我们不堆术语。每个金融概念都按这个顺序讲:

大白话 + 类比 → 公式 → 代码 → 图

你不用背定义,跟着把代码跑一遍、把图看明白,概念自然就懂了。

读完你会什么¶

  • 看懂一家公司的三张财务报表,知道「赚钱」和「收到钱」是两回事;
  • 用 ROE、毛利率、负债率、自由现金流、PE/PB 等指标给公司体检;
  • 读懂 K 线:一根蜡烛的开高低收、均线、成交量分别在说什么;
  • 自己跑一遍定投 vs 一次性买入的回测,理解复利和长期持有的意义;
  • 最终能独立搭一个「这只股票该不该长期持有」的分析框架。

章节地图¶

章节 主题 你会得到
00 导读与环境 跑通环境、画出第一张图
01 钱为什么要投出去 通胀/复利/资产类别,定投复利曲线
02 读懂财报·三张表 利润表/资产负债表/现金流量表白话拆解
03 财务指标与估值 ROE 杜邦拆解、PE/PB、简化 DCF 计算器
04 看懂 K 线与技术面 mplfinance 真实 K 线、均线、成交量
05 长期投资策略 定投 vs 一次性买入回测、估值买入区间
06 构建与跟踪组合 多股组合年化/回撤、再平衡演示
07 实战·完整分析一只股票 把全部串起来的分析框架

怎么用¶

  1. 选对 kernel:右上角 kernel 选 Python (invest)(对应共享 venv /data/docs/investing/.venv)。
  2. 从上往下逐个 cell 运行(Shift+Enter)。每个 cell 都能改了重跑,鼓励你动手改参数看变化。
  3. 图下面都有「这张图在说什么」的解读文字,别只看图。

0.1 环境引导¶

下面这个 cell 是每章开头都会跑的「引导代码」:导入库、配置中文字体、固定随机种子。 它还会导入本教程的统一数据层 invest_data(别名 D),所有取数都走它。

In [1]:
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

0.2 数据从哪来(真实数据优先)¶

本教程坚持用真实数据举例:

  • A股:用 akshare(走新浪 sina 端点)取贵州茅台(600519)、宁德时代(300750)的行情与财报。
  • 美股:用 yfinance 取苹果(AAPL)、英伟达(NVDA)的行情与三表。
  • 指数:沪深300(000300)、标普500(GSPC),用于定投回测。

为了可重复 + 离线也能跑,第一次抓到的真实数据都缓存在 data/*.csv。 invest_data 的取数逻辑是三级降级:

读本地缓存(真实) → 失败则实时拉取(真实) → 再失败才用「⚠️ 合成示例数据」并显式标注

铁律:正文里出现的每个数字都来自实际跑出来的 cell 输出;合成数据只在真实数据彻底拿不到时才用,且一定打 ⚠️ 示例数据 标记,绝不冒充真实。

下面看看缓存里有哪些真实数据:

In [2]:
import os
files = sorted(os.listdir(D.DATA_DIR))
print(f"data/ 目录共 {len(files)} 个缓存文件:")
for f in files:
    size = os.path.getsize(os.path.join(D.DATA_DIR, f)) // 1024
    print(f"  {f:28s} {size:>5d} KB")
data/ 目录共 20 个缓存文件:
  abstract_300750.csv             33 KB
  abstract_600519.csv             80 KB
  balance_300750.csv              39 KB
  balance_600519.csv              81 KB
  cashflow_300750.csv             24 KB
  cashflow_600519.csv             49 KB
  income_300750.csv               25 KB
  income_600519.csv               47 KB
  index_000300.csv               328 KB
  index_GSPC.csv                 142 KB
  price_300750.csv               171 KB
  price_600519.csv               175 KB
  price_AAPL.csv                 117 KB
  price_NVDA.csv                 115 KB
  yf_balance_AAPL.csv              5 KB
  yf_balance_NVDA.csv              5 KB
  yf_cashflow_AAPL.csv             4 KB
  yf_cashflow_NVDA.csv             4 KB
  yf_income_AAPL.csv               2 KB
  yf_income_NVDA.csv               3 KB

0.3 中文字体自检¶

matplotlib 默认不带中文字体,画图时中文会变成一串方框 □□□。 D.setup_matplotlib() 已经在引导 cell 里自动挑好了可用的中文字体(本机是 Noto Sans CJK SC)。

下面画一张测试图确认中文 + 负号都正常:

In [3]:
fig, ax = plt.subplots(figsize=(8, 3.2))
x = np.linspace(-3, 3, 100)
ax.plot(x, x**3 - 2*x, lw=2, color="#c0392b")
ax.set_title("中文字体自检:横轴负号也要正常显示")
ax.set_xlabel("自变量 x(含负数)")
ax.set_ylabel("函数值 y")
ax.axhline(0, color="gray", lw=0.8); ax.axvline(0, color="gray", lw=0.8)
plt.tight_layout(); plt.show()
print(f"当前中文字体: {FONT}")
No description has been provided for this image
当前中文字体: Noto Sans CJK SC

这张图在说什么:如果标题、坐标轴标签里的中文清晰可读,横轴上的负号是「-」而不是方框,说明字体配置成功,后面所有图的中文都没问题。如果你在自己机器上看到方框,去 invest_data.setup_matplotlib() 里把你系统装了的中文字体名加进 prefer 列表即可。

0.4 第一张真实图:茅台 vs 苹果的「股价走势」¶

光说不练假把式。我们拉一段贵州茅台和苹果的真实收盘价,各自归一化到「期初=100」, 放在一张图里看走势。归一化是因为茅台一股一千多人民币、苹果一股一百多美元, 直接画没法比——统一起跑线才能比涨跌幅。

In [4]:
mt = D.load_a_price("600519")   # 贵州茅台
aapl = D.load_us_price("AAPL")  # 苹果

# 只取近 ~5 年,对齐到各自第一天 = 100
def rebase(s, n=1250):
    s = s.dropna().iloc[-n:]
    return s / s.iloc[0] * 100

mt_r = rebase(mt["close"])
aapl_r = rebase(aapl["close"])

print("茅台数据来源:", D.source_tag(mt), "| 区间:", mt_r.index[0].date(), "→", mt_r.index[-1].date())
print("苹果数据来源:", D.source_tag(aapl), "| 区间:", aapl_r.index[0].date(), "→", aapl_r.index[-1].date())

fig, ax = plt.subplots(figsize=(11, 5))
ax.plot(mt_r.index, mt_r.values, label=f"贵州茅台 600519 {D.source_tag(mt)}", color="#c0392b", lw=1.6)
ax.plot(aapl_r.index, aapl_r.values, label=f"苹果 AAPL {D.source_tag(aapl)}", color="#2c3e50", lw=1.6)
ax.axhline(100, color="gray", ls="--", lw=0.8)
ax.set_title("茅台 vs 苹果 · 收盘价走势(期初归一化 = 100)")
ax.set_xlabel("日期"); ax.set_ylabel("相对净值(期初=100)")
ax.legend()
plt.tight_layout(); plt.show()
茅台数据来源: (真实数据·本地缓存) | 区间: 2021-04-21 → 2026-06-18
苹果数据来源: (真实数据·本地缓存) | 区间: 2021-06-28 → 2026-06-18
No description has been provided for this image

这张图在说什么:

  • 两条线都从 100 出发,站得越高 = 这段时间涨得越多。比如某条线到了 200,意味着这期间翻了一倍。
  • 这就是「长期投资」最朴素的画面——买入并持有,赚的是企业价值随时间增长的钱,而不是天天猜涨跌。
  • 注意图例里标了数据来源。如果显示 ⚠️ 示例数据,说明实时和缓存都没取到,这张图只用于演示画法,别拿数值当真。

后面的章节,我们会把「为什么这条线能往上走」一层层拆开:先看企业到底赚不赚钱(财报),再看它值多少钱(估值),最后看买卖时机(K线与策略)。


本章小结¶

  • 你已经跑通了环境、确认中文字体正常、画出了第一张真实数据图。
  • 记住数据层 D 的三级降级逻辑和 ⚠️ 示例数据 标记约定。
  • 下一章 01:先想清楚一个最根本的问题——钱为什么要投出去,以及复利到底有多吓人。

免责声明:本教程为投资教育内容,所有分析与示例仅为方法演示,不构成任何投资建议。文中涉及的公司与数据仅用于教学举例,不代表推荐。市场有风险,决策需自负。