← 返回目录
q1.10动手⏱ 约 10 分钟

绩效评估:看懂数字不被骗

年化、回撤、夏普,以及成本这只看不见的手

🔎 最后验证 2026-07📚 来源:夏普比率(William F. Sharpe, 1966)、本节全部数字于 2026-07 实测(沪深300 2005-04-08 起,5/20双均线满仓模型)🧰 pandas、numpy
为什么学这个

q1.8 的成绩单你已经会读一半了;q1.9 结尾我又留了一个问题:佣金从 0.05% 涨到 0.1%,这个策略会怎样?

今天把答案摆上桌——顺便教你绩效评估的三件套(年化、回撤、夏普)。剧透两个扎心结论:

  1. 成本升到 0.2% 时,这个策略被「什么都不做」反超——21 年的忙碌,输给了躺平。
  2. 同一个策略,本节的简化回测算出 724%,q1.8 的 backtrader 算出 359%——差了一倍。这不是谁错了,而是又一课。
💡 打个比方

评估一个策略只看收益率,就像招聘只看「最高月薪」:他确实拿过 10 万月薪(收益),但你还得问——为拿到它他连续加了几个月班(回撤,扛了多少痛苦)?平均下来时薪多少(夏普,单位辛苦换多少钱)?通勤补贴要自己出多少(成本)?

四个问题都问完,才算看懂一份成绩单。

一、三件套:一段代码全算出

继续用老实版双均线(满仓 1/0 模型),这次把成本做成参数:

import pandas as pd
import numpy as np

df = pd.read_csv("csi300.csv", parse_dates=["date"]).set_index("date").sort_index()
close = df[df.index >= "2005-04-08"]["close"]
ret = close.pct_change().fillna(0)
pos = (close.rolling(5).mean() > close.rolling(20).mean()).astype(int).shift(1).fillna(0)
years = len(close) / 243                      # 每年约243个交易日

def report(name, r_series):
    eq = (1 + r_series).cumprod()                        # 净值曲线
    total = eq.iloc[-1] - 1                              # 累计收益
    annual = eq.iloc[-1] ** (1 / years) - 1              # 年化收益(复利折算)
    max_dd = (eq / eq.cummax() - 1).min()                # 最大回撤(距历史最高点的最深跌幅)
    sharpe = r_series.mean() / r_series.std() * np.sqrt(243)  # 夏普(简化版,未扣无风险利率)
    print(f"{name}: 累计{total*100:6.1f}% 年化{annual*100:5.2f}% 回撤{max_dd*100:6.1f}% 夏普{sharpe:.2f}")

for fee in [0, 0.0005, 0.001, 0.002]:
    net = ret * pos - fee * pos.diff().abs().fillna(0)   # 每次进出场都付一次费
    report(f"费率{fee*100:.2f}%", net)
report("买入持有  ", ret)                                 # 对照组,必须有
print("换手(单边)次数:", int(pos.diff().abs().sum()))

三个指标的人话版:年化=把总收益折算成「相当于每年复利多少」;最大回撤=净值从最高点最深摔了多少(你要扛的最大痛苦);夏普=每承担一单位波动,换来多少收益(性价比)。

二、成本敏感性:看不见的手,摸得见的账单

2026-07 实测(312 次单边换手):

单边费率累计收益年化最大回撤夏普
0%(幻想)724.5%10.41%-35.0%0.67
0.05%605.5%9.60%-35.4%0.63
0.10%503.6%8.80%-36.5%0.58
0.20%341.7%7.22%-44.7%0.50
买入持有(对照)358.4%7.41%-72.3%0.41

读出三件事:

  1. 成本是复利的反面:费率每加 0.05%,年化掉约 0.8 个百分点——312 次换手,每一次都在给券商打工。换手越勤的策略,被成本杀得越狠(高频策略的成本敏感性比这夸张得多)。
  2. 0.2% 时被躺平反超:年化 7.22% 输给买入持有的 7.41%。加上滑点、冲击成本、基金费率,真实世界的总成本奔着 0.2% 去并不难——很多回测里的「优势」,实盘里第一个死于成本
  3. 风险调整后仍有价值:即便 0.2% 费率,夏普 0.50 仍高于买入持有的 0.41,回撤 44.7% 也小于 72.3%——再次印证 q1.8:这类策略的价值是「少挨跌」,不是「多赚钱」。看收益它输了,看性价比它还站着——这就是为什么专业评估必看夏普。

