跳到主要内容
DA DataAlgorithm
Insights ROI 只需加减乘除 IN-03

命中 70% 却亏钱,命中 30% 却赚钱:准确率不等于收益

摘要 · 一句话结论 准确率是一个不带单位的数,收益是一个带钱的数,两者之间隔着赔率。 本文摆出两份各 10 注的账本:策略 A 命中 7/10、亏 90 元;策略 B 命中 3/10、赚 80 元。 我们把差别拆成三层——盈亏平衡命中率(判决线在哪)、 每注期望值(把准头和赔率压成一个数)、 波动与回撤(正期望也可能让你半路下车)。 全程只有加减乘除,最后一节给出可直接运行的复算脚本。
栏目:通俗洞察 Insights 阅读时长:约 12 分钟 数学门槛:只需加减乘除 发布:2026-08

1 两个策略,一张账本

先不谈理论。假设有两个人各自下了 10 注,每注都是 100 元,没有任何滚仓、没有加倍, 单位注固定。他们的下注对象不同:

设定

策略 A(稳):只押超级大热门,赔率一律 1.30。 10 注命中 7 次,命中率 70%。

策略 B(值):只押模型判断被市场低估的一方,赔率一律 3.60。 10 注命中 3 次,命中率 30%。

直觉会毫不犹豫地站 A:70% 对 30%,这不是一个量级的准头。 但账本要按钱算,不按次数算。十进制赔率的定义是押 1 拿回多少(含本金), 所以命中一注 A 拿回 130 元、净赚 30 元;命中一注 B 拿回 360 元、净赚 260 元。 没命中的注,两个人都是亏掉 100 元。

表 1 两个策略的逐注账本(单位注 100 元,✓ 表示命中)
第几注123 4567 8910
A @1.30
B @3.60

把这两行加起来。A 命中 7 次,每次拿回 1.30 × 100 = 130 元, 合计回收 7 × 130 = 910 元;总投入 10 × 100 = 1000 元。 B 命中 3 次,每次拿回 3.60 × 100 = 360 元, 合计回收 3 × 360 = 1080 元;总投入同样 1000 元。

表 2 结账:准确率与收益率的方向相反
策略赔率命中率 总投入总回收净盈亏收益率 ROI
A(稳)1.3070.00% 1000910 −90−9.00%
B(值)3.6030.00% 10001080 +80+8.00%

准确率栏里 A 完胜,收益率栏里 B 完胜。两栏的最优解互相矛盾, 而它们描述的是同一份账本。这不是构造出来的悖论,是十进制赔率的算术结构必然会产生的现象: 准确率只统计“对了几次”,收益率还要乘上“对一次值多少钱”。

本节要点

看到一个模型宣称“准确率 70%”,你无法据此判断它是否赚钱—— 因为这句话里缺了赔率。脱离赔率谈准确率,等于报了个数字却不说单位。

2 判决线:盈亏平衡命中率

上一节的矛盾有一个非常干净的解释。对固定赔率 d 的重复下注, 存在一条唯一的命中率红线:命中率高于它就长期赚,低于它就长期亏。 推导只需要一步——设命中概率为 p, 赢的时候净赚 d − 1,输的时候净亏 1,长期打平意味着两者期望抵消:

p(d1) = (1p) pBE = 1d
(1)

pBE盈亏平衡命中率(break-even hit rate)。 它恰好等于赔率的倒数,也就是 IN-02 讲过的隐含概率—— 同一个数字,站在庄家一侧读是“报价概率”,站在下注者一侧读是“及格线”。

把两个策略的赔率代进去,矛盾立刻消失:

表 3 把命中率和它自己的及格线比,而不是互相比
策略赔率1 / 赔率(及格线) 实际命中率超出幅度判决
A1.3076.92%70.00% −6.92 pp不及格,长期亏
B3.6027.78%30.00% +2.22 pp及格,长期赚

