报告里哪些数字是化过妆的
- 认得出六种常见的报告美化手法:挑时间段、换基准、只报一头的收益口径、曲线画法、剔除「异常」交易、费用假设偏乐观
- 说得出每一种手法藏起来的是哪一个「选择」,以及它为什么能骗过一个认真看报告的人
- 学会用「这份报告有没有把没算进去的部分单独列出来」这一条反向信号,去衡量做报告的人诚不诚实
有人发给你一份策略业绩报告。你把它从头看到尾,认真看的那种——曲线看了,年化看了,回撤也看了。看完你觉得这东西挺靠谱。
三个月后你发现自己判断错了。你回头再翻那份报告,一行一行找,想找出对方在哪儿撒了谎。
你找不到。因为很可能一句谎都没有。每个数字都是真算出来的,每张图都是真画出来的,甚至连回撤那一栏都老老实实填了个不小的数。
这就是我想讲的那件事:一份报告要把你带偏,根本不需要编数字。它只需要做一连串选择,然后不告诉你它选了什么。从哪天开始算、跟谁比、用哪种口径报收益、曲线的纵轴怎么画、哪几笔交易算数、费用按谁的价格填——每一样都是一个岔路口,每一样都有一个「让成绩更好看」的方向。而这些选择做完之后,报告上呈现出来的仍然是一堆真实的、经得起复核的数字。
化妆和整容不一样。整容会留疤,化妆不会。化过妆的数字,每一个单独拿出来查都是对的。
下面六种手法,是我认为最值得你先认出来的。为了不跟旁边两篇打架,这里先说清分工:拿到一份报告该按什么顺序看,在 拿到一份策略业绩报告,先看哪几个地方;看完之后该开口问什么,在 看到「年化 30%」,你该问出哪五个问题。这一篇只做一件事:认脸。 认出手法长什么样、它藏起了哪个选择、以及它为什么骗得到一个认真的人。
先立一个贯穿全文的说法。你在看报告的时候,脑子里默认有一个假设:眼前这些数字,是被「客观地算出来」的。 六种手法全都在利用这个假设。它们真正的杀伤力不在于把数字改大了多少,而在于让你误以为这里根本没有人做过选择。
手法一:挑时间段,把最难看的那一年挪到镜头外
先打个比方
朋友圈里那种减肥前后对比照,你一定见过。左边那张,穿着宽松的旧衣服、饭后、灯从下往上打、没吸气;右边那张,换了合身的衣服、空腹、顶光、站直。
两张照片都没修图。同一个人,同一个身体。骗你的不是像素,是这两个时刻是从几百个时刻里挑出来的。
这对你意味着什么
一份业绩报告的开始日期和结束日期,看起来最像「客观事实」的两个数——「过去五年」「2019 到 2024」,读起来像是天经地义的一段历史。
但它是选的。而且这个选择的杠杆大得惊人。把起点往后挪三个月,可能就把某一次最惨的下跌整段挪出了统计窗口;把终点定在某个阶段性高点上,那条曲线就停在了它最漂亮的地方。回撤(账户从最高点往下掉了多少)这个数尤其脆弱,因为它只由历史上最惨的那一次决定——只要那一次不在窗口里,报告上的回撤就是另一个数量级。
更隐蔽的一层:一段特定的历史,本身就有它的性格。某几年是持续上行的,某几年是来回震荡的。一套只在上行行情里能活的方法,只要报告的时间窗恰好盖住那几年,它看起来就是全天候的。你以为你在看一套方法在「历史」上的表现,其实你在看它在「某一段被挑出来的历史」上的表现。
它的机制,和它骗人的地方
时间段在真实系统里就是一行参数,改起来毫无成本。
freqtrade 是一个公开的自动交易框架。它的回测命令有个 --timerange 开关,文档里把用法列得清清楚楚:只用某个日期之前的数据、只用某个日期之后的、或者掐头去尾指定一段。改这个开关不需要动策略一个字。
qlib 是另一套公开的量化研究框架。它把数据切分写在配置文件里,示例配置中训练段、验证段、测试段三段的起止日期是三行明明白白的文本。这种写法本身是好事——把选择写出来,就是把它交给人质疑。问题在于,配置文件通常不会跟着报告一起发给你。
它为什么骗得到人?因为日期看起来不像一个选择,看起来像一个事实。你会去质疑「年化 30% 是怎么算的」,但很少有人会停下来问「为什么是从这一天开始」。而在所有可调的旋钮里,这一个几乎是最省力、效果最猛的。
顺带说一句,这件事和「用同一段历史反复调参数直到好看为止」是两个问题,虽然它们经常一起出现。后者是样本内与样本外那一层的事,讲的是规律怎么被历史噪音磨合身;这里讲的是更前面一步——连这段历史本身都是挑的。
手法二:换基准,找一个更弱的对手站在旁边
先打个比方
孩子拿回来一张 90 分的卷子。你要不要高兴,取决于旁边那个数是什么。班级平均 95,这 90 分是坏消息;班级平均 72,这 90 分是好消息。
现在假设孩子有权决定拿哪个班的平均分给你看。
这对你意味着什么
投资里那个「班级平均」叫基准——就是「假如我什么聪明事都不干,用最省事、最公开的方式参与这个市场,我能拿到多少」。你的收益减去基准收益,剩下那一截叫超额收益,那才是真正属于做这件事的人的部分。
关键在于:减数是他自己挑的。 挑一个更弱的对手站在旁边,超额收益就凭空变胖,而你的收益那一栏一个数字都没动。
几种常见的挑法:拿一个整体表现平平的宽泛指数,去比一套只做某个热门方向的方法;拿一个不含分红的价格指数,去比一个把分红算进去的账户;或者干脆不设基准,只报绝对收益——不设基准是最省事的一种换基准,等于把参照物直接从画面里拿掉,让你无从比较。
反过来那一面也一样要小心:报告里出现了「基准」两个字,不代表这个比较是公平的。事实上,一份写了基准的报告比一份不写的更容易让你放松警惕,因为它看起来已经做过这道功课了。
基准该怎么选、超额收益有哪几种算法,基准与超额收益 那篇把判据讲得很细,这里不重复推导。这里只留一句给读报告的人:你看到的每一个超额数字背后,都站着一个你没见过面的对手。
它的机制,和它骗人的地方
三套真实系统对「基准」这两个字的理解完全不同,这本身就说明了它有多可塑。
qlib 把基准做成配置项——它的示例配置里,基准是一行指数代码。想换?改那一行就行。
freqtrade 面对的是数字货币市场,那里没有一个被广泛接受又能低成本买到的宽基指数。于是它给了个务实的答案:报告里有一项叫 Market change,文档的定义是**「回测期内所有交易对,从第一根到最后一根 K 线涨跌幅的平均值」**。注意这句话的含义——你在配置里挑了哪几个标的,就等于同时定义了你的基准。挑标的这个动作,一次性影响了比较的两边。
Vibe-Trading 是一套要同时应付股票、数字货币、期货、外汇的系统。它维护一张「市场类型对应哪个默认基准」的表,而外汇那一行的值是空的,代码里给的理由是没有普适基准。承认「这里没有合适的尺子」,比硬塞一把不合适的诚实得多。
它为什么骗得到人?因为减法这个动作太像客观运算了。你看到「超额 12%」,大脑处理的是「12」这个结果,不会自动展开成「12 = 我的收益 − 某个我没看见的东西」。减法的两个数里,只有一个被摆在你面前。
手法三:只报一头的收益口径
先打个比方
两个人都跟你说「我瘦了二十斤」。
一个用了三个月,一个用了六年。这两句话在字面上完全相同,在信息量上差着一个数量级。
反过来也成立。有人说「我上周瘦了两斤」,你要是把这个速度往一年上外推,会得到一个不可能的数——但如果他不告诉你那是一周的数据,只把外推的结果报给你,听起来就相当惊人。
这对你意味着什么
收益有两种常见口径,报哪一种是一次选择:
累计收益,就是从头到尾一共赚了百分之多少。这个数在长周期上会自然变得很大——因为它把很多年攒在一起了。「累计 300%」听着像神话,摊到十二年,每年大约是十二个点出头(这里只是让你感受一下量级,具体换算你可以用复利计算器自己拨两下)。
年化收益,就是把这段时间的成绩折算成一年的速度。它把时间这个分母还给了你,所以更适合横向比较。但它在短周期上会往反方向失真:一段两个月的成绩折算成一年,等于假设这个速度能一直保持下去,而两个月里发生的事很可能只是运气的一次抖动。
于是一份报告有了一个很舒服的选择空间:长周期就报累计,短周期就报年化。哪种更唬人报哪种,两种都是合法算法,两种都算得对。
真正的问题是那个共同的缺失项:期限。只要不明说这段成绩跑了多久,两种口径都可以脱离约束。
它的机制,和它骗人的地方
freqtrade 的回测报告里,累计和年化是并列的两行——一行是总收益百分比,一行是复合年增长率(也就是年化)。它的文档里有一段示例输出,同一份报告的这两行分别是 5.72% 和 92.41%(这是文档里用来演示格式的示例数据,不是任何人的实盘成绩,我也没有跑过这套程序)。
我想让你看的不是这两个数本身,而是它们的比值。一个五个多点的总收益,能被折算成一个九十多点的年化数字,唯一的原因是那段回测的时间窗很短。同一份成绩单,两行数字,一行让人打哈欠,一行让人心跳加速。
这件事在源码里还有一个更有意思的旁证。freqtrade 里算年化的那个函数,专门写了一段溢出保护,注释直白地说:在很短的时间窗上外推一个很大的涨幅,结果可能超出浮点数能表示的范围。
停一下想想这句话的分量。一个负责算「年化」的函数,需要防备的不是算错,而是算出来的数大到计算机存不下。 这就是短窗口外推的荒唐程度——它不是「有点乐观」,它可以荒唐到需要工程上的护栏。
它为什么骗得到人?因为人对「时间」这个分母天生不敏感。收益率那个百分号会直接进入你的情绪系统,而「这跑了多久」需要你主动去找、去算。前者是本能,后者是功课。
顺带提一句:一份诚实的报告不会只给你一个汇总数。freqtrade 支持把成绩按日、按周、按月、按年拆开看,甚至能按星期几拆。能拆开看的成绩,和只能整块看的成绩,可信度不是一回事。
手法四:曲线怎么画,也是一次选择
先打个比方
同一段山路,摊在两张地图上。一张比例尺大,弯道看着惊心动魄;一张比例尺小,整段路变成一条几乎笔直的线。
路没变。你对这条路难不难走的判断,变了。
这对你意味着什么
你看资金曲线的时候,其实在做一件很粗糙的事:用眼睛量像素高度。那个坑看着深不深、那段横盘看着长不长——你判断的是图上的距离,不是百分比。
而图上的距离取决于纵轴怎么画。
纵轴按等差刻度画(也就是最常见的那种,刻度是 100、200、300),一次早期的下跌几乎看不见——账户从 100 掉到 70,在一张最高标到 1000 的图上只是一道浅浅的划痕。可那是实实在在的三成。反过来,同样是三成,发生在 1000 那个高度上,图上就是一大块塌方。等差刻度会系统性地放大后期的波动、抹掉早期的波动。
纵轴按等比刻度画(也就是对数坐标,刻度是 100、1000、10000),情况反过来:涨了同样的倍数就占同样的高度,所以早期那三成和后期那三成看起来一样深,这在判断百分比变化时其实更公道。代价是,当整张图的跨度很大时,任何一次回撤都会被压扁——十倍的总跨度里,一次三成的下跌只占一小截,曲线看上去就是一条平缓上行的斜线加几个小毛刺。
两种画法各藏一头,都不算造假。真正的问题是:很多图根本不标注自己用的是哪一种,而你也不会去看。
它的机制,和它骗人的地方
比坐标轴更隐蔽的,是曲线本身怎么累计出来的。
qlib 在做绩效分析时,提供了两种把逐日收益攒成一条曲线的方式:一种是把每日收益相加,一种是把每日收益连乘。源码里有一句注释,我读到的时候觉得非常值钱——它说 qlib 倾向于用求和而不是连乘来累计,为的是避免累计曲线被指数级地扭曲。
这句话的意思是:同一串真实的日收益数据,两种累计方式会画出两条形状不同的曲线,而两条都不是错的。连乘那条在后期会翘得更厉害,回撤在视觉上也被拉扯得不成比例。
我把这一条放进「化妆手法」里,不是说 qlib 在化妆——恰恰相反,它把这个选择写进了注释里,还给了你切换的开关。我要说的是:连「怎么把收益攒起来」这种听上去纯技术的事,都有一个不唯一的答案,而不同的答案会改变你看图时的第一感觉。
它为什么骗得到人?因为图比数字更早进入大脑。你还没读到「最大回撤」那一栏,眼睛已经先给出判断了。而且坐标轴、累计口径这些东西,属于「没人想到要去核」的类别——它们看起来是画图软件的默认设置,不像是谁做的决定。
想真正把一条曲线看明白,怎么看一条收益曲线 和 回撤恢复期 那两篇比这里细得多。特别是后者:一张图上最难被目测出来的东西,就是「在水下待了多久」——那是一段横向的距离,而人的眼睛只对纵向的落差敏感。
手法五:剔除「异常」交易
先打个比方
一个学生给你看成绩单,一边看一边解释:「这次数学 40 分,那天我发烧了,不算。这次物理没考,家里有事。」
你听着,每一条理由单独都成立。可当你回过神来,会发现一件事:他从来不会因为「那天状态特别好」而剔除一次高分。
理由不是假的。理由是单向的。
这对你意味着什么
策略报告里的剔除通常穿着更专业的外衣:那笔是数据错误、那段是极端行情不具代表性、那次是接口故障导致的误操作、那几笔是测试期的。
问题从来不在于某一条理由站不站得住,而在于三件事:
第一,剔除的方向是单向的。 亏钱的交易总有一个故事可讲,赚钱的交易从来不需要解释。你几乎不会看到有人说「那笔特别赚的,是运气,剔了」。
第二,被剔掉的常常正是最有信息量的部分。 极端行情下的表现,恰恰是你最该知道的——因为那正是你真金白银时最可能受伤的时刻。把它们当成「不具代表性」拿掉,等于把体检报告里唯一那项异常指标划掉,然后宣布一切正常。
第三,也是最容易漏的:有些交易不是被剔除的,是从来就没被记进去的。 比如在报告结束那一刻手上还没平掉的仓位;比如信号发出来了但因为已经满仓而没能执行的那些。这些不在「剔除」的清单上,因为它们压根没进过清单。
这和幸存者偏差是同构的:你看到的样本,是经过一道你看不见的筛子筛过的。 区别只是那篇讲的是标的名单被筛,这里讲的是交易记录被筛。
它的机制,和它骗人的地方
这一节我想反过来讲——不讲怎么剔,讲成熟系统怎么处理「没算干净的部分」,因为这给了你一个特别好用的对照物。
freqtrade 的回测报告里,回测结束那一刻还没平仓的持仓会被强制按当时价格平掉,然后单独列成一张表。文档给的理由是:为了呈现完整的图景。它没有把这些交易混进主表悄悄稀释,也没有把它们删掉,而是摆在旁边让你自己看。
同一份报告里还有一项,叫被拒绝的入场信号——统计的是那些本来触发了、但因为同时持仓数量已经到上限而没能执行的信号。这是一个「没发生的事」的计数器。 一份报告愿意为「没发生的事」留一栏,态度已经写在设计里了。
qlib 那边有个相关但性质不同的例子。它在做特征标准化时,有一个默认打开的裁剪开关,会把标准化之后超出正负三倍的数值压回到边界上(这是我读到的快照版本里的默认行为,你手上那个版本以实际为准)。这不是造假,是建模里很常规的做法,为的是不让极少数极端值主导整个模型。但它有个副作用值得你知道:在这套流程里,极端行情被压平过一次。 所以当有人说「我这套方法连那种行情都扛住了」,你至少该意识到,「那种行情」在模型眼里长什么样,本身就是一个被处理过的问题。
它为什么骗得到人?因为剔除是带着理由出现的,而理由触发的是你的理解,不是你的警觉。有人跟你解释「这笔不算,因为当时接口出问题了」,你的第一反应是「哦,那确实」,而不是「你一共剔了几笔、剔掉的那些加起来是赚是亏」。
手法六:费用假设填得太漂亮
先打个比方
你在纸上算一门网店生意:进货十块,卖二十块,一件赚十块,一天卖五十件。算得挺清楚,数学没错。
真做起来才发现:运费、包装、退货、平台抽成、售后寄回。这些你不是算错了,是根本没往表里填。
更微妙的一种情况是:你填了。你在表格里写了「运费:一件两块」——然后就安心地把这一项勾掉了,再也没想过那个「两块」是从哪来的。
这对你意味着什么
这是六种手法里最特别的一种,因为它是唯一一个「报告确实填了一个数」的化妆。
前五种手法靠的是不说:不说时间段怎么选的,不说基准是谁,不说跑了多久,不说坐标轴是哪种,不说剔了几笔。而费用这一项,报告上通常明明白白写着一个费率。你看到那个数字,心里就把这一项划掉了——它算过了。
可算过不等于算对。要命的地方在于:
费用是按次收的,一次买卖要收两遍(买一遍、卖一遍)。所以「单次成本万分之几」这个数在一笔完整来回里要翻倍。
费用是乘在操作次数上的,不是从总收益里减一次。 一套一年调仓两次的方法,一年只付四次;一套一周动两次的方法,一年要付两百多次。同样把费率抬高一点点,前者纹丝不动,后者可能整条曲线被压平。换手(一段时间里你把仓位翻来覆去换了多少遍)越频繁,一个偏乐观的费率假设给它的美颜滤镜就越厚。
还有一层根本没在费率那一栏里:成交价本身。 报告默认「你想按这个价成交就能按这个价成交」——不排队、不被拒、不影响价格。freqtrade 在它的「回测所做的假设」那一节里把这条写得毫不含糊:只要价格落在那根 K 线的最高最低之间,所有订单都按你要的价格全额成交,没有滑点(滑点就是你想按这个价成交、真成交时价格已经跑偏了那一点差额)。这条假设写出来了,所以可以被质疑;没写出来的报告里,它同样存在。
它的机制,和它骗人的地方
回测、参数搜索、模拟盘这几种模式在费率上共用什么假设,以及不同市场的费用结构差多远,回测按贵宾价算账,实盘按你的真实价算账 那篇专门讲这件事;成本这个东西一共包含几件性质不同的账(费率档位、滑点、自己把价格推走、最低收费、买卖不对称),回测里的交易成本假设 拆得更细。这里我只补一句读报告的人该有的直觉。
「我已经设了手续费」和「我已经算了成本」是两句完全不同的话。 手续费是这几件事里唯一明码标价、也唯一最容易算的那件。剩下几件——你的单子把价格推走的那部分、小单踩最低收费、买卖两头不对称——加起来往往比手续费本身还大,而且它们不会出现在任何一张账单上。
它为什么骗得到人?因为有数字比没数字更让人放心,哪怕那个数字来路不明。一份报告写着「手续费按万分之三计」,你的注意力就从这一栏移开了。空白会引起追问,一个具体的数字反而会终止追问。这是所有化妆手法里最反直觉的一条:填了一个数,比留一个空,更能让人不再深究。
六种手法串起来看:它们其实是同一件事
把六种并排放一下,你会发现它们的骨架完全一样。
| 手法 | 被藏起来的那个选择 | 谁最容易被它骗 |
|---|---|---|
| 挑时间段 | 起止日期是从很多种可能里选的 | 觉得「过去五年」是客观事实的人 |
| 换基准 | 减法里那个减数是自选的 | 看到「超额」两个字就放松警惕的人 |
| 只报一头的口径 | 这段成绩到底跑了多久 | 对时间这个分母不敏感的人(几乎是所有人) |
| 曲线画法 | 纵轴刻度和累计方式 | 习惯用眼睛目测坑有多深的人 |
| 剔除「异常」 | 剔了几笔、方向是不是单向的 | 会认真听理由的人 |
| 费用填得漂亮 | 那个费率是谁的价、成交价怎么假设的 | 看到具体数字就觉得算过了的人 |
第二列是这张表的关键。六行全都是「有一个选择被做了,但没被说出来」。 没有一行需要造假。
这也解释了为什么这些手法特别难防:你的警觉是冲着「假数字」去的,而这里根本没有假数字。你查每一个数,每一个都对。
那有没有一条不靠追问就能用的判据?我给你一条,它来自前面所有那些系统的共同做法:
看这份报告有没有主动把「它没算进去的部分」单独列出来。
回想一下这一篇里出现过的几个例子。回测结束时还没平的仓位,被单独列成一张表而不是混进去。因为满仓而没能执行的信号,专门有一个计数器。超额收益被拆成扣成本和不扣成本两行分开报。外汇那一栏的基准直接写「没有」,而不是硬塞一个。回测所做的假设被逐条列成清单,包括那条最不利的「假设没有滑点」。
这些都不是在炫耀优点,全是在主动交代自己的缺口。
反过来就是那条判据:一份从头到尾只有优点、没有任何一句「本报告未能覆盖」的成绩单,本身就是最大的警号。一个人愿不愿意说出自己方法的边界,比他报出来的那个年化数字更能说明他的水平。
这一层判断和整卷的入口是同一个思路,回测好看实盘亏,差的到底是哪三件事 那篇讲的三处结构性差异,本质上也是「有没有被测量、有没有被披露」。
本篇讲的是怎么识别报告里的美化手法,不构成任何投资建议、买卖信号或收益承诺。把这六种手法全都识别出来,也只是让你少被带偏一点,它不能帮你判断一套方法未来会不会赚钱。 任何回测成绩都建立在一整套假设之上——回测不等于实盘,一份数字干净的报告依然不能预测未来。文中涉及的所有源码与文档说明,均来自上述本地快照版本的阅读,不是运行结果;具体行为与数值请以你手上的版本、你的券商和当时的政策为准。完整风险提示见 免责声明。
小结
- 一份报告要把你带偏,不需要编数字。它只需要做一连串选择,然后不告诉你选了什么。化过妆的数字,每一个单独查都是对的。
- 挑时间段:起止日期看起来像客观事实,其实是所有旋钮里最省力、效果最猛的一个。回撤这个数尤其脆弱——它只由最惨的那一次决定,只要那一次不在窗口里,数就完全不同。
- 换基准:超额收益是一道减法,而减数是对方自己挑的。你面前只摆着一个数,另一个从没露面。不设基准,是最省事的一种换基准。
- 只报一头的口径:长周期报累计、短周期报年化,两种都合法。共同的缺失项是期限。一个负责算年化的函数需要加溢出保护,就是短窗口外推荒唐程度的注脚。
- 曲线画法:你看图是在用眼睛量像素高度。等差刻度抹掉早期波动,等比刻度压扁所有回撤,连「怎么把日收益攒成一条线」都有不止一个正确答案。
- 剔除「异常」:每条理由单独听都成立,但方向是单向的——亏的总有故事,赚的从来不是意外。还有一类交易不是被剔除,是从来没被记进去。
- 费用填得漂亮:唯一一种「确实填了个数」的化妆。填了一个数,比留一个空,更能让人不再深究。而成本是乘在操作次数上的,换手越频繁,滤镜越厚。
- 一条不用追问就能用的反向信号:诚实的报告会主动列出自己没算进去的部分。 只有优点、没有一句「这里我覆盖不到」的成绩单,本身就是最大的警号。
一句话说完这篇:看成绩单的时候,别光盯着上面写了什么,多想想是谁决定了哪些东西可以不写。
本文为投资教育整理,关键数据与结论请结合下列权威来源验证。
- freqtrade 文档 docs/backtesting.md(本地仓库快照 commit b3404c9,2026-08-18 读取):--timerange 说明、示例报告表格与字段释义、Assumptions made by backtesting、--breakdown 说明 ↗
- freqtrade 源码 freqtrade/data/metrics.py 的 calculate_cagr、freqtrade/optimize/optimize_reports/optimize_reports.py 的 generate_periodic_breakdown_stats(同上快照) ↗
- qlib 源码 qlib/contrib/evaluate.py 的 risk_analysis(sum / product 两种累计模式及其注释)、qlib/data/dataset/processor.py 的 RobustZScoreNorm(本地仓库快照 commit 79633dd,2026-07-23 读取) ↗
- qlib 示例配置 examples/benchmarks/LightGBM/workflow_config_lightgbm_Alpha158.yaml(同上快照) ↗
- Vibe-Trading 源码 agent/backtest/benchmark.py(本地仓库快照 commit 3a752d5,2026-08-04 读取) ↗