策略组合优化:信号权重优化、风险平价、凯利公式

做高频交易做到一定阶段,你会发现一个尴尬的事实——单个策略再牛,也有吃瘪的时候。我见过太多人花几个月打磨一个信号,回测曲线漂亮得像假的一样,结果实盘一跑,连续回撤直接把人打懵。

说白了,单一策略就像单腿走路。你想想看,市场风格一变,你的信号可能就失效了。所以这一章,我们来聊聊怎么把多个策略组合起来,让它们互相补位。

为什么需要组合优化?

先讲个我自己的经历。几年前我同时跑着三个高频策略:一个做动量突破,一个做均值回归,还有一个做订单流不平衡。单独看,每个策略的夏普比都在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%。所以实际中,我一般用半凯利(仓位减半)或者四分之一凯利。

三种方法的对比与选择

方法 核心思想 优点 缺点 适用场景
信号权重优化 最大化夏普比 收益导向,理论成熟 依赖收益预测,不稳定 策略相关性低,历史数据稳定
风险平价 风险贡献均等 稳健,不依赖收益预测 可能牺牲收益 策略波动差异大,追求稳健
凯利公式 长期复利最大化 数学上最优 参数敏感,仓位可能过大 胜率和赔率稳定,资金充裕

我个人习惯的做法是:先用风险平价打底,保证组合的稳健性。然后在这个基础上,用凯利公式对每个策略的仓位做微调。最后再用均值-方差优化做一次整体校准。

说白了,没有银弹。每种方法都有它的适用边界。关键是要理解它们的假设条件,然后根据你的实际情况做取舍。

实战中的组合管理流程

下面这张图是我在实际项目中用的组合管理流程,你可以参考一下:

策略组合优化流程 策略信号生成 动量/均值回归/订单流 相关性分析 计算策略间相关系数 权重计算 风险平价/凯利/优化 组合构建 分配资金,执行交易 监控与再平衡 每日/每周权重调整 绩效评估 夏普比/回撤/胜率 反馈循环:根据绩效调整权重 建议每周进行一次再平衡,极端行情下缩短至每日

这个流程我用了好几年,核心就是闭环。权重不是算一次就完事了,需要根据实际表现不断调整。

最后说一句:组合优化不是万能药。如果你的每个策略本身都是垃圾,再怎么组合也变不成黄金。先把单个策略打磨好,再来谈组合的事。

核心要点总结

  • 信号权重优化追求收益最大化,但依赖预测准确性
  • 风险平价追求风险分散,适合稳健型交易者
  • 凯利公式追求长期复利,但参数估计要保守
  • 实际中建议混合使用,定期再平衡

交易系统化学习资料 微信Strategy888888