
做了几年期货量化单策略跑得再猛也有心慌的时候。趋势策略遇到震荡行情连续回撤三四周套利策略赶上极端行情价差瞬间拉开这时候才意识到真正让你能安稳睡着的不是某个策略的胜率而是组合层面怎么分配资金。多策略资金分配这件事听起来只是在几个策略之间切分本金实际操作起来涉及波动率估计、相关性计算、保证金约束、再平衡节奏等一系列问题。这篇文章就围绕期货量化策略组合优化这个主题把多策略资金分配的方法、逻辑和踩过的坑完整梳理一遍给正在从单策略向组合过渡的朋友一个可以直接参考的框架。关于这套东西适合谁看我简单说两句。如果你手里已经有两三个跑得通的期货策略哪怕只是简单的双均线趋势或跨期套利只要你想把它们真正组合起来而不是简单拼凑这篇文章就能派上用场。如果你还在单策略阶段也可以提前了解组合资金分配的逻辑毕竟从单策略到组合是量化交易必经的一步。1. 为什么单策略跑不动了组合才是正解1.1 单策略的三个致命弱点先泼一盆冷水。任何一个期货量化策略无论回测表现多漂亮都存在三个绕不过去的问题曲线拟合风险、市场风格切换风险、单一资金曲线带来的心理压力。曲线拟合是最隐蔽的坑。你在历史数据上反复调整参数让回测曲线的夏普比例高达三以上但实盘一跑就变样原因很简单——参数过度优化导致策略只是在复述历史行情而不是在捕捉真实的市场规律。多品种多策略组合能部分缓解这个问题因为不同策略对市场的假设不一样同时被历史噪声欺骗的概率会显著下降。市场风格切换是单策略最致命的克星。一个日线级别的趋势跟踪策略在2016年到2020年的商品期货牛市里可以赚得盆满钵满但一旦进入低波动的窄幅震荡行情它就会像钝刀割肉一样来回止损。这种回撤不是策略崩了而是它赖以生存的市场状态消失了。而套利策略、日内动量策略、基本面量化策略在不同市场状态下的表现各不相同组合起来才有机会在不同行情阶段都有策略在赚钱。资金曲线的心理压力很多人忽视了。真实交易中一个单策略的回撤如果超过30%策略开发者往往会在底部区域手动干预甚至停掉策略而恰恰这时候往往是该策略的转折点。多策略组合在没有降低各策略期望收益的前提下通过分散降低了组合回撤幅度让人扛得住、拿得稳这才是组合优化的核心价值。1.2 组合优化的本质不是分散而是互补很多人做多策略组合时有个误区以为往组合里塞的策略越多越好觉得东边不亮西边亮。这种思路有一定道理但真正的组合优化关键不在于策略数量而在于策略之间的相关性结构。按我的经验比较理想的组合结构是这样的两到三个趋势类策略负责捕捉大行情两到三个套利或截面类策略负责平滑日常波动。趋势策略在极端行情中提供爆发力但平时会频繁小亏套利策略赚的是相对回归的钱波动小但稳定。这两类策略的相关性天然偏低组合起来后资金曲线的平滑度会有质的提升。这里要特别强调一个概念——策略相关性不是固定不变的。很多人在回测时算过各策略收益序列的相关系数比如0.3觉得这个组合很分散但实盘中相关系数在极端行情下会系统性上升。2008年、2020年3月这种极端行情里几乎所有的量化策略都在同时亏钱因为流动性突然枯竭市场结构瞬间扭曲。所以组合优化时不能只看平均相关性也要考察策略在尾部场景下的相关性是否可接受。多策略资金分配方法的本质就是要在这些互补策略之间找到一组权重让组合整体在风险和收益之间达到最佳平衡。这个权重不是拍脑袋定下来的而是需要通过定量方法计算、结合实盘约束动态调整的。2. 资金分配的核心算法选型2.1 从等权到波动率倒数入门到进阶多策略资金分配最简单的方法自然就是等权分配。比如你有三个策略每个策略分到总资金的三分之一。等权分配的优点就是简单、不用做任何假设但在实际使用中有个明显缺陷它默认所有策略的风险是一样的。现实中不同策略的风险水平差异很大。一个纯日内高频策略的年化波动率可能只有8%而一个隔夜趋势策略的年化波动率可能高达35%。如果给这两个策略分配等量资金波动率高的策略就会在组合中占据绝对的风险主导地位组合的整体回撤基本就由这个波动大的策略说了算分散化的效果大打折扣。等权的升级版就是波动率倒数加权。核心逻辑很简单给波动率高的策略分配更少的资金给波动率低的策略分配更多的资金让每个策略对组合风险的贡献大致相当。具体公式是权重 (1 / 策略年化波动率) / Σ(1 / 各策略年化波动率)举例来说策略A的年化波动率是10%策略B是20%那么它们的权重比就是 (1/10) / (1/10 1/20) 66.7% 对 33.3%。这样资金分配上高风险策略少分钱低风险策略多分钱组合层次的风险贡献就基本均衡了。波动率倒数加权的优势在于计算简单、逻辑清晰而且对波动率估计误差不敏感。但它没有考虑策略之间的相关性如果两个策略高度相关按波动率倒数加权后组合仍然可能在某些市场状态下同时集中回撤。所以这个方法适合作为多策略资金分配的入门起点简单可靠但离最优还有一定距离。2.2 风险平价与均值方差谁更实用风险平价比波动率倒数又进了一步它的目标是让每个策略对组合总风险贡献相等而不仅仅是按波动率单独调整权重。风险平价在计算权重时需要同时考虑各策略的波动率和两两之间的相关系数求解逻辑大致是这样目标最小化 Σ(各策略风险贡献比例 - 均衡目标)² 约束权重之和等于1权重均为非负实际操作中风险平价通常需要迭代求解不像波动率倒数那样有一组显式公式。Python里可以用 scipy.optimize.minimize 来做这个优化也可以用几个成熟的库简化计算。风险平价的好处是从组合层面做风险均衡不是简单地按波动率倒推权重因此对于策略间相关性显著的情况风险平价往往能给出更合理的分配。均值方差优化是马科维茨的经典理论目标是让组合在给定风险水平下期望收益最大化。理论上这是最严谨的框架但在期货多策略资金分配的实践中我反而不太推荐使用完整的均值方差优化原因很现实均值方差优化对期望收益的估计极其敏感。只要你在估计策略年化收益时偏差几个百分点优化器算出的权重就会剧烈变化经常出现把所有资金压到一个策略上的极端解。风险平价不需要估计期望收益只依赖波动率和相关系数而波动率相对于期望收益来说更容易被准确估计。所以我的经验是均值方差优化的思想可以借鉴但交付给实盘的资金分配方案用风险平价或波动率倒数加权这类基于风险的分配方法会更稳健。这也是为什么风险平价在机构里越来越流行的原因。2.3 凯利公式在期货策略资金分配中的变体凯利公式在交易圈子里很有名它的原始形式是解决下注比例问题的在胜率和赔率已知的情况下计算出使长期资金增长率最大化的下注比例。公式是f* (bp - q) / b其中p是胜率q是失败概率(1-p)b是赔率盈亏比。但把凯利公式直接用在期货多策略资金分配上需要做几层变形。第一层变形是分数凯利。原始凯利公式算出的仓位通常非常激进在期货这种自带杠杆的市场里满仓凯利比例往往意味着巨大回撤风险。实际操作中一般把计算结果乘以一个分数系数比如0.25到0.5之间用来控制整体杠杆。第二层变形是把单策略的凯利公式扩展为组合层面的配置逻辑。如果多个策略之间收益是独立的组合的最优配置可以用各策略香农最优组合的思路去做本质上是求解一个带约束的凸优化问题。但如果策略之间存在相关性凯利公式在多策略场景下就失去了解析解只能退化为数值优化。我在实际项目中很少把凯利公式作为资金分配的唯一依据更多是把它作为一个仓位上限参考。比如算出来某个策略的凯利比例为总资金的40%我再结合风险评价的结果分配25%这个策略的配置就不会脱离合理区间。凯利公式的价值在于给出一个理论上的激进上限告诉你什么仓位区间是长期来看不理智的。3. 实操用Python实现多策略资金分配3.1 数据准备与策略回测结果理论讲得再多不如直接看代码和实操过程。我用一个模拟案例来演示多策略资金分配的具体实现过程。假设我现在有三个期货策略策略A螺纹钢日线趋势跟踪年化收益约15%年化波动率约25%最大回撤22%。策略B螺纹钢与热卷价差套利年化收益约8%年化波动率约10%最大回撤5%。策略C聚丙烯与聚乙烯价差套利年化收益约10%年化波动率约14%最大回撤7%。这三个策略有清晰的逻辑区别A是典型的中长趋势策略负责贡献主要收益B和C是跨品种价差套利策略波动低且与趋势策略的相关性天然比较低。这种策略结构正好是上一节说的互补型结构。回测的初始资金统一设为100万手续费和滑点按实际期货市场的平均水平扣除。回测周期选取最近的三年数据这样能覆盖到趋势、震荡、极端行情等多种市场状态。回测结果暗示一个很重要的点策略A赚总利润最多但回撤也最大策略B和C单项收益不高但资金曲线极其平滑。如果我只看单策略绩效很容易把主要资金押注到策略A上但这就是单策略思维和组合思维的差别。实际数据如下表所示策略年化收益年化波动率最大回撤夏普比例A趋势15%25%22%0.60B卷螺套8%10%5%0.67C塑化套10%14%7%0.64从单策略的夏普比例来看其实大家都差不多都在0.6到0.7之间但风险结构差异巨大。接下来要解决的核心问题是这三个策略分别分配多少资金最合适。3.2 波动率倒数加权分配器的实现首先实现最简单的波动率倒数加权。通过读取策略每日收益序列来计算各自的年化波动率然后按倒数加权计算权重最后按权重进行资金分配。代码实现如下import numpy as np import pandas as pd def annualized_volatility(daily_returns): 将日收益序列转换为年化波动率 return np.std(daily_returns, ddof1) * np.sqrt(252) def volatility_inverse_weighting(daily_returns_dict): 波动率倒数加权分配计算 参数: daily_returns_dict: dict 键是策略名称值是策略的日收益率序列(pd.Series) 返回: weights: dict 各策略的资金分配权重 # 计算各策略年化波动率 vols {} for name, returns in daily_returns_dict.items(): vols[name] annualized_volatility(returns) # 计算波动率倒数 inv_vols {name: 1/vol for name, vol in vols.items()} total_inv_vols sum(inv_vols.values()) # 归一化得到权重 weights {name: inv_vol/total_inv_vols for name, inv_vol in inv_vols.items()} return weights, vols # 模拟三组日收益序列 np.random.seed(42) n_days 756 # 三年交易日 # 策略A趋势跟踪日波动率约 25%/sqrt(252)1.57% trend_returns pd.Series(np.random.normal(0.0005, 0.0157, n_days)) # 策略B卷螺套利日波动率约 10%/sqrt(252)0.63% arb_returns_b pd.Series(np.random.normal(0.0003, 0.0063, n_days)) # 策略C塑化套利日波动率约 14%/sqrt(252)0.88% arb_returns_c pd.Series(np.random.normal(0.0004, 0.0088, n_days)) returns_dict { A趋势: trend_returns, B卷螺套: arb_returns_b, C塑化套: arb_returns_c } weights, vols volatility_inverse_weighting(returns_dict) print(各策略年化波动率) for name, vol in vols.items(): print(f {name}: {vol*100:.2f}%) print(\n各策略资金分配权重) for name, w in weights.items(): print(f {name}: {w*100:.2f}%)换算成实际资金分配假设总资金1000万按波动率倒数加权的结果大致是策略B约317万C约252万A约227万不对我重新算一下。A波动率25%B波动率10%C波动率14%倒数分别是0.04、0.1、0.0714总和0.2114。权重分别为A 18.9%、B 47.3%、C 33.8%。所以A得189万B得473万C得338万。A虽然预期收益最高但因为波动率高反而只分到最小份额这就是基于风险的分配逻辑和基于收益直觉的区别。3.3 风险平价权重计算的迭代求解波动率倒数虽然有效但它没有利用策略间的相关性信息。更进一步我需要用以下几个步骤实现风险平价组合第一步估算三个策略收益序列的协方差矩阵。这里的核心是用历史收益数据计算注意要保证数据的长度足够稳定估计协方差矩阵。样本协方差矩阵在策略数量少、数据量充足时表现尚可但一旦策略数量增多比如超过10个就需要考虑Ledoit-Wolf收缩估计或者因子模型来降低估计误差。第二步用迭代优化的方式求解权重。常用的方法是把风险平价问题转化为凸优化问题求解。我这里把核心求解部分简单示范如下from scipy.optimize import minimize def risk_parity_weights(cov_matrix): 通过最优化计算风险平价权重 参数: cov_matrix: np.ndarray 策略收益的协方差矩阵 返回: weights: np.ndarray 风险平价权重 n len(cov_matrix) def risk_contribution(weights): 计算各策略的风险贡献 portfolio_vol np.sqrt(weights cov_matrix weights) marginal_contrib (cov_matrix weights) / portfolio_vol return weights * marginal_contrib def objective(weights): 目标函数各策略风险贡献的差异平方和 rc risk_contribution(weights) target np.mean(rc) return np.sum((rc - target) ** 2) # 约束条件权重和1各权重0 constraints [ {type: eq, fun: lambda x: np.sum(x) - 1} ] bounds [(0, 1) for _ in range(n)] # 初始值用等权 init_weights np.ones(n) / n result minimize( objective, init_weights, methodSLSQP, boundsbounds, constraintsconstraints, options{maxiter: 500, ftol: 1e-12} ) return result.x # 构建协方差矩阵模拟 # 注意这里用模拟数据示意实盘中直接用历史收益序列计算即可 cov_matrix np.array([ [0.000246, 0.000012, 0.000008], [0.000012, 0.000040, 0.000005], [0.000008, 0.000005, 0.000078] ]) weights_rp risk_parity_weights(cov_matrix) print(风险平价权重, weights_rp)风险平价与波动率倒数加权在策略相关性接近零的时候结果会非常接近。但在策略间存在正相关性的情况下风险平价会自动调低相关策略的权重防止风险在同一维度重复堆积。以我的模拟数据为例A和B之间相关系数大概0.12B和C大约0.1A和C约0.05这时候风险平价算出的权重和波动率倒数已经有一些差异了风险平价会给波动更小且与其它策略相关性更低的策略略高一点权重。3.4 实际资金分配流程与再平衡机制算出静态权重只是第一步实操中真正的难点在于动态更新和再平衡。市场状态在变化策略的波动率在变化策略之间的相关性也在变化静态权重没法长期保持最优。我的标准流程是每周五收盘后重新计算一次各策略最近60个交易日的波动率和协方差矩阵然后滚动更新目标权重。这个60日窗口既足够近以保证反映当前市场状态又足够长以平滑单日异常值的影响。再平衡的执行逻辑是带缓冲区的新算出的目标权重与当前实际权重的偏差超过一定阈值比如正负5个百分点才执行调仓否则保持现状。这么做不是为了偷懒而是为了避免频繁调仓引发不必要的交易成本和摩擦。资金分配调仓通常涉及转入或转出策略保证金账户频繁操作不仅手续费高还可能在某些流动性差的时段产生额外的滑点损失。再平衡的执行逻辑用伪代码表示def rebalance_check(current_weights, target_weights, threshold0.05): 判断是否需要再平衡 参数: current_weights: dict 当前各策略实际资金占比 target_weights: dict 基于风险平价计算的各策略目标权重 threshold: float 触发再平衡的权重偏离阈值 返回: bool: 是否执行再平衡 for name in target_weights.keys(): deviation abs(current_weights[name] - target_weights[name]) if deviation threshold: return True return False执行再平衡时的具体操作也有讲究。如果资金从一个策略转出到另一个策略转出时要考虑策略当前是否持有仓位。假设策略A当前满仓螺纹钢多单如果要从A调出资金就需要先减持一部分仓位这个过程会产生冲击成本和滑点。比较稳妥的做法是设置资金调整的每日上限比如单日最多调整总资金的5%剩余部分通过后续几天逐步完成。这样虽然拉长了调整周期但有效控制了交易成本。4. 实盘使用中必须注意的细节与纪律4.1 波动率估计的偏差来源波动率估计是整个资金分配模型的地基地基歪了权重再好都是空中楼阁。实践中我发现波动率估计有三个主要偏差来源值得警惕。第一个是样本窗口长度选择带来的偏差。太短的窗口比如10个交易日对近期波动敏感但估计噪声很大太长的窗口比如250个交易日足够平滑但对市场状态变化反应太慢。我常用的方式是用60日指数加权移动平均来估计波动率给近期数据更高的权重既兼顾了平滑性又保留了敏感性。第二个是异常值干扰。期货市场偶尔会出现单日涨跌停或极端行情这类异常值会让普通标准差估计严重失真。处理手段是波动率估计前做缩尾处理winsorization把日收益率限制在比如正负5个标准差以内防止单日极端值污染整个波动率估计。第三个是期货合约换月带来的跳空。移仓换月时新旧主力合约之间存在价差这个价差会被计入当日收益造成日收益序列出现异常跳动。我的处理方式是在策略日收益序列中剔除换月当天的异常收益或者在回测数据拼接时就处理好主力合约的价格调整。这个问题新手很容易忽略但它对波动率估计的污染效果相当明显。4.2 相关性在极端行情下会突然失效前面提过正常市场状态下策略间相关性可能都不高但在极端行情下相关性会阶梯式上升这是多策略资金分配方案中一个很难完全绕开的风险。以趋势策略和套利策略为例正常行情下它们相关性可能只有0.1左右。但当市场出现连续跌停、流动性枯竭时所有策略都会因为无法顺利止损而同时录得大规模回撤相关性瞬间向1靠拢。这就是所谓的流动性危机中的相关性崩塌是资金分配模型最不适用的场景。针对这个问题我一般采取三方面措施。第一在每个策略层面设置严格的单日最大亏损熔断机制假设单日账户回撤超过3%立刻无条件平掉所有仓位。第二在组合层面预留5%到10%的现金缓冲这部分资金不参与任何策略分配用于极端行情下的保证金追加避免被迫在不利价位砍仓。第三在计算相关性的数据中加入对尾部区域的加权也就是说在风险平价优化中不仅考虑平均相关性还考虑在历史尾部行情中策略的相关性表现。4.3 保证金约束下的资金分配修正期货交易区别于股票的地方在于保证金制度这个特性对资金分配有直接影响。比如你给趋势策略分配了300万资金但这300万里真正作为保证金被交易所占用的可能只有60万其余都是以可用资金的形式闲置在账户里的。这意味着多策略资金分配不只是简单的每个策略分多少钱还要考虑各策略的保证金占用比例。如果一个策略的保证金占用率是40%另一个只有10%同样的资金规模带来的实际风险敞口完全不同。实盘中我倾向于把资金分配分为两层来做先按风险模型计算出各策略的目标权重然后检查各策略需要的保证金总额是否超过账户总资金可以支撑的上限。如果保证金占用过高就对高保证金占用率的策略降权来降低组合整体杠杆如果占用很低可以考虑适度提升仓位或增加现金缓冲。简而言之资金分配的最终结果必须同时满足风险约束和现金约束模型优化的结果一般是理想化状态实盘执行时还要做实际约束的处理。4.4 再平衡频率过度调优反而是减分项再平衡是资金分配模型从理论走向实战的关键环节但过度的再平衡调整往往会降低策略净收益。资金分配模型计算的权重是历史数据的函数本身存在估计误差。如果每周调仓、甚至有更短的周期敏感地调整仓位往往会因为过度拟合近期的波动率变化而不断放大调仓成本。反复测试后发现月度再平衡加上5%偏差阈值的设计比只看波动率倒数调权的效果要稳定得多主要原因是减少了无谓的资金转移摩擦成本。另一个容易忽略的细节是策略内仓位与策略间资金分配的耦合。资金分配层面调仓时要确认策略内部正好满足新建仓条件而不是为了调整权重去强行开仓或平仓。我在实战中会在资金分配层和策略信号层之间设一个协调机制只有当策略信号本身触发开平仓动作时才允许资金分配层的权重调整同步执行否则资金调整延迟到下一次策略信号触发时再进行。5. 从实操到优化迭代的进阶路径5.1 把组合绩效归因做细资金分配方案上线后定期做绩效归因是持续优化的基础。我每个季度会做一次完整的组合归因分析核心是拆解以下几个问题第一个问题是组合的超额收益有多少来自策略本身的alpha有多少来自资金分配层的择时。拆解方法是用固定权重比如等权或上一期权重重新计算一个基准组合与动态分配的组合对比收益差异。如果动态分配的收益长期跑不赢静态权重说明资金分配层的择时没有正贡献应该简化模型把更多精力放在提升策略本身的alpha上。第二个问题是各策略的实际风险贡献是否和目标一致。时不时会出现目标权重没问题、但某策略的实际风险贡献显著超比例的情况往往是因为策略实盘表现与回测的波动率假设出现了系统性偏差。这时候我会检查策略代码逻辑是否在实盘环境出现变化比如滑点比例上升、成交延迟增加等。5.2 资金分配模型自身的参数风险很多人在做策略组合优化时把注意力全放在策略上忽略了资金分配模型本身也有参数需要管理和警惕。比如波动率倒数加权中的波动率窗口长度风险平价的求解精度与约束条件再平衡的阈值设置这些参数的不同选择会导致完全不同的实盘资金曲线。我的建议是资金分配模型的参数一旦设定就不要频繁调整。模型参数与策略参数的逻辑是相似的——频繁调整意味着你在拟合历史数据的特定阶段容易过拟合。每半年或一年回顾一次模型的稳定性做一次敏感性分析看看波动率窗口改成30天或90天再平衡阈值改成3%或8%组合的资金曲线和风险指标是否会发生剧烈变化。如果结果对参数极其敏感说明模型本身不够稳健这个时候应该考虑换更简化的分配模型而不是继续调参数去适配历史数据。从长远看多策略资金分配不是一次性的工程而是一个持续迭代的过程。市场结构在演化策略容量和相关性在变化资金分配模型需要跟着周期性的复盘和调整才能持续有效。但切记不要陷入不断优化参数的陷阱——模型的稳定性往往比理论上的最优性更值钱。我在实盘中最深刻的体会是资金分配的价值不在于把组合的收益做到最高而在于把组合的风险结构做得更可承受。三个0.6夏普比例的策略通过合理的资金分配组合在一起组合的夏普比例往往能提升到0.8甚至更高同时最大回撤显著低于任何单策略。有了这样的组合结构和分配纪律逐年的资金曲线虽然没什么惊艳的爆发力但胜在稳定。这大概就是多策略资金分配方法真正让人睡得着觉的地方。