跳转至

Kelly 公式:每次押多少

题

一个可以无限重复的赌局:每注胜率 \(p = 0.6\),赢了拿回本金外加同等金额(赔率 \(b = 1\)),输了赔掉本金。你每次押当前财富的固定比例 \(f\)。\(f\) 取多少,长期财富增长最快?押多了会怎样?

一句话

押 20%。Kelly 公式 \(f^* = p - \dfrac{q}{b}\) 最大化每注的期望对数增长 \(E[\log W]\),本例每注增长 \(0.0201\)(约 2%)。押到 39% 以上,长期增长率变负——胜率再高也会被磨光。

关键技巧

一、重复下注时,该最大化的是对数财富。 押 \(n\) 次后财富 \(W_n = W_0 \prod_i (1 + f X_i)\),其中 \(X_i = b\) 或 \(-1\)。取对数变成和:

\[ \frac{1}{n}\log \frac{W_n}{W_0} = \frac{1}{n}\sum_{i=1}^{n} \log(1 + f X_i) \xrightarrow{\text{a.s.}} g(f) = p \log(1 + bf) + q \log(1 - f) \]

由大数定律,几乎每条路径的长期增长率都收敛到 \(g(f)\)。最大化 \(g\) 就是最大化"典型路径"的财富。

二、对 \(g\) 求导。