A 的 70% 之所以亏,是因为它要过的线是 76.92%,差了 6.92 个百分点; B 的 30% 之所以赚,是因为它只需要过 27.78%,超出了 2.22 个百分点。 准确率必须和自己那档赔率的及格线比,不能和别人的准确率比。 A 和 B 的准确率之所以没有可比性,是因为它们参加的是两场不同难度的考试。

常见误读

“我的模型准确率 55%,比抛硬币强,所以能赚钱。”—— 这句话只在赔率恰好高于 1 / 0.55 = 1.818 时成立。 如果模型挑中的比赛平均赔率是 1.70,那它的及格线是 58.82%,55% 依然亏。 顺带一提:IN-01 算过的“永远猜主胜”基线命中率是 42.05%, 对应的及格赔率是 1 / 0.4205 = 2.3781—— 主胜赔率低于 2.38 的比赛,闭眼押主胜就是亏的。

本节要点

赔率的倒数有双重身份:庄家读作报价概率,下注者读作盈亏平衡命中率。 准确率是否合格,取决于它和这条线的相对位置,而不是它的绝对高低。

3 把准头和赔率压成一个数:期望值

表 3 用“超出几个百分点”做判决,方向是对的,但幅度不能直接换成钱—— 因为在赔率 1.30 上多命中 1 个百分点和在赔率 3.60 上多命中 1 个百分点,值的钱不一样。 要把两者放在同一个刻度上,得用每注期望值(expected value per unit stake)。

EV= p(d1) (1p) = pd1
(2)

中间那一步的展开值得看一眼:p(d−1) − (1−p) = pd − p − 1 + p = pd − 1。 两个 p 抵消了,最后只剩命中率乘赔率再减一。 这是本文最实用的一个公式:它把“准头”和“赔率”这两件事压成了一个可以直接当百分比读的数。

代进两个策略:

表 4 每注期望值 EV = p × d − 1
策略pd p × dEV(每 1 元)折成百分比
A0.701.30 0.9100−0.0900−9.00%
B0.303.60 1.0800+0.0800+8.00%

注意这两个数字:−9.00% 和 +8.00%,和表 2 里实际结账出来的 ROI 一模一样。 这不是巧合。当每注金额固定、赔率固定时, ROI = EV 严格成立——因为 ROI 的定义是净盈亏除以总投入, 而总投入就是注数乘单位注,净盈亏就是注数乘单位注乘 EV,约掉之后只剩 EV。

口径提醒

公式 (2) 里的 p真实命中概率, 表 4 用的是这 10 注的实测频率。样本只有 10 注时, 频率和概率的差距可能很大——B 的 3/10 换成 2/10 就是 0.20 × 3.60 − 1 = −28%,直接由赚变亏。 所以 EV 是一个需要足够样本才能可信估计的量, 这也是为什么 IN-01 反复强调不要用几十场的结果给模型下结论。

4 赔率杠杆:同样的准头,天差地别的结果

公式 (2) 里 pd 是相乘的关系, 这意味着赔率对收益是乘性放大,不是加性修正。 把命中率钉死在 70%,只动赔率,看 EV 怎么走:

表 5 命中率固定 70%,赔率变化时的收益率
赔率 d及格线 1/d 70% 相对及格线EV = 0.70 × d − 1
1.3076.92%−6.92 pp−9.00%
1.8055.56%+14.44 pp+26.00%
2.5040.00%+30.00 pp+75.00%
3.6027.78%+42.22 pp+152.00%
5.0020.00%+50.00 pp+250.00%

同一个 70% 的准确率,在 1.30 上是每注亏 9 分,在 5.00 上是每注赚 2.5 元—— 差了 259 个百分点。准确率这个数字在整张表里一动没动。 如果有人拿着一份“准确率 70%”的报告来找你, 你唯一该问的问题是:这 70% 是在什么赔率区间上拿到的?

现实中的取舍

