仓位管理与凯利公式
直觉
「该买多少」比「买什么」更决定生死。买太少,好策略也赚不到钱;买太多,一次回撤就让你出局——再也等不到均值回归。凯利公式(Kelly criterion) 从「最大化长期复利增长率」出发,给出理论最优的下注比例。它的核心洞见是:最优仓位与「胜率/赔率」成正比,与「波动」成反比——优势越大、越稳,越该重仓;但全仓下注风险极高,实务中几乎总是用分数凯利(如半凯利)。
凯利公式
离散形式(赔率 赢、 输,胜率 ,):
连续形式(收益近似正态, 均值、 方差)——更贴近每日交易:
它最大化的是对数财富的期望增长率 。
「人话」解释:为什么全凯利危险、半凯利够用?
凯利公式最大化的是长期复利,但它的代价是剧烈的中途回撤——全凯利的最大回撤常常达到 50%~90%,绝大多数人心理上根本扛不住。更糟的是:公式假设你精确知道 和 ,而现实中它们只是估计值、且会变,估计偏高就会过度下注、导致破产。 半凯利()只牺牲约 25% 的增长率,却把回撤和方差大幅减半,是实务的标准选择。有人甚至用 凯利——「先活下来,再谈赚钱」。
可运行案例:全凯利 vs 半凯利 vs 买入持有
用滚动 252 日均值/方差估计凯利分数 (做多、不允许加杠杆:截断到 ),对比全凯利、半凯利与满仓持有的净值与回撤。
import quant
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('/data/spy_daily.csv', parse_dates=['date']).set_index('date')
close = df['adj_close']; r = close.pct_change()
# 凯利分数 f_t = 滚动均值 / 滚动方差 (每日口径), 做多且不加杠杆
mu = r.rolling(252).mean(); sig2 = r.rolling(252).var()
f = (mu / sig2).clip(0, 1)
full = quant.vector_backtest(close, f, cost_bps=1)
half = quant.vector_backtest(close, (f / 2).clip(0, 1), cost_bps=1)
buy_hold = quant.vector_backtest(close, pd.Series(1.0, index=close.index), cost_bps=1)
print(f"全凯利 平均仓位={f.mean():.2f}")
for name, bt in [('买入持有', buy_hold), ('半凯利', half), ('全凯利', full)]:
s = quant.performance_summary(bt['equity'], bt['returns'])
print(f"{name:6}: 年化={s['年化收益']:+.2%} 夏普={s['夏普']:.2f} 最大回撤={s['最大回撤']:.2%}")
plt.figure(figsize=(9, 3.6))
plt.plot(full['equity'], label='全凯利(剧烈回撤)', lw=1.2)
plt.plot(half['equity'], label='半凯利', lw=1.6)
plt.plot(buy_hold['equity'], label='买入持有', lw=1.2, ls='--')
plt.title('凯利仓位下的净值(全凯利长期高但中途坐过山车)')
plt.ylabel('净值'); plt.legend(fontsize=9); plt.tight_layout(); plt.show()
print("\n→ 全凯利长期净值最高, 但回撤最深; 半凯利性价比最高。")
动手改一改
把凯利上限从 clip(0,1) 放宽到 clip(0,2)(允许 2 倍杠杆),观察年化收益上升的同时,最大回撤如何爆炸——这就是「过度下注」的代价。
小结
- 凯利公式 给出最大化长期复利的理论最优仓位;
- 全凯利回撤极深且对估计误差敏感,实务多用半凯利;
- 仓位管理本质是「在增长与生存之间找平衡」,分数凯利是稳健的折中。