策略组合管理:多策略并行、策略权重分配、动态切换、相关性控制

做市系统做到一定规模,你会发现一个尴尬的事实——单一策略就像只会一招的拳手,行情顺的时候赚得盆满钵满,行情一变立马被打趴下。我见过太多团队,辛辛苦苦开发了一个高频价差策略,结果市场波动率结构一变,回撤直接吞掉三个月的利润。

所以,策略组合管理不是锦上添花,而是生存刚需。说白了,就是让你手里的多个策略像一支足球队一样,前锋、中场、后卫各司其职,还能根据场上形势随时换人换阵型。

多策略并行:别把所有鸡蛋放在一个篮子里

多策略并行,听起来简单,做起来坑不少。我早期犯过一个低级错误——让两个策略同时交易同一个币对,结果它们互相抢单,手续费交了不少,利润却没见涨。

并行策略的核心原则是:策略之间在逻辑上要正交。什么叫正交?就是它们赚的钱来自不同的市场特征。

  • 价差策略:赚的是买卖价差,依赖高流动性、低波动
  • 趋势策略:赚的是方向性波动,依赖趋势延续
  • 统计套利策略:赚的是价格回归,依赖均值回复特性
  • 做市库存策略:赚的是资金费率或持仓收益

你看,这四种策略赚的钱来源完全不同。把它们放在一起,就像同时开了四个水龙头,每个水龙头接的是不同的水源。一个干涸了,另外三个还能继续流。

我的经验:并行策略的数量不是越多越好。我个人习惯控制在3-5个核心策略。超过这个数,管理成本和系统复杂度会指数级上升,边际收益反而下降。

策略权重分配:动态调仓的艺术

策略权重分配,说白了就是决定每个策略分多少钱去交易。这里有个常见的误区——很多人以为权重是固定的,比如策略A占30%,策略B占70%,然后就一直这么跑下去。

嗯,这其实是个坑。市场在变,策略的表现也在变。固定权重就像穿着冬天的棉袄过夏天,不热死才怪。

我建议用风险平价的思路来做权重分配。核心逻辑是:让每个策略对总风险的贡献相等。

// 风险平价权重计算示例
function calculateRiskParityWeights(strategies) {
    // strategies: [{name, volatility, sharpe, correlation_matrix}]
    const n = strategies.length;
    let weights = new Array(n).fill(1/n);
    
    // 迭代优化,使每个策略的边际风险贡献相等
    for (let iter = 0; iter < 100; iter++) {
        let riskContributions = [];
        for (let i = 0; i < n; i++) {
            let rc = 0;
            for (let j = 0; j < n; j++) {
                rc += weights[i] * weights[j] * 
                      strategies[i].volatility * strategies[j].volatility * 
                      strategies[i].correlation_matrix[i][j];
            }
            riskContributions.push(rc);
        }
        // 调整权重,使风险贡献趋于一致
        let avgRisk = riskContributions.reduce((a,b) => a+b, 0) / n;
        for (let i = 0; i < n; i++) {
            weights[i] *= avgRisk / riskContributions[i];
        }
        // 归一化
        let sum = weights.reduce((a,b) => a+b, 0);
        weights = weights.map(w => w / sum);
    }
    return weights;
}

这段代码的核心思想是:让每个策略的边际风险贡献(Marginal Risk Contribution)相等。波动率大的策略自然权重小,波动率小的策略权重大。这样组合的整体波动会更平滑。

避坑指南:我曾经在实盘中直接用历史波动率算权重,结果遇到一次极端行情,波动率瞬间飙升,权重还没来得及调整,一个策略就把整个组合带崩了。后来我加了波动率预测和权重更新频率限制,才稳住局面。

动态切换:什么时候换策略?

动态切换,就是根据市场状态,自动启用或禁用某些策略。这比权重调整更激进——权重调整是给每个策略分钱,动态切换是直接让某些策略「下场休息」。

