13、多产品组合利润优化:相关性矩阵、组合VaR、资本配置优化
做市商手里通常不止一个产品。你想想看,我们同时做ETF期权、股指期货、甚至还有几个商品期货的做市。每个产品单独看都赚钱,但合在一起,风险就复杂了。
我早年吃过一次亏。当时几个产品单独看风险都不大,结果市场一波动,它们居然一起跌。那天的亏损,让我记住了组合风险管理的分量。今天我们就聊聊多产品组合的利润优化,核心就是三件事:相关性矩阵、组合VaR、资本配置。
13.1 为什么单产品风控不够用?
单产品做市,你盯着自己的希腊字母就行。Delta大了就对冲,Gamma高了就小心。但多产品组合,问题就来了——产品之间会互相影响。
举个简单的例子:
- 你同时做多沪深300ETF期权和做空沪深300股指期货
- 表面上看,两个头寸方向相反,风险对冲了
- 但实际呢?期权有非线性特征,期货是线性的
- 市场大涨时,期权Gamma会放大收益,期货只是线性亏损
- 结果组合风险并不像你想象的那么小
这就是相关性在作怪。产品之间的相关性不是固定的,它会随着市场状态变化。我习惯用滚动窗口计算相关性矩阵,而不是用全样本的静态数据。
13.2 相关性矩阵:从数据到洞察
相关性矩阵说白了就是一个表格,告诉你每两个产品之间是怎么联动的。值在-1到1之间,1代表完全同向,-1代表完全反向,0代表没关系。
但这里有个坑。我记得有一次,我用日收益率算相关性,结果发现两个产品相关性高达0.85。我差点就以为它们是一回事。后来我换成15分钟的高频数据算,相关性只有0.3。为什么?因为日线掩盖了日内波动的细节。
我建议的做法是:
- 选择合适的时间窗口:做市商关注的是日内风险,用30分钟或1小时的收益率更合适
- 滚动计算:用过去20个交易日的窗口,每天更新一次相关性矩阵
- 关注极端相关性:市场压力下,相关性会急剧上升。我习惯单独算一个“压力相关性矩阵”,只用市场大跌时的数据
下面是一个简单的Python示例,计算两个产品的滚动相关性:
import numpy as np
import pandas as pd
# 假设有两个产品的收益率序列
returns_product1 = np.random.randn(1000) * 0.01
returns_product2 = np.random.randn(1000) * 0.01
# 滚动计算相关性,窗口为50个数据点
window = 50
rolling_corr = []
for i in range(window, len(returns_product1)):
corr = np.corrcoef(
returns_product1[i-window:i],
returns_product2[i-window:i]
)[0, 1]
rolling_corr.append(corr)
# 看看最近的相关性
print(f"最近的相关性: {rolling_corr[-1]:.3f}")
13.3 组合VaR:把风险量化出来
有了相关性矩阵,我们就可以算组合VaR了。VaR(Value at Risk)就是“在给定置信水平下,未来一段时间内可能的最大损失”。
组合VaR的计算公式其实不复杂:
组合VaR = sqrt( w^T * Σ * w ) * z * sqrt(T)
其中:
w = 各产品的权重向量
Σ = 协方差矩阵(由相关性矩阵和标准差算出)
z = 置信水平对应的分位数(95%对应1.645,99%对应2.326)
T = 持有期(天数)
但这里有个问题。这个公式假设收益率是正态分布的。现实中的数据往往有厚尾特征——极端事件发生的概率比正态分布预测的要高。我见过太多人用这个公式算出来VaR是100万,结果一天亏了300万。
所以我建议用历史模拟法算VaR。方法很简单:
- 取过去500个交易日的组合收益率数据
- 按收益率从小到大排序
- 取第5%分位数(95%置信水平)对应的值
这个方法不需要假设分布,直接看历史数据。虽然也有缺点(历史不会完全重复),但至少比纯正态假设靠谱。
13.4 资本配置优化:把钱放到最赚钱的地方
做市商有资本金限制。你不能把所有钱都押在一个产品上。资本配置优化的目标就是:在给定风险预算(比如组合VaR不超过1000万)的前提下,最大化预期收益。
这个问题可以转化为一个优化问题:
最大化: 预期收益 = w^T * μ
约束条件: 组合VaR ≤ 风险预算
w^T * 1 = 1 (权重之和为1)
w_i ≥ 0 (不允许做空,视情况而定)
其中μ是各产品的预期收益率向量。但这里有个现实问题——预期收益率很难准确估计。我见过有人用历史平均收益率,结果优化出来的权重全集中在过去涨得好的产品上,然后市场风格一变就亏惨了。
我个人的做法是:
- 用隐含波动率的变化来估计预期收益,而不是历史收益率
- 加入“分散度约束”,限制单个产品的最大权重不超过30%
- 定期再平衡,比如每周调整一次权重
下面是一个简单的优化示例,用scipy求解:
from scipy.optimize import minimize
import numpy as np
# 假设有3个产品
expected_returns = np.array([0.05, 0.03, 0.04]) # 预期收益率
cov_matrix = np.array([
[0.01, 0.002, 0.001],
[0.002, 0.008, 0.0015],
[0.001, 0.0015, 0.009]
]) # 协方差矩阵
risk_budget = 0.02 # 风险预算(2%的VaR)
def portfolio_var(weights):
return np.sqrt(weights.T @ cov_matrix @ weights)
def objective(weights):
return -weights.T @ expected_returns # 最大化收益 = 最小化负收益
# 约束条件
constraints = [
{'type': 'eq', 'fun': lambda w: np.sum(w) - 1}, # 权重之和为1
{'type': 'ineq', 'fun': lambda w: risk_budget - portfolio_var(w)} # VaR不超过预算
]
# 初始权重
initial_weights = np.array([1/3, 1/3, 1/3])
# 求解
result = minimize(objective, initial_weights, constraints=constraints)
print(f"最优权重: {result.x}")
print(f"组合VaR: {portfolio_var(result.x):.4f}")
13.5 实战中的避坑指南
说了这么多,最后分享几个我踩过的坑:
- 相关性会突变:2020年3月,几乎所有资产的相关性都飙到了0.8以上。平时算的分散化效果,在危机时刻基本失效。我后来加了一个“压力测试”模块,专门模拟极端情况。
- 不要过度优化:有一次我优化出来的权重是47.3%、32.1%、20.6%,看起来特别精确。结果第二天市场一波动,这些数字就全变了。我现在只保留到整数百分比,给自己留点容错空间。
- 交易成本是隐形的杀手:优化模型通常不考虑交易成本。但实际做市时,调整头寸是要花钱的。我建议在优化目标中加入一个“换手率惩罚项”,避免频繁调整。
嗯,多产品组合的利润优化,说到底就是在风险和收益之间找平衡。相关性矩阵给你地图,组合VaR给你指南针,资本配置优化就是你的路线规划。三者缺一不可。
最后说一句,这套方法不是万能的。市场永远有黑天鹅。但有了相关性矩阵、组合VaR和资本配置优化,至少你能在大部分时间里,把风险控制在可接受的范围内。剩下的,就看你的经验和运气了。