
2026年重磅升级已全面落地!欢迎加入专注财经数据与量化投研的【数据科学实战】知识星球!您将获取持续更新的《财经数据宝典》与《量化投研宝典》,双典协同提供系统化指引;星球内含300篇以上独有高质量文章,深度覆盖策略开发、因子分析、风险管理等核心领域,内容基本每日更新;同步推出的「量化因子专题教程」系列(含完整可运行代码与实战案例),系统详解因子构建、回测与优化全流程,并实现日更迭代。我们持续扩充独家内容资源,全方位赋能您的投研效率与专业成长。无论您是量化新手还是资深研究者,这里都是助您少走弯路、事半功倍的理想伙伴,携手共探数据驱动的投资未来!
在量化投资领域,波动率与市场收益之间的关系是最常被利用的现象之一。当波动率飙升时,市场往往下跌;当市场平静时,上涨趋势更容易持续。但你知道吗?负收益对未来波动率的放大效应,远大于同等幅度的正收益。这种不对称性被称为"杠杆效应"。
今天这篇文章将带你了解如何使用 GJR-GARCH 模型来捕捉这种不对称性,并构建一个实用的"低波动率满仓、高波动率空仓"的择时策略。即使你不打算实盘交易,这套框架也能帮你深入理解波动率建模和回测的核心要点。
标准的 GARCH 模型对正向和负向冲击的处理是对称的,而 GJR-GARCH(Glosten-Jagannathan-Runkle GARCH)模型增加了一个不对称项,公式如下:
σ²ₜ = ω + αε²ₜ₋₁ + γε²ₜ₋₁Iₜ₋₁ + βσ²ₜ₋₁
其中 Iₜ₋₁ 是一个指示变量:当 εₜ₋₁ < 0(即出现负收益)时,Iₜ₋₁ = 1,否则为 0。当 γ > 0 时,负向冲击对未来波动率的影响比正向冲击更大。这在股票市场中是被广泛验证的经验事实,因此 GJR-GARCH 特别适合用于风险管理。
这个策略的思路非常直接:
核心假设是:在市场波动剧烈时退出,可以有效降低回撤,同时在平静期捕捉大部分上涨收益。
下面是策略的核心实现。我们使用 Python 的 arch 库来拟合 GJR-GARCH 模型。
from dataclasses import dataclass@dataclassclass StrategyConfig: """策略配置参数""" ticker: str = "SPY" # 交易标的 benchmark_ticker: str = "^GSPC" # 基准指数 start_date: str = "2010-01-01" # 回测起始日期 end_date: str = "2024-12-31" # 回测结束日期 garch_window: int = 252 # GARCH 滚动窗口(交易日) vol_percentile_threshold: float = 70.0 # 波动率分位数阈值 low_vol_weight: float = 1.0 # 低波动时的仓位 high_vol_weight: float = 0.0 # 高波动时的仓位 commission_per_share: float = 0.005 # 每股佣金 min_commission: float = 1.0 # 最低佣金import numpy as npimport pandas as pdfrom arch import arch_modelclass GJRGARCHEngine: """GJR-GARCH 波动率引擎""" def __init__(self, config: StrategyConfig): self.config = config def fit_gjr_garch(self, returns: pd.Series) -> dict: """拟合 GJR-GARCH 模型""" # 创建 GJR-GARCH(1,1,1) 模型,使用 t 分布捕捉肥尾特性 model = arch_model( returns * 100, # 转换为百分比收益率 vol='Garch', p=1, # GARCH 项阶数 o=1, # 不对称项阶数(GJR 的核心) q=1, # ARCH 项阶数 dist='t' # Student-t 分布 ) result = model.fit(disp='off', show_warning=False) return { 'model': result, 'conditional_vol': result.conditional_volatility / 100, 'params': result.params } def compute_rolling_volatility(self, returns: pd.Series) -> pd.Series: """计算滚动条件波动率""" n = len(returns) window = self.config.garch_window conditional_vol = pd.Series(index=returns.index, dtype=float) for i in range(window, n): window_returns = returns.iloc[i-window:i] try: result = self.fit_gjr_garch(window_returns) # 预测未来 1 天的波动率 forecast = result['model'].forecast(horizon=1) conditional_vol.iloc[i] = np.sqrt(forecast.variance.values[-1, 0]) except: # 拟合失败时使用简单标准差作为后备 conditional_vol.iloc[i] = window_returns.std() return conditional_vol这是很多回测容易犯错的地方。如果使用整个数据集计算分位数,就会引入"前视偏差"——用未来的信息做过去的决策。正确的做法是使用扩展窗口分位数:
class RegimeClassifier: """市场状态分类器""" def __init__(self, config: StrategyConfig): self.config = config def classify_regime(self, conditional_vol: pd.Series) -> pd.Series: """基于扩展窗口分位数进行状态分类""" # 计算每个时间点相对于历史的分位数排名 expanding_percentile = conditional_vol.expanding(min_periods=20).apply( lambda x: pd.Series(x).rank(pct=True).iloc[-1] * 100, raw=False ) regime = pd.Series(index=conditional_vol.index, dtype=int) # 0 表示低波动状态,1 表示高波动状态 regime[expanding_percentile <= self.config.vol_percentile_threshold] = 0 regime[expanding_percentile > self.config.vol_percentile_threshold] = 1 return regime信号必须滞后一期,确保我们基于昨天的信息做今天的决策:
class StrategyEngine: """策略引擎""" def __init__(self, config: StrategyConfig): self.config = config def generate_signals(self, regime: pd.Series) -> pd.Series: """生成交易信号""" target_weight = pd.Series(index=regime.index, dtype=float) target_weight[regime == 0] = self.config.low_vol_weight # 低波动满仓 target_weight[regime == 1] = self.config.high_vol_weight # 高波动空仓 # 关键:信号滞后一期,避免使用当天信息 signal = target_weight.shift(1) return signal使用 2010-2024 年的 SPY 数据进行回测,结果如下:
从绝对收益来看,策略跑输了基准。这不奇怪,因为策略有约 30% 的时间处于空仓状态,错过了一些在高波动期出现的反弹。
但从风险调整后的角度看,结果就不一样了:波动率降低了 42%,最大回撤减少了 44%,夏普比率略高于基准。对于那些无法承受 30% 以上回撤的投资者来说,这种取舍是值得的。
在 15 年间共发生了约 78 次状态切换,平均每年约 5 次,并没有频繁交易的问题。
GJR-GARCH 状态切换策略展示了一种基于原理的波动率择时方法。通过尊重波动率冲击的不对称性,并严格避免前视偏差,我们构建了一个能够显著降低风险的策略框架。
它能跑赢买入持有吗?从绝对收益来看,不能。但从回撤调整后的指标来看,它具有竞争力。对于那些在 30% 以上回撤时难以安睡的投资者来说,这种取舍可能正是他们需要的。
这套代码和分析仅供学习参考。过去的表现不代表未来的结果,在实施任何交易策略之前,请进行充分的研究并考虑咨询专业的财务顾问。
2026年全面升级已落地!【数据科学实战】知识星球核心权益如下:
星球已沉淀丰富内容生态——涵盖量化文章专题教程库、因子日更系列、高频数据集、PyBroker实战课程、专家深度分享与实时答疑服务。无论您是初探量化的学习者,还是深耕领域的从业者,这里都是助您少走弯路、高效成长的理想平台。诚邀加入,共探数据驱动的投资未来!
好文推荐
1. 用 Python 打造股票预测系统:Transformer 模型教程(一)
2. 用 Python 打造股票预测系统:Transformer 模型教程(二)
3. 用 Python 打造股票预测系统:Transformer 模型教程(三)
4. 用 Python 打造股票预测系统:Transformer 模型教程(完结)
6. YOLO 也能预测股市涨跌?计算机视觉在股票市场预测中的应用
9. Python 量化投资利器:Ridge、Lasso 和 Elastic Net 回归详解
好书推荐