表 5 会让人产生一个错觉:那就专挑高赔率下注好了。 问题是市场不会免费送你高赔率——赔率之所以是 5.00, 正因为多数人(包括庄家的定价模型)认为这件事发生概率约 20%。 要在 5.00 上真的做到 70% 命中,你的模型必须比市场认知强出 50 个百分点, 这在成熟赛事上基本不存在。真实世界里可获得的优势通常是 几个百分点级别,也就是表 3 里 B 那种 +2.22 pp 的形态。 高赔率的正确用法是放大你已经证明存在的小优势, 而不是假装优势可以无限大。

本节要点

赔率是乘数不是加数。EV = p × d − 1 里改动 d 的杠杆效应远大于改动 p——但市场只在你真的具备信息优势时才会让你享受这个杠杆。

5 正期望也会让你半路下车:波动的代价

到这里 B 看起来全面胜出:EV 正、及格线过了、赔率杠杆也在它那边。 但账本还有一栏没算——路径。 表 1 里两个策略的净盈亏序列长得完全不一样: A 是 +30, +30, −100, +30 …, B 是 −100, −100, +260, −100 …

把这 10 个数取标准差(衡量单注结果的离散程度):

表 6 单注盈亏的均值与标准差(10 注样本,单位:元)
策略单注均值 单注标准差标准差 / |均值|
A−9.00 59.576.62
B+8.00 164.9720.62

最后一栏是关键:B 每赚 1 块钱,要承受 20.62 块钱的波动;A 是 6.62。 换句话说 B 的信号被噪声埋得更深。 这直接决定了一件很实际的事——你需要多少注才能确认自己真的有优势, 以及在确认之前你要忍受多大的回撤。

用一个小实验把这件事量出来:初始资金 5000 元,单位注 100 元固定不变, 连下 200 注,重复 10000 轮,看结局分布。 命中概率分别设为各自的真实值(A = 0.70,B = 0.30),随机种子固定为 20260808。

表 7 200 注 × 10000 轮模拟(起始资金 5000,单位注 100)
策略结局中位数 最差 5%最好 5% 爆仓比例中位最深低点
A @1.303200 17704630 0.01%3070
B @3.606600 264010560 0.44%4180

读这张表要读三层。第一层:中位数验证了 EV。 A 的 3200 就是 5000 − 200 × 100 × 0.09 = 3200, B 的 6600 就是 5000 + 200 × 100 × 0.08 = 6600, 模拟没有推翻算术,只是把算术的分布画了出来。

第二层:分布宽度差得很远。 A 的 5%–95% 区间是 1770 到 4630,跨度 2860; B 是 2640 到 10560,跨度 7920,是 A 的 2.8 倍。 值得注意的是 B 的最差 5% 结局(2640)虽然低于 A 的中位数结局(3200),但 B 的中位数 6600 已经是 A 的两倍多—— 正期望的力量在 200 注这个尺度上开始压倒波动,只是尾部依然难看。

第三层:过程比结局难熬。 A 的中位最深低点 3070,几乎就是它的结局值 3200——因为 A 是一路平稳下滑, 没有起伏,亏得很稳定。B 的中位最深低点是 4180, 低于 5000 的起始资金:一半以上的路径都曾跌破本金 820 元以上, 然后才涨到 6600。这 820 元的浮亏是 B 的真实成本, 不出现在 EV 里,但出现在每一个盯着账户看的人的心理账上。 很多正期望策略死在这一步,不是因为算错了,是因为在低点被放弃了。

爆仓比例要谨慎解读

表 7 里两个爆仓比例都很小(0.01% 与 0.44%),但这完全是因为我们设定了 固定单位注 100 元、本金 5000 元,即最多能承受 50 连败。 把单位注改成 500 元(本金的 10%),B 的爆仓比例会急剧上升。 注码规模是一个独立于 EV 的问题,属于 Kelly 判据的范畴,本文不展开。 这里只需记住一句:EV 决定你该不该下,注码决定你能不能活到 EV 兑现的那天。

本节要点

