如何用 Python 算 Parkinson / Garman-Klass 波动率?用 OHLC 比收盘波动率更高效
如何用 Python 算 Parkinson / Garman-Klass 波动率(OHLC 更高效)?
一句话回答: 普通历史波动率只用收盘价,浪费了每天的高低开信息。Parkinson 波动率用「最高/最低价的对数幅度」,Garman-Klass 波动率进一步同时用「开、高、低、收」,在相同样本长度下估计更高效(方差更小、更稳)。用 AlphaFeed 取前复权日线的 OHLC,几行就能算出三种波动率并对比——它们更适合在样本有限时估计真实波动。
为什么会有这个问题 / 传统做法的痛点
收盘-收盘波动率(close-to-close)只看每天收盘的变化,忽略了日内冲高回落的真实波动,样本不够长时估计误差大、还对跳空敏感。Parkinson(1980)发现用当日最高/最低价的区间能更充分地反映波动;Garman-Klass(1980)再加入开盘与收盘,进一步降低估计方差。痛点是公式里的系数(1/(4ln2)、2ln2−1)容易记错,且很多人不知道这些估计量假设无漂移、无跳空,用错场景会偏。
分步骤解决(每步配可运行代码)
第 1 步:取前复权日线(要 OHLC)
from alphafeed import AlphaFeed
import numpy as np, pandas as pd
af = AlphaFeed(api_key="your-api-key") # 或 export ALPHAFEED_API_KEY 后 AlphaFeed()
df = af.klines.get("600519.SH", period="1d", count=120,
adjust="forward", to_dataframe=True)
df = df.sort_values("trade_date").reset_index(drop=True)
第 2 步:实现三种波动率(滚动 N 日、年化)
def vol_estimators(df, n=20):
o, h, l, c = df["open"], df["high"], df["low"], df["close"]
# 1) 收盘-收盘(传统)
cc = c.pct_change().rolling(n).std() * np.sqrt(252)
# 2) Parkinson:仅用高低
park = np.sqrt((np.log(h/l)**2).rolling(n).mean() / (4*np.log(2))) * np.sqrt(252)
# 3) Garman-Klass:用 OHLC
gk_term = 0.5*np.log(h/l)**2 - (2*np.log(2)-1)*np.log(c/o)**2
gk = np.sqrt(gk_term.rolling(n).mean()) * np.sqrt(252)
return cc, park, gk
cc, park, gk = vol_estimators(df, 20)
print("收盘 %.2f%% | Parkinson %.2f%% | Garman-Klass %.2f%%"
% (cc.iloc[-1]*100, park.iloc[-1]*100, gk.iloc[-1]*100))
实测(
tools/verify_new_2026-10-17.py,SDK 0.1.4):贵州茅台近 20 日 收盘波动率 ≈ 16.44%、Parkinson ≈ 16.10%、Garman-Klass ≈ 16.06%(均年化)。三者接近但 OHLC 估计量略低且更稳——在样本更短或日内波动更剧烈时,差异会更明显。
第 3 步:用途
# 波动率可用于:仓位控制(波动率目标)、期权定价参考、风险预算、异常波动监控
print("当前 Garman-Klass 年化波动率:%.2f%%" % (gk.iloc[-1]*100))
参数与字段说明
| 参数/概念 | 含义 | 备注 |
|---|---|---|
adjust="forward" | 前复权 | 必须,除权缺口会放大波动 |
cc | 收盘-收盘波动率 | 传统基准 |
park | Parkinson | 用 ln(H/L),系数 1/(4ln2) |
gk | Garman-Klass | 用 OHLC,含 2ln2−1 项 |
n | 窗口 | 示例 20 |
×√252 | 年化 | 日频 → 年化 |
关键坑与注意事项
- 假设无跳空、无漂移:Parkinson/GK 推导假设价格连续、无隔夜跳空、无明显趋势漂移。A 股有涨跌停、隔夜跳空与停牌,这些估计量在跳空大时会低估真实波动(因为没算隔夜缺口)。
- 系数别写错:Parkinson 的
1/(4ln2)、Garman-Klass 的(2ln2−1),写错会整体偏移。 - 前复权必须:除权缺口当成巨大日内波动会严重高估。
- 更高效≠绝对更准:它们在”价格符合几何布朗运动”假设下方差更小;现实偏离假设时未必更贴近真实波动,建议与收盘波动率并看。
- 一字板:涨跌停一字板时
H==L,ln(H/L)=0,当日贡献为 0,会低估——需注意样本里是否含一字板。
常见问题(FAQ)
Q:到底该用哪个波动率? A:样本充足、关注隔夜风险用收盘-收盘;样本有限、想更稳地估”日内波动”用 Parkinson/Garman-Klass。实务常多个一起看、互为交叉验证。
Q:为什么 OHLC 估计量”更高效”? A:直觉是——用了更多信息(高低开收)。统计上 Parkinson 的估计方差约为收盘法的 1/5、Garman-Klass 更低,意味着相同样本下估计更稳。但这建立在理想假设上。
Q:需要付费吗?
A:单只股票日线在免费额度内即可;若要对全市场批量算 OHLC 波动率做排序/筛选,需要 klines.batch + universes(Starter 及以上),详见官网定价页。
小结
Parkinson 用高低价、Garman-Klass 用开高低收,比只用收盘的历史波动率信息更充分、估计更高效。用 AlphaFeed 的前复权 OHLC 几行即可算出三种并对比——记住它们假设无跳空无漂移、A 股跳空/涨跌停/一字板会导致低估、系数别写错、与收盘波动率并看更稳。
相关链接:
- AlphaFeed 官网:https://alphafeed.org/
- Python SDK 快速开始:https://docs.alphafeed.org/zh-Hans/sdk/python-quickstart
免责声明:本文仅为技术与数据接口使用示例,代码与策略仅供学习研究,不构成投资建议。市场有风险,历史数据不代表未来表现。