\[ g'(f) = \frac{pb}{1 + bf} - \frac{q}{1 - f} = 0 \quad\Longrightarrow\quad f^* = \frac{pb - q}{b} = p - \frac{q}{b} \]

分子 \(pb - q\) 是每押 1 块的期望收益(edge),分母 \(b\) 是赔率(odds)——Kelly = edge / odds。edge \(\le 0\) 时 \(f^* \le 0\):不押。

三、别最大化期望财富。 \(E[W_n] = W_0 (1 + f(pb - q))^n\) 对 \(f\) 单调增,指向"每次全押"。但全押连赢 10 次的概率只有 \(0.6^{10} \approx 0.6\%\),其余路径全部归零——期望被极少数天文数字路径撑起来,中位数是 0。

解

\(p = 0.6\),\(q = 0.4\),\(b = 1\):

\[ f^* = 0.6 - \frac{0.4}{1} = 0.2, \qquad g(0.2) = 0.6 \ln 1.2 + 0.4 \ln 0.8 \approx 0.02014 \]

每注对数增长 0.0201,1000 注后财富的典型值约 \(e^{20.1} \approx 5.6 \times 10^8\) 倍。

\(f\) 0.1(半 Kelly) 0.2(Kelly) 0.3(1.5 倍) 0.4(2 倍)
\(g(f)\) 0.01504 0.02014 0.01475 \(-0.00245\)
占 Kelly 增长率 75% 100% 73% \(-12\%\)
曾跌到一半的概率(1000 注模拟) 11.4% 45.2% 77.1% 95.5%

\(g(f)\) 在 \(f^*\) 附近近似抛物线,左右对称:半 Kelly 和 1.5 倍 Kelly 的增长率几乎一样,风险却天差地别。\(g\) 在 \(f \approx 0.389\)(约 \(2f^*\))处过零——押到两倍 Kelly,赢面再大也只是原地踏步,再多就是稳定地亏。

{
  "height": 300,
  "grid": {"left": 65, "right": 30, "top": 30, "bottom": 45},
  "xAxis": {"type": "value", "name": "下注比例 f", "nameLocation": "middle", "nameGap": 28, "min": 0, "max": 0.44},
  "yAxis": {"type": "value", "name": "g(f)"},
  "series": [{
    "type": "line", "smooth": true, "showSymbol": false,
    "lineStyle": {"color": "#4e79a7", "width": 2},
    "data": [[0.0,0.0],[0.02,0.0038],[0.04,0.0072],[0.06,0.01021],[0.08,0.01282],[0.1,0.01504],[0.12,0.01686],[0.14,0.01829],[0.16,0.01931],[0.18,0.01993],[0.2,0.02014],[0.22,0.01993],[0.24,0.01929],[0.26,0.01822],[0.28,0.01671],[0.3,0.01475],[0.32,0.01231],[0.34,0.0094],[0.36,0.00598],[0.38,0.00204],[0.4,-0.00245],[0.42,-0.0075],[0.44,-0.01314]],
    "markLine": {
      "symbol": "none",
      "lineStyle": {"color": "#e15759", "type": "dashed"},
      "data": [{"xAxis": 0.2, "label": {"formatter": "f* = 0.2"}}, {"xAxis": 0.1, "label": {"formatter": "半 Kelly"}}, {"yAxis": 0, "label": {"show": false}}]
    }
  }]
}

延伸

  • 半 Kelly 是实战默认:押 \(c \cdot f^*\) 时增长率约为 Kelly 的 \(c(2 - c)\) 倍(\(c = 0.5\) 给 75%);连续时间近似下财富曾经跌到初始 \(x\) 倍的概率是 \(x^{2/c - 1}\)——全 Kelly 腰斩概率 \(1/2\),半 Kelly 只有 \(1/8\),1.5 倍 Kelly 是 \(0.79\)。模拟与之吻合(见折叠块)。
  • 胜率估不准时偏小押:\(p\) 高估 5 个点,按公式押的 \(f\) 就可能落到真实 \(f^*\) 的 1.5 倍;而 \(g\) 在右侧掉得比左侧快(对数的凹性),押少的代价远小于押多——这是半 Kelly 的第二个理由。
  • 与赌徒破产的呼应:对数财富是一个步长 \(\ln(1 + bf)\) / \(\ln(1 - f)\) 的随机游走,"跌到一半"就是赌徒破产里的吸收壁。比例下注永远押不光,真正的归零不会发生;但 Kelly 下漂移为正,只保证碰到任意下限的概率小于 1——全 Kelly 跌到初始 \(x\) 倍的概率约等于 \(x\) 本身。
  • 推广:一般结果分布下 \(f^* = \arg\max_f E[\log(1 + fX)]\);股票这类连续收益的近似是 \(f^* \approx \mu / \sigma^2\)(超额收益 ÷ 方差)。多个同时下注的机会,要对联合分布最大化 \(E[\log W]\),不能各押各的 Kelly。
  • 常见错误一:把 \(f^* = p - q/b\) 里的 \(b\) 当成总回报。\(b\) 是净赔率——押 1 赢了净得 \(b\)。1:1 时 \(b = 1\),不是 2。
  • 常见错误二:以为"期望为正就该多押"。期望线性、增长率不是——波动会从增长率里扣掉一个约 \(\frac{1}{2}f^2\sigma^2\) 的"方差税",押得越多税越重。
数值验证

计算 \(g(f)\)、过零点,再模拟 2000 条 1000 注的路径,统计中位增长率与"曾跌到一半"的频率,并和 \(x^{2/c-1}\) 对比:

import math, random

p, q, b = 0.6, 0.4, 1
g = lambda f: p * math.log(1 + b * f) + q * math.log(1 - f)
fs = p - q / b
print(round(fs, 4), round(g(fs), 5))              # 0.2 0.02014
for f in (0.1, 0.3, 0.4):
    print(f, round(g(f), 5), round(g(f) / g(fs), 3))
# 0.1 0.01504 0.747
# 0.3 0.01475 0.732
# 0.4 -0.00245 -0.122

lo, hi = fs, 0.99                                  # g 的零点
for _ in range(60):
    m = (lo + hi) / 2
    lo, hi = (m, hi) if g(m) > 0 else (lo, m)
print(round(lo, 4))                                # 0.3894
print(0.6 ** 10)                                   # 0.006046617599999997  全押连赢 10 次

random.seed(42)
N, T = 1000, 2000
for f in (0.1, 0.2, 0.3, 0.4):
    rates, halved = [], 0
    for _ in range(T):
        lw, low = 0.0, 0.0
        for _ in range(N):
            lw += math.log(1 + f) if random.random() < p else math.log(1 - f)
            low = min(low, lw)
        rates.append(lw / N); halved += low <= math.log(0.5)
    rates.sort()
    c = f / fs
    print(f, round(rates[T // 2], 4), sum(r < 0 for r in rates) / T, halved / T,
          round(0.5 ** (2 / c - 1), 3))
# f    中位增长率  最终亏损比例  曾腰斩  理论 0.5^(2/c-1)
# 0.1  0.0148     0.0          0.114   0.125
# 0.2  0.0205     0.0005       0.452   0.5
# 0.3  0.0147     0.065        0.771   0.794
# 0.4  -0.0016    0.5385       0.955   1.0

模拟的腰斩频率都略低于理论值——理论是无限时长,模拟只跑了 1000 注。