高赔率策略的正期望要用高波动来换。 判断一个策略不能只看 EV,还要看 EV 与波动的比值 以及路径上的最深回撤——它们决定了这个正期望能不能被人真正拿到手。

6 那该报什么指标?

如果准确率不能单独用,一份诚实的模型评估报告里该有什么? 按重要程度排,至少是下面这四个数:

表 8 替代“裸准确率”的最小指标集
指标算法回答什么问题
相对基线的准确率 模型准确率 − 多数类基线 比闭眼猜强多少(IN-01)
相对及格线的命中率 命中率 − 1/平均赔率 是否越过了盈亏平衡(§2)
每注期望值 p × d − 1 每 1 元预期赚多少(§3)
EV / 单注标准差 均值 ÷ 标准差 信噪比,要多少样本才可信(§5)

这四个数都只用加减乘除,都能在一份回测账本上直接算出来, 并且任意一个单独看都会误导——必须一起看。 加上 IN-01 讲的对数损失和 IN-02 讲的归一化报价概率, 就构成了一套最低限度的、不至于自欺的评估口径。

7 复算脚本

本文所有数字由下面这一段脚本产生,没有任何手写的结果。 只依赖标准库,直接运行即可复现表 2 到表 7 的每一个值。 模拟部分随机种子固定为 20260808,因此输出可逐位比对。

Python 3
import random
import statistics as st

UNIT, BANK, N, TRIALS = 100.0, 5000.0, 200, 10000


def breakeven(d):
    return 1.0 / d


def ev(p, d):
    return p * d - 1.0


def ledger(d, hits):
    stake = UNIT * len(hits)
    ret = sum(d * UNIT if h else 0.0 for h in hits)
    pnl = [(d - 1) * UNIT if h else -UNIT for h in hits]
    return stake, ret, ret - stake, (ret - stake) / stake, pnl


def simulate(d, p, seed):
    random.seed(seed)
    ends, mins, ruin = [], [], 0
    for _ in range(TRIALS):
        bank, lo = BANK, BANK
        for _ in range(N):
            if bank < UNIT:
                ruin += 1
                break
            bank += (d - 1) * UNIT if random.random() < p else -UNIT
            lo = min(lo, bank)
        ends.append(bank)
        mins.append(lo)
    ends.sort()
    return st.median(ends), ends[int(.05 * TRIALS)], ends[int(.95 * TRIALS)], \
        100.0 * ruin / TRIALS, st.median(mins)


A_HITS = [1, 1, 0, 1, 1, 1, 0, 1, 1, 0]
B_HITS = [0, 0, 1, 0, 0, 1, 0, 0, 1, 0]

for name, d, hits in (("A@1.30", 1.30, A_HITS), ("B@3.60", 3.60, B_HITS)):
    stake, ret, profit, roi, pnl = ledger(d, hits)
    p = sum(hits) / float(len(hits))
    print("%s acc=%.2f%% BE=%.2f%% profit=%+.0f ROI=%+.2f%% EV=%+.2f%% sd=%.2f sd/mean=%.2f"
          % (name, p * 100, breakeven(d) * 100, profit, roi * 100,
             ev(p, d) * 100, st.pstdev(pnl), st.pstdev(pnl) / abs(profit / len(hits))))

print("")
for d in (1.30, 1.80, 2.50, 3.60, 5.00):
    print("acc=70%% d=%.2f BE=%.2f%% EV=%+.2f%%" % (d, breakeven(d) * 100, ev(0.70, d) * 100))

print("")
for name, d, p in (("A@1.30", 1.30, 0.70), ("B@3.60", 3.60, 0.30)):
    med, p05, p95, ruin, dip = simulate(d, p, 20260808)
    print("%s median=%.0f p05=%.0f p95=%.0f ruin=%.2f%% worst_dip=%.0f"
          % (name, med, p05, p95, ruin, dip))

代码 1 账本结算 → 盈亏平衡线 → 期望值 → 赔率杠杆 → 200 注路径模拟

运行输出(本文表 2 至表 7 的数字来源):

