策略组合优化:信号权重优化、风险平价、凯利公式
做高频交易做到一定阶段,你会发现一个尴尬的事实——单个策略再牛,也有吃瘪的时候。我见过太多人花几个月打磨一个信号,回测曲线漂亮得像假的一样,结果实盘一跑,连续回撤直接把人打懵。
说白了,单一策略就像单腿走路。你想想看,市场风格一变,你的信号可能就失效了。所以这一章,我们来聊聊怎么把多个策略组合起来,让它们互相补位。
为什么需要组合优化?
先讲个我自己的经历。几年前我同时跑着三个高频策略:一个做动量突破,一个做均值回归,还有一个做订单流不平衡。单独看,每个策略的夏普比都在2.5以上,我觉得稳了。
结果呢?某天市场突然出现极端波动,动量策略疯狂追涨,均值回归策略拼命做空,两个策略对着干,一天亏掉了一周的利润。那天晚上我盯着账户发呆,突然意识到——策略之间的相关性,比策略本身的收益更重要。
组合优化的核心目标有三个:
- 降低波动——让资金曲线更平滑
- 提升稳健性——适应不同市场环境
- 控制回撤——别让一次黑天鹅把你带走
嗯,这里要注意,组合优化不是简单地把信号加起来。它需要一套数学框架来分配权重。
信号权重优化:最直接的方法
信号权重优化,说白了就是给每个策略分配一个系数。比如策略A权重0.4,策略B权重0.3,策略C权重0.3。
但问题来了——权重怎么定?
最朴素的做法是等权分配。每个策略给相同的资金,简单粗暴。但这样做有个问题:如果某个策略明显更优,等权反而拖累了整体表现。
我个人习惯用均值-方差优化。这是马科维茨那套理论,虽然老,但在高频场景下依然好用。
import numpy as np
from scipy.optimize import minimize
def optimize_weights(returns, target_vol=0.15):
"""
均值-方差优化:寻找最优权重
returns: 各策略的日收益率矩阵,shape=(n_days, n_strategies)
"""
n = returns.shape[1]
mean_ret = returns.mean(axis=0)
cov_matrix = np.cov(returns.T)
def portfolio_stats(weights):
port_ret = np.dot(weights, mean_ret)
port_vol = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
return port_ret, port_vol
def objective(weights):
ret, vol = portfolio_stats(weights)
# 最大化夏普比
return -ret / vol
constraints = [
{'type': 'eq', 'fun': lambda x: np.sum(x) - 1} # 权重之和为1
]
bounds = [(0, 1) for _ in range(n)]
result = minimize(objective,
x0=np.ones(n)/n,
bounds=bounds,
constraints=constraints,
method='SLSQP')
return result.x
# 示例:三个策略的日收益率
np.random.seed(42)
returns = np.random.randn(1000, 3) * 0.02 # 模拟数据
weights = optimize_weights(returns)
print(f"最优权重: {weights}")
避坑指南:我曾经在实盘中直接用历史最优权重,结果翻车了。因为均值-方差优化对输入参数极其敏感,历史数据的最优解,未来不一定最优。建议加上权重约束,比如单个策略权重不超过0.5,避免过度集中。
风险平价:让每个策略承担相同的风险
均值-方差优化有个硬伤——它依赖预期收益率的估计。而预期收益率这东西,说实话,很难准确预测。尤其是在高频领域,收益分布经常是肥尾的。
所以后来我更喜欢用风险平价。它的思路很简单:让每个策略对组合的风险贡献相等。
你想想看,如果策略A波动大,策略B波动小,等权分配的话,策略A实际上承担了大部分风险。风险平价就是要纠正这种不平衡。
def risk_parity_weights(cov_matrix):
"""
风险平价:每个资产对组合的风险贡献相等
"""
n = cov_matrix.shape[0]
def risk_contribution(weights):
port_vol = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
# 每个资产的风险贡献
rc = weights * (np.dot(cov_matrix, weights)) / port_vol
return rc
def objective(weights):
rc = risk_contribution(weights)
# 让所有风险贡献尽可能相等
target_rc = np.mean(rc)
return np.sum((rc - target_rc) ** 2)
constraints = [
{'type': 'eq', 'fun': lambda x: np.sum(x) - 1}
]
bounds = [(0, 1) for _ in range(n)]
result = minimize(objective,
x0=np.ones(n)/n,
bounds=bounds,
constraints=constraints,
method='SLSQP')
return result.x
# 示例
cov = np.array([[0.04, 0.01, 0.005],
[0.01, 0.09, 0.002],
[0.005, 0.002, 0.16]])
weights_rp = risk_parity_weights(cov)
print(f"风险平价权重: {weights_rp}")
我的经验:风险平价在震荡市中表现特别好。因为它天然分散了风险,不会因为某个策略突然失效而崩盘。但要注意,如果所有策略同时失效(比如流动性枯竭),风险平价也救不了你。
凯利公式:追求长期复利最大化
凯利公式是个很有意思的东西。它告诉你,在已知胜率和赔率的情况下,应该下多大的注才能让长期复利最大化。
公式很简单:
f* = (bp - q) / b
其中:
- f* 是最优仓位比例
- b 是赔率(盈亏比)
- p 是胜率
- q = 1 - p 是败率
但在高频交易中,我们面对的不是单一赌局,而是连续的交易信号。所以需要把凯利公式扩展到多策略场景。
def kelly_weights(win_rates, avg_win, avg_loss):
"""
多策略凯利公式:基于每个策略的统计特征计算最优仓位
"""
n = len(win_rates)
weights = np.zeros(n)
for i in range(n):
p = win_rates[i]
b = avg_win[i] / abs(avg_loss[i]) # 盈亏比
q = 1 - p
f = (b * p - q) / b
# 凯利公式建议的仓位可能很大,实际中需要缩水
weights[i] = max(0, min(f, 0.25)) # 限制单策略最大仓位25%
# 归一化
total = np.sum(weights)
if total > 0:
weights = weights / total
return weights
# 示例
win_rates = [0.55, 0.48, 0.62]
avg_win = [0.02, 0.015, 0.025]
avg_loss = [0.01, 0.012, 0.01]
kelly_w = kelly_weights(win_rates, avg_win, avg_loss)
print(f"凯利权重: {kelly_w}")
重要提醒:凯利公式有个大坑——它假设你知道准确的胜率和赔率。但在真实交易中,这些参数是估计出来的,有误差。我曾经用全凯利仓位跑了一个月,结果胜率估计偏高了5%,直接导致回撤超过20%。所以实际中,我一般用半凯利(仓位减半)或者四分之一凯利。
三种方法的对比与选择
| 方法 | 核心思想 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 信号权重优化 | 最大化夏普比 | 收益导向,理论成熟 | 依赖收益预测,不稳定 | 策略相关性低,历史数据稳定 |
| 风险平价 | 风险贡献均等 | 稳健,不依赖收益预测 | 可能牺牲收益 | 策略波动差异大,追求稳健 |
| 凯利公式 | 长期复利最大化 | 数学上最优 | 参数敏感,仓位可能过大 | 胜率和赔率稳定,资金充裕 |
我个人习惯的做法是:先用风险平价打底,保证组合的稳健性。然后在这个基础上,用凯利公式对每个策略的仓位做微调。最后再用均值-方差优化做一次整体校准。
说白了,没有银弹。每种方法都有它的适用边界。关键是要理解它们的假设条件,然后根据你的实际情况做取舍。
实战中的组合管理流程
下面这张图是我在实际项目中用的组合管理流程,你可以参考一下:
这个流程我用了好几年,核心就是闭环。权重不是算一次就完事了,需要根据实际表现不断调整。
最后说一句:组合优化不是万能药。如果你的每个策略本身都是垃圾,再怎么组合也变不成黄金。先把单个策略打磨好,再来谈组合的事。
核心要点总结:
- 信号权重优化追求收益最大化,但依赖预测准确性
- 风险平价追求风险分散,适合稳健型交易者
- 凯利公式追求长期复利,但参数估计要保守
- 实际中建议混合使用,定期再平衡