3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在量化投资中,资产之间的相关性往往不是恒定不变的。DCC-GARCH(Dynamic Conditional Correlation GARCH,动态条件相关系数模型) 能够有效地捕捉资产收益率之间随时间波动的相关性,这对于统计套利(如配对交易)、投资组合优化和风险管理具有极大的价值。
在 JoinQuant(聚宽)平台上,虽然 Python 的标准库中没有像 R 语言 rmgarch 那样完善的多元 GARCH 现成包,但我们完全可以通过结合 arch 库(用于单变量 GARCH 拟合)和 scipy.optimize(用于极大似然估计)来自己构建 DCC-GARCH 模型。
实现 DCC-GARCH 通常分为两步(Engle 的两步估计法):
首先,我们需要使用 JoinQuant 的 API 获取目标股票的历史价格数据并计算对数收益率。
import jqdata
import pandas as pd
import numpy as np
from arch import arch_model
import scipy.optimize as opt
# 获取两只股票的数据(例如:平安银行和万科A)
stock1 = '000001.XSHE'
stock2 = '000002.XSHE'
start_date = '2020-01-01'
end_date = '2023-01-01'
df1 = get_price(stock1, start_date=start_date, end_date=end_date, frequency='daily', fields=['close'])
df2 = get_price(stock2, start_date=start_date, end_date=end_date, frequency='daily', fields=['close'])
# 计算对数收益率
ret1 = np.log(df1['close'] / df1['close'].shift(1)).dropna() * 100
ret2 = np.log(df2['close'] / df2['close'].shift(1)).dropna() * 100
returns = pd.concat([ret1, ret2], axis=1)
returns.columns = [stock1, stock2]
使用 Python 的 arch 库对每个序列拟合 GARCH(1,1) 模型。
# 存储标准化残差和条件方差
std_resid = pd.DataFrame(index=returns.index, columns=returns.columns)
cond_vol = pd.DataFrame(index=returns.index, columns=returns.columns)
for col in returns.columns:
# 构建 GARCH(1,1) 模型,假设均值为常数
am = arch_model(returns[col], mean='Constant', vol='GARCH', p=1, q=1)
res = am.fit(disp='off')
cond_vol[col] = res.conditional_volatility
std_resid[col] = res.resid / res.conditional_volatility
这一步需要自定义似然函数并使用 scipy.optimize 求解。为了简化,以下提供 DCC 核心逻辑的伪代码框架:
# 计算标准化残差的无条件相关系数矩阵 Q_bar
Q_bar = np.cov(std_resid.T)
# 定义 DCC 似然函数 (简化版框架)
def dcc_loss(params, std_resid, Q_bar):
a, b = params[0], params[1]
T, N = std_resid.shape
# 约束条件:a > 0, b > 0, a + b < 1
if a <= 0 or b <= 0 or a + b >= 1:
return 1e10
Q_t = np.zeros((T, N, N))
Q_t[0] = Q_bar
loglik = 0.0
for t in range(1, T):
eps_t_1 = std_resid.iloc[t-1].values.reshape(-1, 1)
# DCC 演化方程
Q_t[t] = (1 - a - b) * Q_bar + a * (eps_t_1 @ eps_t_1.T) + b * Q_t[t-1]
# 计算相关系数矩阵 R_t
D_t_inv = np.diag(1 / np.sqrt(np.diag(Q_t[t])))
R_t = D_t_inv @ Q_t[t] @ D_t_inv
# 累加对数似然值 (此处省略具体的多元正态似然公式)
# loglik += ...
return -loglik
# 使用 scipy.optimize.minimize 求解最优的 a 和 b
# initial_guess = [0.05, 0.90]
# bounds = ((0.0001, 0.9999), (0.0001, 0.9999))
# result = opt.minimize(dcc_loss, initial_guess, args=(std_resid, Q_bar), bounds=bounds)
注:完整的 DCC 似然函数较为复杂,建议在 JoinQuant 研究环境中引入开源的 Python DCC-GARCH 实现脚本(如 GitHub 上的 mgarch 库)作为自定义模块调用。
一旦你计算出了两只股票(或资产)每天的动态条件相关系数 $\rho_t$,就可以构建以下类型的量化策略:
传统的配对交易依赖于协整关系的长期稳定性。结合 DCC-GARCH:
在构建投资组合时,传统的马科维茨均值-方差模型使用静态协方差矩阵。使用 DCC-GARCH:
portfolio_optimizer(投资组合优化器)中,选择 MinVariance(最小化方差)或 RiskParity(风险平价)目标函数,实现每日或每周的动态调仓,从而更敏锐地应对市场系统性风险的变化。在 JoinQuant 平台上实现 DCC-GARCH 需要一定的统计编程基础。建议先在**研究环境(Jupyter Notebook)**中利用历史数据跑通两步估计法,将计算出的动态相关系数序列保存下来,观察其与资产价差的关系。验证有效后,再将其封装为函数,引入到 handle_data 或定时运行函数中进行回测。