我常用的切换信号有几种:

  • 波动率阈值:波动率超过某个值,关闭价差策略,开启趋势策略
  • 流动性指标:买卖价差过大时,关闭高频策略
  • 策略自身表现:连续亏损N笔后,暂时禁用该策略
  • 市场状态分类:用机器学习模型判断当前是震荡市还是趋势市,然后切换

举个例子,我做过一个简单的切换逻辑:

// 策略动态切换逻辑
function strategySwitcher(marketState, strategyPerformances) {
    let activeStrategies = [];
    
    // 波动率低时,启用价差策略
    if (marketState.volatility < 0.02) {
        activeStrategies.push('spread');
    }
    
    // 趋势明显时,启用趋势策略
    if (Math.abs(marketState.trendStrength) > 0.3) {
        activeStrategies.push('trend');
    }
    
    // 统计套利只在相关性稳定时启用
    if (marketState.correlationStability > 0.8) {
        activeStrategies.push('statArb');
    }
    
    // 策略连续亏损超过3笔,强制休息
    for (let [name, perf] of Object.entries(strategyPerformances)) {
        if (perf.consecutiveLosses >= 3) {
            activeStrategies = activeStrategies.filter(s => s !== name);
        }
    }
    
    return activeStrategies;
}

这里要注意的是,切换不能太频繁。我见过有人每秒钟切换一次策略,结果系统光在切换上就消耗了大量资源,交易反而没做好。我个人习惯设置一个最小切换间隔,比如5分钟,避免来回切换。

相关性控制:组合的隐形杀手

相关性控制,是策略组合管理里最容易被忽视的一环。很多人以为选了不同策略就万事大吉,结果一算相关性矩阵,发现两个策略的相关性高达0.8——说白了,它们本质上在赚同一份钱。

为什么会这样?因为策略虽然名字不同,但底层逻辑可能高度相似。比如一个基于布林带的价差策略和一个基于RSI的价差策略,虽然指标不同,但交易信号高度重合。

我建议定期计算策略之间的相关性矩阵,并设定一个上限:

策略对 相关性 操作建议
价差策略A vs 价差策略B 0.85 合并或只保留一个
价差策略 vs 趋势策略 -0.12 保留,有对冲效果
统计套利 vs 做市库存 0.45 可保留,但需监控
趋势策略A vs 趋势策略B 0.72 考虑降低其中一个权重

我一般把相关性阈值设在0.6。超过这个值,我就会考虑合并策略或者降低其中一个的权重。你想想看,如果两个策略相关性0.8,那它们同时亏损的概率就很高,组合的分散化效果就大打折扣。

注意:相关性不是一成不变的。我遇到过最坑的情况是,两个策略在回测中相关性只有0.2,结果实盘跑了两个月,相关性飙到了0.9。后来一查,是因为市场结构发生了变化。所以,相关性要动态监控,不能一劳永逸。

整体架构:一张图看懂策略组合管理

说了这么多,我们来画一张整体架构图。这张图展示了我个人比较推崇的策略组合管理流程:

策略组合管理架构图 市场数据输入 策略池 价差策略 趋势策略 统计套利 做市库存 相关性控制模块 风险平价权重分配 动态策略切换 反馈调整

这张图展示了我常用的四层架构:市场数据输入 → 策略池 → 相关性控制 → 权重分配 → 动态切换。注意那个反馈回路,它把策略的表现数据回传给相关性控制和权重分配模块,形成闭环。

嗯,这套架构我用了三年多,经历过几次极端行情,整体表现还算稳健。当然,没有完美的系统,只有不断迭代的系统。你如果刚开始搭建,建议先从两个策略做起,跑通了再加第三个。步子迈大了,容易扯着蛋。

最后一个小建议:策略组合管理不是一锤子买卖。我每周都会花半小时看看组合的表现,检查相关性矩阵有没有异常,权重是否需要调整。这半小时,往往能帮我避免后面几天的回撤。


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