stdout
A@1.30 acc=70.00% BE=76.92% profit=-90 ROI=-9.00% EV=-9.00% sd=59.57 sd/mean=6.62
B@3.60 acc=30.00% BE=27.78% profit=+80 ROI=+8.00% EV=+8.00% sd=164.97 sd/mean=20.62

acc=70% d=1.30 BE=76.92% EV=-9.00%
acc=70% d=1.80 BE=55.56% EV=+26.00%
acc=70% d=2.50 BE=40.00% EV=+75.00%
acc=70% d=3.60 BE=27.78% EV=+152.00%
acc=70% d=5.00 BE=20.00% EV=+250.00%

A@1.30 median=3200 p05=1770 p95=4630 ruin=0.01% worst_dip=3070
B@3.60 median=6600 p05=2640 p95=10560 ruin=0.44% worst_dip=4180

代码 2 实际运行结果,与正文数字逐位一致

8 写在最后

准确率之所以流行,是因为它便宜——一个百分数,谁都看得懂,谁都能拿去比。 代价是它把“对了几次”和“对得值不值”这两件事合并成了一个数, 而合并的时候丢掉的恰好是赔率,也就是钱。

本文的三层结构其实是同一句话的三种说法。 §2 说:及格线由赔率决定,70% 可能不及格,30% 可能及格。 §3 说:把准头和赔率乘起来减一,就得到每 1 元的预期收益,这个数才可比。 §5 说:即使这个数为正,波动也可能让你在兑现之前离场。 三层缺一层,结论就会跑偏。

作为本站的研究口径,我们不打算再单独发布任何形式的裸准确率。 需要说明模型表现时,至少同时给出表 8 里的四个数—— 它们都只需要加减乘除,没有任何理由省略。 如果一份评估里只有准确率,那它要么是没算,要么是算了但不想说。

全文一句话

准确率衡量你对了几次,收益衡量你对得值不值, 中间隔着赔率——不带赔率的准确率,是一个没有单位的数字。

参考文献

  1. Kelly, J. L. A New Interpretation of Information Rate. Bell System Technical Journal, 1956, 35(4), 917–926. (期望值为正之后的注码规模判据,本文 §5 提及未展开)
  2. Thorp, E. O. The Kelly Criterion in Blackjack, Sports Betting, and the Stock Market. In Handbook of Asset and Liability Management, 2008, Vol. 1, 385–428. (正期望策略的回撤特征与注码实践)
  3. Levitt, S. D. Why are Gambling Markets Organised so Differently from Financial Markets? The Economic Journal, 2004, 114(495), 223–246. (赔率定价与市场认知偏差的实证研究,对应 §4 关于“市场不送高赔率”的论断)
  4. Constantinou, A. C.; Fenton, N. E. Solving the Problem of Inadequate Scoring Rules for Assessing Probabilistic Football Forecast Models. Journal of Quantitative Analysis in Sports, 2012, 8(1). (为什么准确率类指标不足以评估足球预测模型)
  5. 本站 IN-01:《你的模型真的比“永远猜主胜”强吗?》 baseline-vs-majority-class.html (多数类基线 42.05% 的出处,本文 §2 与表 8 引用)
  6. 本站 IN-02:《赔率 2.10 是不是就等于 47.6% 的概率?》 odds-implied-probability.html (隐含概率与过轮的算术,本文 §2 的盈亏平衡线与之同源)

本文中的赔率 1.30 / 3.60、命中序列以及 5000 元本金 均为示例数值,用于演示算术流程,不对应任何具体比赛、平台报价或真实账户。 表 2 至表 7 的全部计算结果由 §7 代码 1 实际运行产生, 代码 2 的输出为该脚本真实 stdout,读者可自行复算逐位核对。

本文是一篇模型评估方法论说明, 目的在于讲清准确率与收益率的量纲差别,不构成任何投注建议。 足球比赛结果具有高度不确定性,任何预测模型都无法保证盈利。