50 场赢 30 和 500 场赢 300,是不是同一件事
0 两句话,一个数字
有人告诉你:“我的模型测了 50 场,命中 30 场,胜率 60%。” 另一个人说:“我的模型测了 500 场,命中 300 场,胜率 60%。”
两个 60% 长得完全一样。除一下,30 ÷ 50 = 0.6000, 300 ÷ 500 = 0.6000,一位小数都不差。 但这两句话的可信程度差得非常远, 而差别不在那个 60% 上,在你没看到的那个东西——它有多容易是碰巧。
先用硬币体会 抛一枚公平硬币 10 次,正面 6 次很常见,你完全不会因此相信它偏心。 抛 10000 次得到 6000 次正面,你会立刻断定它有问题。 同样的 60%,一个是噪声,一个是证据。
本站前四篇都在做同一件事:把评估里被含糊掉的东西算清楚。 IN-01 问“你比永远猜主胜强吗”, IN-02 把赔率翻译成概率, IN-03 证明准确率不等于赚钱, IN-04 检验报出的概率本身可不可信。 但这四篇都有一个共同的隐含前提——那些数字本身是稳的。 本文来算这个前提什么时候成立。
本文用到的数学 加、减、乘、除,以及一次开平方。没有积分,没有分布表。 真正要记的只有一件事:噪声按样本量的平方根缩小。 这一句能推出后面所有结论,包括那些看起来很贵的结论。
1 噪声有多大:标准误
假设一个模型真实胜率是 p,你让它预测 n 场。 它命中的场次会在某个数附近上下浮动, 这个浮动的典型幅度叫标准误(standard error, SE),算法只有一步:
分子 p(1−p) 度量单场结果本身有多不确定—— p = 0.5 时最大(0.25),越靠近 0 或 1 越小,因为结果越好猜。 分母是 n。关键在于这个分母在根号里面: 样本量翻 4 倍,噪声只减半,不是减到四分之一。
用 p = 0.60 算两次。50 场时 0.60 × 0.40 = 0.2400, 0.2400 ÷ 50 = 0.004800, 开根号得 0.0693。 500 场时 0.2400 ÷ 500 = 0.000480, 开根号得 0.0219。
根号惩罚 样本量放大 10 倍,噪声只缩小到 0.0219 ÷ 0.0693 = 0.3162 倍, 也就是 1 ÷ √10 = 0.3162。 这是本文所有结论的来源: 它既解释了小样本为什么不可信,也解释了把样本量做大的代价为什么这么高。
2 从标准误到置信区间
有了标准误,置信区间就是一句加减法: 观测值向两边各让出 1.96 个标准误。 1.96 对应 95% 的覆盖水平,是个查一次就能记住的常数 (想要 90% 用 1.645,99% 用 2.576)。
把开头那两句话算清楚。50 场: 1.96 × 0.0693 = 0.1358, 区间是 0.6000 ± 0.1358, 即 [0.4642, 0.7358]。 500 场:1.96 × 0.0219 = 0.0429, 区间 [0.5571, 0.6429]。
| 观测 | 胜率 | 标准误 | 95% 置信区间 | 区间宽度 | 能否排除基线 0.4205 |
|---|---|---|---|---|---|
| 30 / 50 | 0.6000 | 0.0693 | [0.4642, 0.7358] | 0.2716 | 勉强,下界 0.4642 |
| 300 / 500 | 0.6000 | 0.0219 | [0.5571, 0.6429] | 0.0859 | 可以,下界 0.5571 |
| 3000 / 5000 | 0.6000 | 0.0069 | [0.5864, 0.6136] | 0.0272 | 毫无疑问,下界 0.5864 |
基线 0.4205 取自 IN-01 实测的多数类基线, 即永远猜主胜的命中率。区间宽度 = 上界 − 下界。
看第五列。50 场的区间宽 0.2716——整整 27 个百分点。 数据只能告诉你“真实水平大概在 46% 到 74% 之间”。 46% 是个平庸模型,74% 是个足以改变生活的模型, 而这份数据无法区分这两者。 说“我的胜率是 60%”时,那个 60% 只是这段区间里的一个任意代表。
500 场把宽度压到 0.0859,5000 场压到 0.0272。 注意收窄有多慢:样本量放大 100 倍,区间只窄到十分之一。 这就是根号惩罚的账单。
该怎么报 只报一个百分比——“我的胜率 60%”——是信息不完整的表述, 因为它隐藏了样本量。正确写法是 60.00% [0.5571, 0.6429], n = 500。 多写十几个字符,读者才有办法判断这个数字值不值得当真。
3 显著性:这个差距会不会是碰巧
置信区间回答“真实水平可能在哪个范围”。 还有一个相关但不同的问法:如果这个模型其实一点本事都没有, 它碰巧打出这么好的成绩的概率有多大? 这个概率就是 p 值。
“一点本事都没有”需要一个具体的对照,我们用 IN-01 的多数类基线 0.4205。做法是先算出观测值离基线有几个标准误:
注意分母用的是 p0 = 0.4205(基线),不是观测值—— 因为我们在问“假如真相是基线”这个前提下的概率。 50 场那组算一遍:分子 0.6000 − 0.4205 = 0.1795, 分母 √(0.4205 × 0.5795 ÷ 50) = 0.0698, 相除得 z = 2.571。
z = 2.571 的意思是:观测值比基线高出 2.57 个标准误。 换成概率(正态右尾)是 0.00507, 大约 两百分之一。
| 观测 | 胜率 | z 值 | p 值(正态近似) | p 值(精确二项) | 结论 |
|---|---|---|---|---|---|
| 30 / 50 | 0.6000 | 2.571 | 0.00507 | 0.00796 | 显著,但只是勉强 |
| 300 / 500 | 0.6000 | 8.131 | < 0.00001 | < 0.00001 | 非常显著 |
| 3000 / 5000 | 0.6000 | 25.712 | < 0.00001 | < 0.00001 | 无可争辩 |
第五列是精确二项概率,也就是直接把所有“命中 30 场及以上”的情形加起来, 不做任何近似。50 场那组,精确值 0.00796 比正态近似 0.00507 大了约 6 成。
这个差别说明什么 正态近似在小样本上偏乐观——它报的 p 值比真实的小, 也就是让你觉得证据比实际更强。 n = 500 和 n = 5000 时两列几乎完全一致,近似完全够用。 样本小的时候,别信近似,直接算精确值。
还要说一句 p 值容易被误解的地方。 0.00507 的含义是“假如模型真等于基线水平, 出现这么好成绩的概率是 0.00507”。 它不是“模型无效的概率是 0.00507”, 也不是“模型有效的概率是 0.995”。 这两个反向解读都很常见,但都是错的: p 值是在假设无效的前提下算的,它不能反过来给“无效”定概率。
4 小样本上,教科书公式本身就会骗你
第 2 节用的 p̂ ± 1.96 × SE 叫 Wald 区间。 它有个不太出名的毛病:名义上说 95%,实际达不到 95%。
这句话可以直接验。设定真实胜率 0.60, 模拟 20000 次“测 n 场”,每次算出区间, 数一数有多少次真的把 0.60 包进去了。 如果公式诚实,答案应该接近 95%。
| 样本量 | Wald 实际覆盖 | Wilson 实际覆盖 | 缺口(Wald) |
|---|---|---|---|
| n = 20 | 0.9289 | 0.9634 | -0.0211 |
| n = 50 | 0.9448 | 0.9448 | -0.0052 |
| n = 200 | 0.9496 | 0.9496 | -0.0003 |
n = 20 时 Wald 只覆盖 0.9289, 比承诺的 0.95 少了 0.0211。 换句话说,每 100 个“95% 置信区间”里有大约 7 个根本没包含真值, 而不是承诺的 5 个。到 n = 200 时缺口收敛到 0.0003,可以忽略。
修法叫 Wilson 区间。它的思路是不拿观测值当圆心,而是把圆心向 0.5 稍微拉一点, 拉多少取决于样本量:
公式长,但里面依然只有加减乘除和一次开方, 而且 z2 = 1.962 = 3.8416 是常数。 效果对照:
| 观测 | Wald 区间 | 宽度 | Wilson 区间 | 宽度 | 下界之差 |
|---|---|---|---|---|---|
| 30 / 50 | [0.4642, 0.7358] | 0.2716 | [0.4618, 0.7239] | 0.2621 | -0.0024 |
| 300 / 500 | [0.5571, 0.6429] | 0.0859 | [0.5565, 0.6420] | 0.0856 | -0.0006 |
| 3000 / 5000 | [0.5864, 0.6136] | 0.0272 | [0.5863, 0.6135] | 0.0271 | -0.0001 |
50 场时两者的下界差 0.0024, 5000 场时差 0.0001, 基本可以忽略。 结论很实用:n 上百之后用哪个都行,n 只有几十的时候用 Wilson。
这一节的实际含义 小样本的问题是双重的:区间本来就宽(第 2 节), 而且那个宽度还不够宽——公式承诺的可信度它兑现不了(本节)。 两件事叠在一起,“测了 20 场”这种结论基本没有解读价值。
5 反过来问:要多少场才够
前面都是“给定 n,误差多大”。实际做评估时要问的是反问题: 我想要多少精度,得测多少场? 把式 (2) 的半宽记作 h,反解 n 就行:
h 在分母且带平方——精度要求提高一倍,样本量要涨四倍。 这是根号惩罚反过来看的样子,也是评估成本失控的根源。 代入 p = 0.60 算一列:
| 目标半宽 | 区间形如 | 所需 n | 相对上一行 | 现实感 |
|---|---|---|---|---|
| ±0.10 | [0.50, 0.70] | 93 | — | 约 0.24 个赛季 |
| ±0.05 | [0.55, 0.65] | 369 | ×4.0 | 约 0.97 个赛季 |
| ±0.03 | [0.57, 0.63] | 1025 | ×2.8 | 约 2.70 个赛季 |
| ±0.02 | [0.58, 0.62] | 2305 | ×2.2 | 约 6.07 个赛季 |
| ±0.01 | [0.59, 0.61] | 9220 | ×4.0 | 约 24.26 个赛季 |
“现实感”一列按一个联赛赛季约 380 场估算。 从 ±0.05 到 ±0.01,精度只提高 5 倍, 样本量从 369 涨到 9220, 涨了 25 倍。 这就是为什么小数点后第二位的胜率差异,在实践中几乎永远无法被验证。
5.1 更实际的问法:能不能检出优势
比“区间多窄”更接近真实需求的问题是: 假如我的模型确实比基线强那么一点,我要测多少场才有把握发现它? 这里的“有把握”习惯上取 80%,叫统计功效。 公式仍然只有加减乘除和开方,1.96 和 0.84 是两个常数 (分别对应 95% 显著和 80% 功效):
分母是优势的平方。优势越小,分母越小,n 越大——而且是平方级地大。 对照基线 0.4205 算一列:
| 真实胜率 | 优势 | 所需 n | 折合赛季 | 可行性 |
|---|---|---|---|---|
| 0.4500 | +2.95pp | 1741 | 4.6 | 很难,需要多年多联赛 |
| 0.4700 | +4.95pp | 620 | 1.6 | 吃力,约两个赛季 |
| 0.5000 | +7.95pp | 241 | 0.6 | 可行,不到一个赛季 |
| 0.5500 | +12.95pp | 91 | 0.2 | 容易 |
| 0.6000 | +17.95pp | 47 | 0.1 | 很容易 |
第一行最值得琢磨。一个真实胜率 45% 的模型, 确实比基线 0.4205 强 2.95 个百分点, 但你需要 1741 场才有 80% 的把握把它认出来。 而 IN-03 算过, 这种量级的优势在扣掉抽水后往往已经足够赚钱。
残酷的对称性 越是值钱的优势,越难被证明。 大优势(+17.95pp)几十场就能确认, 但那种模型在真实市场里基本不存在; 真实存在的小优势(+2.95pp)需要上千场—— 而等你攒够上千场,市场早就变了。 这不是统计学的缺陷,是这门生意的结构性困难。
6 最贵的陷阱:你挑过模型了吗
前面所有算法都建立在一个前提上:这份成绩是“一次性”拿到的—— 先定好模型,再跑数据,看结果。 但真实工作流几乎从不是这样。真实流程是: 试了十几组特征、几个窗口长度、几种阈值, 然后拿最好的那组去报告。
这个动作会让所有区间和 p 值全部失效,而且失效得很严重。 原因不复杂:你挑的不只是“最好的模型”, 还顺手挑走了“运气最好的那次噪声”。
这件事可以直接量出来。设定 m 个模型, 它们的真实水平完全相同,都恰好等于基线 0.4205—— 也就是说全都毫无本事,彼此之间没有任何高下之分。 每个模型各测 200 场,然后只保留观测胜率最高的那个, 重复 3000 次,看被挑出来的那个平均报出多少。
| 候选数 m | 被选中者观测胜率 | 虚高幅度 | 看起来显著的比例 | 真实情况 |
|---|---|---|---|---|
| 1(不挑) | 0.4201 | -0.04pp | 0.0440 | 诚实,虚高接近 0 |
| 10 | 0.4741 | +5.36pp | 0.4073 | 已经开始骗人 |
| 100 | 0.5083 | +8.78pp | 0.9967 | 看着像好模型,实则一无所有 |
读一下第三行。100 个真实水平全部等于 0.4205 的模型, 挑出观测最好的那个,它报出的平均胜率是 0.5083—— 虚高了 8.78 个百分点。
更糟的是第四列。0.9967 的意思是: 这样挑出来的模型,有 99.7% 的概率通过 5% 显著性检验。 你会拿到一个 p 值小于 0.05 的漂亮结论, 区间下界稳稳高于基线, 而它的真实水平就是基线本身,一点优势都没有。
为什么会这样 单个模型只有 0.0440 的概率碰巧显著——这正是 5% 的设计意图。 但如果你有 100 次独立机会,至少有一次碰巧显著的概率就不是 5% 了。 粗算是 1 − 0.95100 ≈ 0.9941——几乎必然发生。 显著性检验控制的是“单次误报率”, 它对“你试了多少次”完全没有防御。
注意 m = 10 那一行:虚高 5.36pp, 显著比例 0.4073。 十个候选算不算多?调参时随手就超过了。 这个陷阱的门槛远比想象的低。
这也解释了一个常见现象:回测漂亮的策略上线就失效。 并不一定是市场变了,也不一定是代码有 bug—— 很可能那个策略从一开始就没有优势, 它只是在几十次尝试中运气最好的那一次, 而上线之后运气不再配合。
7 那该怎么做
前六节都在说什么不可信。这一节说怎么让它可信。四条,都很朴素。
7.1 报数字时带上样本量和区间
把 “胜率 60%” 换成 60.00% [0.5571, 0.6429], n = 500。 这不是格式洁癖:不带样本量的百分比无法被评估, 读者连“该不该当真”都判断不了。 如果 n 只有几十,用 Wilson 而不是 Wald(第 4 节)。
7.2 先定样本量,再看结果
用式 (6) 事先算出“要检出我关心的那个优势,需要多少场”, 然后测够那么多场再看。 最危险的做法是边测边看,看到显著就停—— 这等价于第 6 节的挑选,只不过挑的是时间点而不是模型。
7.3 留一份从未参与过任何决策的数据
这是对付挑选偏差唯一可靠的办法。 调参、选特征、挑阈值都在训练集和验证集上做, 留一段时间上完全靠后的数据,一次都不碰, 最后只在上面跑一遍。 IN-04 的分箱重映射就是这么验的: 映射表在前 1000 场上学,效果在后 1000 场上报。
判断标准很简单 问自己一句:这份数据影响过我的任何一个决定吗? 影响过,它就不能再用来评估——哪怕只是“看了一眼觉得不行就换了个参数”。 看一眼也是使用。
7.4 老实交代你试了多少次
如果确实试了 30 组参数,就在报告里写清楚试了 30 组。 读者可以据此把 p 值往上调(最保守的做法是乘以尝试次数), 自行判断还剩多少证据。 隐瞒尝试次数,等于把表 7 第三行的虚高偷偷塞给读者。
8 复现
本文所有数字都来自一个纯标准库脚本,无第三方依赖, 随机部分固定种子 20260809, 在任何 Python 3 环境下重跑结果完全一致。
脚本包含四组函数:wald / wilson(两种区间)、
z_test / binom_sf(近似与精确检验)、
n_for_width / n_for_detect(两种样本量反解)、
coverage / selection_bias(两组模拟)。
下面是直接运行的真实输出:
$ python _verify_ci.py
BASE = 0.4205
case p_hat wald_lo wald_hi width
30/50 0.6000 0.4642 0.7358 0.2716
300/500 0.6000 0.5571 0.6429 0.0859
3000/5000 0.6000 0.5864 0.6136 0.0272
wilson:
30/50 0.6000 [0.4618, 0.7239] width=0.2621
300/500 0.6000 [0.5565, 0.6420] width=0.0856
3000/5000 0.6000 [0.5863, 0.6135] width=0.0271
z-test vs BASE:
30/50 p=0.6000 z=2.571 pvalue=0.00507 exact=0.00796
300/500 p=0.6000 z=8.131 pvalue=0.00000 exact=0.00000
3000/5000 p=0.6000 z=25.712 pvalue=0.00000 exact=0.00000
coverage of nominal 95% (p_true=0.60):
n=20 wald=0.9289 wilson=0.9634
n=50 wald=0.9448 wilson=0.9448
n=200 wald=0.9496 wilson=0.9496
sample size for target half-width (p=0.60):
+-0.10 n=93
+-0.05 n=369
+-0.03 n=1025
+-0.02 n=2305
+-0.01 n=9220
sample size to detect edge over BASE (power 80%):
p1=0.4500 edge=+2.95pp n=1741
p1=0.4700 edge=+4.95pp n=620
p1=0.5000 edge=+7.95pp n=241
p1=0.5500 edge=+12.95pp n=91
p1=0.6000 edge=+17.95pp n=47
selection bias (n=200, true p=BASE, 3000 trials):
m=1 mean_best=0.4201 bias=-0.04pp frac_significant=0.0440
m=10 mean_best=0.4741 bias=+5.36pp frac_significant=0.4073
m=100 mean_best=0.5083 bias=+8.78pp frac_significant=0.9967
逐段对照:第一段和 表 1 一致,第二段对应 表 4 的 Wilson 列, 第三段是 表 2,覆盖率段是 表 3, 两组样本量段分别是 表 5 和 表 6, 最后一段是 表 7。 正文中每一个出现在表格里的数字都能在这份输出中找到对应项。
9 结语
回到开头那两句话。50 场赢 30 和 500 场赢 300 不是同一件事, 差别不在那个 60%,在它周围的不确定性有多大: 区间宽度 0.2716 对 0.0859,差 3.16 倍。
本文只用了一个事实——噪声按 √n 缩小——就推出了全部结论:
- 小样本的区间宽得没有解读价值(表 1:50 场时真实水平可能在 46% 到 74% 之间);
- 而且它还不够宽,Wald 在 n = 20 时只兑现 0.9289 的覆盖(表 3);
- 想把区间压窄,成本是平方级的(表 5:从 ±0.05 到 ±0.01 要 25 倍样本);
- 越值钱的小优势越难证明(表 6:0.4205 上多 2.95pp 需要 1741 场);
- 而只要你挑过模型,上面所有保证同时失效(表 7:100 个平庸模型挑最优,虚高 8.78pp,误报率 99.67%)。
最后一条最该记住。前四条是数据量不足的问题,加数据就能解决; 第五条是方法本身出了问题,加数据完全无效—— 候选越多,虚高越大。 唯一的解法是第 7.3 节那一条:留一份从未参与过任何决策的数据。
一句话 统计不能让小样本变可信,它只能诚实地告诉你小样本有多不可信。 这已经很有用了——它让你不必在噪声上下注。
参考文献
- Wilson, E. B. (1927). Probable Inference, the Law of Succession, and Statistical Inference. Journal of the American Statistical Association, 22(158), 209–212.
- Brown, L. D., Cai, T. T., & DasGupta, A. (2001). Interval Estimation for a Binomial Proportion. Statistical Science, 16(2), 101–133.
- Agresti, A., & Coull, B. A. (1998). Approximate Is Better than “Exact” for Interval Estimation of Binomial Proportions. The American Statistician, 52(2), 119–126.
- Benjamini, Y., & Hochberg, Y. (1995). Controlling the False Discovery Rate. Journal of the Royal Statistical Society: Series B, 57(1), 289–300.
- Bailey, D. H., Borwein, J., López de Prado, M., & Zhu, Q. J. (2014). Pseudo-Mathematics and Financial Charlatanism: The Effects of Backtest Overfitting. Notices of the AMS, 61(5), 458–471.
- Cohen, J. (1988). Statistical Power Analysis for the Behavioral Sciences (2nd ed.). Lawrence Erlbaum Associates.
本文表 3 与表 7 为模拟结果, 真实胜率由脚本设定(分别为 0.60 和基线 0.4205), 固定种子 20260809,非真实比赛数据; 表 1、表 2、表 4 至表 6 为解析计算,与数据集无关。 基线值 0.4205 取自 IN-01 的实测统计。
本文是一篇模型评估方法论说明, 不构成任何投注建议。