仓位管理的数学:凯利公式与固定百分比法
作者:FXEA Prime | 阅读时间:约 14 分钟
即使你拥有一个胜率 60%、盈亏比 2:1 的极品策略,如果仓位管理做错,你依然会爆仓。本文正式开启第四卷“资金管理”,从纯数学的视角,拆解交易界两大核心模型:稳健的固定百分比法(Fixed Fractional)与追求极致复利的凯利公式(Kelly Criterion)。并教你如何用 EA 代码实现全自动的动态算仓。
一、引言:生与死的数学线
很多散户耗费数年时间去寻找那个完美的“进场信号”,却对“买多少”凭感觉行事。今天觉得把握大,满仓干;明天觉得没把握,下个 0.1 手。
这不叫交易,这叫抛硬币。在量化交易领域,有一个著名的共识:进场逻辑决定你能不能赚钱,而资金管理决定你能活多久。
如果你用固定手数(比如每次都下 1 手)去交易,你的账户要么增长极其缓慢,要么在连续亏损中迅速死亡。今天,我们将引入真正的专业算仓方法。
二、稳健的盾牌:固定百分比法 (1% Rule)
这是专业交易员最常用、最稳健的仓位管理方法。
核心逻辑: 无论你的止损距离是 10 个点还是 100 个点,你每笔交易的最大亏损金额,永远只占你当前账户净值的固定百分比(通常是 1% 或 2%)。

图解:固定百分比法(蓝线)在盈利时产生复利,在连亏时呈指数级下降,保护本金;而固定手数(红线)在连亏时会导致线性爆仓。
🛡️ 为什么它被称为“反马丁格尔”?
假设你有 $10,000,每次风险为 2%:
- 第一单亏损: 亏损 $200。剩余 $9,800。
- 第二单风险: 变成 $9,800 的 2% = $196。
- 意义: 随着你的本金减少,你的下注金额会自动变小。即使你遭遇了可怕的 20 连亏,你的账户依然还有近 67% 的本金。它自带“连亏熔断”机制。相反,如果账户盈利,下注金额会自动变大,实现复利增长。
三、赌徒的圣杯:凯利公式 (Kelly Criterion)
如果你想追求资金增长的理论极限速度,你就绕不开贝尔实验室科学家约翰·凯利发明的“凯利公式”。
它通过计算你的胜率和盈亏比,告诉你一个“最优下注比例”。
$$f^* = \frac{bp – q}{b}$$
- $f^*$ (Fraction): 你应该下注的资金比例(例如 0.2 代表 20%)。
- $b$ (Odds): 盈亏比(例如盈利/亏损 = 2/1,则 b=2)。
- $p$ (Probability): 胜率(例如 40%,则 p=0.4)。
- $q$ (Probability of loss): 败率($1-p$,即 0.6)。
算个账:
假设你的 EA 回测数据显示:胜率 50% ($p=0.5$),盈亏比 2:1 ($b=2$)。
代入公式:$f^* = \frac{2 \times 0.5 – 0.5}{2} = \frac{0.5}{2} = 0.25$
凯利公式告诉你:为了实现最大化复利,你每笔交易应该押注总资金的 25%!
四、致命陷阱:为什么不能满仓“凯利”?
如果你真的敢每笔交易押注 25%,不出一个月,你的账户就会归零。这就是凯利陷阱。

图解:凯利曲线。下注比例超过最优值后(Over-betting),收益预期急剧下降,并伴随毁灭性的回撤风险。
- 市场不是掷硬币: 抛硬币的胜率永远是 50%,但市场的胜率是动态的。回测的 50% 胜率,在未来可能变成 35%。
- 黑天鹅与滑点: 凯利公式假设你亏损时只亏预定的金额。但在现实中,跳空和滑点会让你的亏损远超预期。如果按 25% 仓位算,一次黑天鹅就会让你爆仓。
- 心理破产: 使用满额凯利公式,账户的回撤(Drawdown)很容易达到 50% 甚至 70%。没有人类的心理能承受这种折磨。
五、实战心法:半凯利与动态缩放
在华尔街的量化基金中,没有人使用“满额凯利(Full Kelly)”。标准的做法是使用“半凯利(Half-Kelly)”或“分数凯利(Fractional Kelly)”。
- 用途一:作为试金石。 先用凯利公式计算你的策略。如果算出来的 $f^*$ 是负数,说明你的策略期望值为负,根本不该交易!
- 用途二:降维打击。 如果算出来是最优仓位是 20%,实战中我们通常只取它的 1/10 甚至 1/20,即使用 1% 或 2% 的固定百分比法。这既享受了复利,又将回撤控制在了人类可承受的范围内。
六、量化视角:EA 如何自动计算开仓手数?
这是开发专业风控 EA 最核心的代码片段。摒弃固定的 Lots = 0.1,让 EA 根据账户余额、风险比例和止损距离自动算出应该下多少手。
input double RiskPercent = 1.0; // 每次交易承担账户 1% 的风险
double CalculateLotSize(double stopLossPoints) {
if (stopLossPoints <= 0) return 0;
// 1. 获取当前账户可用预付款或余额
double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE);
// 2. 计算本次交易允许的最大亏损金额 (如 $10000 * 1% = $100)
double maxRiskAmount = accountBalance * (RiskPercent / 100.0);
// 3. 获取当前品种每手的点值 (Tick Value)
// 注意:如果是交叉盘或黄金,TickValue需要转换
double tickValue = SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_VALUE);
double tickSize = SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_SIZE);
// 4. 计算每 1 标准手,亏损指定点数,会亏多少钱?
// 假设止损是 500 个 point (50 pip)
double lossPerLot = stopLossPoints * (tickValue / tickSize);
// 5. 算出最终手数:允许亏损总额 / 每手亏损金额
double rawLot = maxRiskAmount / lossPerLot;
// 6. 手数标准化 (符合经纪商的最小步长要求)
double minLot = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MAX);
double lotStep = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_STEP);
double finalLot = MathFloor(rawLot / lotStep) * lotStep;
// 限制在最大最小值范围内
if (finalLot < minLot) finalLot = minLot;
if (finalLot > maxLot) finalLot = maxLot;
return finalLot;
}
// 用法示例:
// double sl_points = MathAbs(EntryPrice – StopLossPrice) / Point;
// double my_lot = CalculateLotSize(sl_points);
👨💻 程序员笔记:
在多货币对 EA 中,SYMBOL_TRADE_TICK_VALUE 非常容易出错(特别是账户基础货币与交易品种不一致时)。专业的做法是编写一个独立的汇率转换函数,确保你算出的亏损金额是 100% 准确的。
七、常见问题 (FAQ)
我们深耕 MQL4 程序开发,提供 定制化指标开发、EA 开发服务,可根据交易策略与习惯打造专属工具,降低操作成本,提升执行效率。





