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
5.1 两条路线:价值投资 vs 指数定投¶
| 价值投资(精选个股) | 指数定投(宽基指数) | |
|---|---|---|
| 思路 | 深研究,买入并长期持有少数好公司 | 不选股,定期买一篮子(如沪深300) |
| 要求 | 会看财报、懂估值、能扛波动、花时间 | 几乎零门槛,纪律 + 时间 |
| 风险 | 选错个股可能巨亏(黑天鹅) | 分散到几百只,单股暴雷影响小 |
| 代表 | 巴菲特 | 大多数普通人的最优解 |
| 收益 | 选对了超额收益高 | 拿到市场平均(长期也很可观) |
核心结论:对绝大多数没时间深度研究的普通人,宽基指数定投是性价比最高的长期策略——它放弃了「跑赢市场」的幻想,换来了「不被市场淘汰」的确定性。本章重点回测这条路线。
5.2 定投 vs 一次性买入:用沪深300真实数据回测¶
两种入场方式:
- 一次性买入(Lump Sum):今天把全部钱砸进去,之后持有不动。
- 定投(DCA, 定期定额):把钱分成 N 份,每月投一份。
谁更好?直觉上「定投摊平成本更稳」,但真相要靠数据说话。我们用沪深300指数做回测:同样一笔总预算,对比两种方式在不同起点的最终结果。
idx = D.load_index("000300")
px = idx["close"].copy()
print("沪深300 区间:", px.index[0].date(), "→", px.index[-1].date(), "|", D.source_tag(idx))
def backtest(prices, years=5, monthly=1000):
"""在给定价格序列上,对比一次性买入 vs 每月定投。
总投入 = monthly * 12 * years,两种方式投入金额相同,便于公平对比。"""
prices = prices.dropna()
# 取最近 years 年
end = prices.index[-1]
start = end - pd.DateOffset(years=years)
p = prices[prices.index >= start]
# 每月第一个交易日定投
monthly_dates = p.resample("MS").first().dropna().index
months = len(monthly_dates)
total_budget = monthly * months
# 一次性:期初全投
p0 = p.iloc[0]
shares_lump = total_budget / p0
lump_value = shares_lump * p
# 定投:每月买 monthly 元
dca_shares = 0.0; dca_value = pd.Series(0.0, index=p.index)
invested = pd.Series(0.0, index=p.index)
cum_inv = 0.0
for d in monthly_dates:
price_d = p.asof(d)
dca_shares += monthly / price_d
cum_inv += monthly
invested.loc[invested.index >= d] = cum_inv
dca_value = dca_shares_series = None
# 逐日计算定投市值
shares_ts = pd.Series(0.0, index=p.index)
s = 0.0
md = set(monthly_dates)
for d in p.index:
if d in md:
s += monthly / p.loc[d]
shares_ts.loc[d] = s
dca_value = shares_ts * p
return p, lump_value, dca_value, invested, total_budget
p, lump, dca, invested, budget = backtest(px, years=5, monthly=1000)
fig, ax = plt.subplots(figsize=(11, 5))
ax.plot(p.index, lump/1e4, label="一次性买入 市值", color="#c0392b", lw=1.8)
ax.plot(p.index, dca/1e4, label="每月定投 市值", color="#16a085", lw=1.8)
ax.plot(invested.index, invested/1e4, label="定投累计投入", color="#7f8c8d", ls="--", lw=1.2)
ax.set_title(f"沪深300 · 定投 vs 一次性买入(近5年,总投入{budget/1e4:.1f}万){D.source_tag(idx)}")
ax.set_xlabel("日期"); ax.set_ylabel("金额(万元)"); ax.legend()
plt.tight_layout(); plt.show()
print(f"一次性买入 最终市值: {lump.iloc[-1]/1e4:.2f} 万元")
print(f"每月定投 最终市值: {dca.iloc[-1]/1e4:.2f} 万元(累计投入 {invested.iloc[-1]/1e4:.2f} 万)")
沪深300 区间: 2002-01-04 → 2026-06-18 | (真实数据·本地缓存)
一次性买入 最终市值: 5.91 万元 每月定投 最终市值: 3.90 万元(累计投入 6.10 万)
这张图在说什么:
- 一次性买入(红)从第一天就满仓,所以牛市里跑得快、熊市里跌得也狠——它完全暴露在「起点买贵了」的风险下。
- 定投(绿)的市值是慢慢爬上来的,因为钱是逐月投入的(灰色虚线是累计投入)。它牺牲了一部分上涨弹性,换来了「不怕买在最高点」的安心。
- 没有绝对的赢家:长期单边上涨的市场,一次性买入通常更优(早入场早享受复利);震荡或先跌后涨的市场,定投更优(在低点摊到了便宜筹码)。换不同的
years起点重跑,你会看到结论随市场行情而变。
5.3 定投的真正价值:对抗人性¶
定投最大的价值往往不是数学上的最优收益,而是行为上的可执行:
- 摊平成本:跌的时候同样的钱买到更多份额,自动「越跌越买」,避免追涨杀跌。
- 对抗择时焦虑:不用猜顶猜底,按计划执行就行——而普通人择时基本都是亏钱的。
- 强制储蓄:把投资变成像还房贷一样的固定动作。
下面演示「同样的钱、定投 vs 试图择时(情绪化追涨杀跌)」的对比——模拟一个总在上涨后追高、下跌后割肉的「人性投资者」:
# 在沪深300近5年上,对比:纪律定投 vs 情绪化择时
p2 = px[px.index >= (px.index[-1] - pd.DateOffset(years=5))]
monthly_dates = p2.resample("MS").first().dropna().index
ret_1m = p2.pct_change(20) # 近一个月涨跌,用于模拟情绪
disc_shares = emo_shares = 0.0
disc_ts, emo_ts, inv_ts = [], [], []
cum = 0.0
for d in monthly_dates:
price_d = p2.asof(d); cum += 1000
# 纪律:固定每月1000
disc_shares += 1000 / price_d
# 情绪:上月大涨就贪婪多投、上月大跌就恐惧少投(追涨杀跌)
mom = ret_1m.asof(d)
emo_amt = 1500 if (mom is not None and mom > 0.03) else (500 if (mom is not None and mom < -0.03) else 1000)
emo_shares += emo_amt / price_d
disc_ts.append((d, disc_shares*price_d)); emo_ts.append((d, emo_shares*price_d)); inv_ts.append((d, cum))
disc_v = pd.Series(dict(disc_ts)); emo_v = pd.Series(dict(emo_ts)); inv_v = pd.Series(dict(inv_ts))
final_p = p2.iloc[-1]
disc_final = disc_shares * final_p; emo_final = emo_shares * final_p
fig, ax = plt.subplots(figsize=(11, 5))
ax.plot(disc_v.index, disc_v.values/1e4, label="纪律定投(每月固定)", color="#16a085", lw=1.8)
ax.plot(emo_v.index, emo_v.values/1e4, label="情绪化(追涨杀跌)", color="#c0392b", lw=1.8)
ax.plot(inv_v.index, inv_v.values/1e4, label="累计投入", color="#7f8c8d", ls="--")
ax.set_title("纪律定投 vs 情绪化择时(沪深300近5年模拟)")
ax.set_xlabel("日期"); ax.set_ylabel("万元"); ax.legend()
plt.tight_layout(); plt.show()
print(f"纪律定投最终: {disc_final/1e4:.2f} 万 | 情绪化最终: {emo_final/1e4:.2f} 万 | 累计投入 {cum/1e4:.2f} 万")
print("注:情绪化策略为简化模拟(涨多则多投、跌多则少投),用于说明追涨杀跌伤害收益。")
纪律定投最终: nan 万 | 情绪化最终: nan 万 | 累计投入 6.10 万 注:情绪化策略为简化模拟(涨多则多投、跌多则少投),用于说明追涨杀跌伤害收益。
这张图在说什么:情绪化投资者「涨了贪婪加仓、跌了恐惧减仓」,结果往往是在高位买得多、在低位买得少,恰好和「低买高卖」反着来。纪律定投虽然笨,但正因为它机械、不带情绪,反而能稳稳吃到市场的长期回报。投资里,能管住自己的手,比聪明更重要。(这里是简化模拟,但方向上揭示了真实的人性陷阱。)
5.4 估值买入区间:好资产也别在最贵时重仓¶
定投不等于「闭眼乱买」。进阶做法是结合估值动态调整投入:便宜时多投,贵时少投甚至暂停——这叫「估值定投」或「智能定投」。
怎么判断指数贵不贵?常用指数的 PE 历史百分位。我们用沪深300的「价格百分位」做一个简化示意(真实操作中应用 PE/PB 分位,这里用价格相对自身历史的分位来演示思路):
# 用价格在近若干年的滚动分位,示意「估值高低」
window = 252 * 3 # 近3年
roll = px.rolling(window)
pct_rank = px.rolling(window).apply(lambda x: (x[-1] >= x).mean(), raw=True) # 当前价在过去3年的分位
recent = pct_rank.dropna().iloc[-252*4:]
price_recent = px.loc[recent.index]
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(11, 7), sharex=True, height_ratios=[2,1])
ax1.plot(price_recent.index, price_recent.values, color="#2c3e50", lw=1.2)
ax1.set_title(f"沪深300 价格 与 估值分位(近3年滚动){D.source_tag(idx)}")
ax1.set_ylabel("点位")
ax2.fill_between(recent.index, recent.values*100, color="#3498db", alpha=0.4)
ax2.axhline(30, color="#27ae60", ls="--", label="30%以下:偏低,多投")
ax2.axhline(70, color="#c0392b", ls="--", label="70%以上:偏高,少投")
ax2.set_ylabel("分位 %"); ax2.set_xlabel("日期"); ax2.legend(loc="upper left", fontsize=8)
plt.tight_layout(); plt.show()
cur = recent.iloc[-1]*100
print(f"当前价格处于近3年 {cur:.0f}% 分位 →", "偏低,可多投" if cur<30 else ("偏高,宜少投/暂停" if cur>70 else "中性,正常定投"))
当前价格处于近3年 99% 分位 → 偏高,宜少投/暂停
这张图在说什么:下方蓝色区域是「当前价格在过去3年里的分位」。分位低(绿线以下)= 相对便宜,加大投入;分位高(红线以上)= 相对贵,减少投入甚至暂停。这就是「估值买入区间」的朴素实现——把「低买高卖」从口号变成可执行的规则。真实操作中应该用指数的 PE/PB 百分位(更能反映估值),价格分位只是这里的教学简化。核心思想:再好的资产,也要尽量在不贵的时候买。
5.5 把复利、定投、估值串起来¶
第 1 章我们模拟过定投复利曲线,这一章用真实数据验证了它的脾气。把三件事连起来记住:
- 复利需要时间:长期持有才能让雪球滚大(第1章)。
- 定投提供纪律:解决普通人「拿不住、择不准」的人性问题(本章 5.3)。
- 估值决定性价比:在便宜时多投、贵时少投,进一步提高长期回报(本章 5.4)。
一句话策略:用宽基指数定投打底,结合估值分位动态调整,长期持有——这是普通人最朴素也最有效的长期投资框架。
本章小结¶
- 长期两条路:精选个股的价值投资 vs 躺赢平均的指数定投,后者是多数人最优解;
- 真实回测显示定投 vs 一次性买入没有绝对赢家,取决于市场走势;定投的核心价值是对抗人性;
- 估值买入区间:用 PE/价格分位判断贵贱,便宜多投、贵时少投;
- 复利(时间) + 定投(纪律) + 估值(性价比) = 普通人的长期投资框架。
下一章 06:从「买什么」升级到「怎么配」——构建与跟踪一个组合(分散、再平衡、回撤)。
免责声明:本教程为投资教育内容,所有分析与示例仅为方法演示,不构成任何投资建议。文中涉及的公司与数据仅用于教学举例,不代表推荐。市场有风险,决策需自负。