三、724% vs 359%:同一策略,为何两个答案

细心的你该拍桌子了:q1.8 backtrader 算出 359%(0.05% 佣金),本节同费率算出 605%,差距巨大。都没错——差异全在实现细节:q1.8 用 95% 仓位、按整数份额买、指标预热期空仓;本节是理想化的满仓比例模型。

这就是本节最值钱的一课:「回测收益」从来不是一个客观数字,它是一堆假设的函数。下次任何人给你报收益率,除了 q1.9 教你的「样本外验过吗」,还要再补一问:「仓位、成本、执行,是怎么假设的?」——两问出手,九成的吹嘘当场卡壳。

⚠️ 避坑⚠️ 坑一:「年化」是数字里最会化妆的一个

「我这策略一个月赚了 8%,年化 152%!」——把短期收益复利外推成年化,是最流行的数字化妆术。

一个月 8% 可能只是碰上了顺风行情;外推成年化,等于假设「每个月都这么顺」——q0.2 的幸存者偏差换了身衣服。年化只对足够长的实测区间有意义(本节是 21 年);低于一年的「年化」,当广告词处理。

⚠️ 避坑⚠️ 坑二:夏普也不是万能钥匙

夏普高≠安全。它的软肋:① 把「向上的波动」也当风险惩罚(暴涨会拉低夏普,冤枉);② 对肥尾不敏感——一个每天稳赚一点、十年崩一次的策略(想想 q0.5 的 LTCM),崩盘前夏普可以漂亮得惊人。

所以专业评估从不单看任何一个指标:年化(赚多少)+ 回撤(多痛)+ 夏普(性价比)+ 成本敏感性(经不经得起摩擦),四件套一起上——这也是你以后审视任何产品宣传页的清单。

❓ 测验
某策略宣传:「回测年化 12%,夏普 1.2」。用本节的框架,下面哪组追问最致命?
✏️ 填空
夏普比率的人话版:每承担一单位 ___ ,换来多少收益——它衡量的是性价比,不是绝对收益。

📌 免责:本课为技术科普,全部数字为历史模拟且依赖简化假设,不代表实盘与未来,不构成任何投资建议;投资有风险,盈亏自负。

✅ 小结

这一节你集齐了绩效四件套:年化(警惕短期外推)、最大回撤(你要扛的痛苦)、夏普(性价比,但防肥尾)、成本敏感性(0.2% 就能让策略输给躺平)。外加两记杀手锏追问:样本外验过吗?假设是怎么定的?

数字的部分到此告一段落。接下来,把你在 q0.3、q0.6 认识的那位「超级研究实习生」正式请进工作流。

下一节,用 DeepSeek API 批量读公告:几行代码,让 AI 按固定格式输出摘要、情绪标签——并且强制它引用原文作为证据(治幻觉的缰绳)。你会看到它把两条「利好利空混杂」的公告拆解得明明白白,也会看清它的输出为什么只能当研究参考、不能当交易信号

下一节 → LLM 辅助研究:让 DeepSeek 批量读公告
🔎 来源与核验· 3 条,点开核对
本节每个关键论断都对应一个可追溯的来源 —— 这是本课程"靠谱、不过时"的底线。
「双均线满仓模型(沪深300 2005-04-08起,312次单边换手)成本敏感性:费率0/0.05%/0.1%/0.2%对应年化10.41%/9.60%/8.80%/7.22%,夏普0.67/0.63/0.58/0.50;买入持有年化7.41%、回撤-72.3%、夏普0.41」
📚 本节 2026-07 实测✓ 已核验 2026-07
「同一策略因仓位/整数份额/预热期等实现差异,backtrader 版(q1.8)总收益359.1%,满仓比例模型为605.5%(同0.05%费率)——回测结果是假设的函数」
📚 本节与 q1.8 实测对比✓ 已核验 2026-07
「夏普比率由 W. F. Sharpe 于1966年提出;对上行波动与肥尾风险存在已知局限」
📚 Sharpe(1966)及绩效评估通识✓ 已核验 2026-07
本节指标计算为教学用简化实现(夏普未扣无风险利率);所有数字仅对所述假设成立。
智图软件的赞赏码
都看到这了,打个赏呗!
接下来 · q1.11
LLM 辅助研究:让 DeepSeek 批量读公告
继续读下一节 →