3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
这是一个非常实用的量化分析需求。在 QMT 中,我们可以通过以下步骤实现:
ContextInfo.get_option_iv() 接口获取期权的实时隐含波动率。ContextInfo.get_option_detail_data() 查询期权对应的标的资产代码(如 ETF 或 股票)。ContextInfo.get_market_data_ex() 获取标的资产的历史收盘价。以下是完整的 Python 策略代码。你可以将其复制到 QMT 的策略编辑器中运行。
# -*- coding: gbk -*-
import numpy as np
import pandas as pd
import math
def init(ContextInfo):
# 在这里设置你想分析的期权代码
# 例如:'10004366.SHO' (假设这是某个上证50ETF购X月X合约,请根据实际情况修改)
# 注意:请确保该期权合约在当前回测或实盘时间段内是上市交易的
ContextInfo.option_code = '10004366.SHO'
# 设置计算历史波动率的周期列表 (天)
ContextInfo.periods = [30, 60, 90]
# 设置运行周期,建议在日线级别运行
ContextInfo.period = '1d'
def handlebar(ContextInfo):
# 只在最后一根K线(最新时刻)进行计算和输出,避免历史回测时重复打印
if not ContextInfo.is_last_bar():
return
option_code = ContextInfo.option_code
# 1. 获取期权的隐含波动率 (IV)
# get_option_iv 返回的是小数,例如 0.20 代表 20%
iv = ContextInfo.get_option_iv(option_code)
# 2. 获取期权详细信息,找到标的资产代码
detail = ContextInfo.get_option_detail_data(option_code)
if not detail:
print(f"错误:无法获取期权 {option_code} 的详细信息")
return
# 拼接标的代码和市场,例如 '510050' 和 'SH' -> '510050.SH'
underlying_code = detail['OptUndlCode'] + '.' + detail['OptUndlMarket']
print("=" * 50)
print(f"期权代码: {option_code}")
print(f"标的代码: {underlying_code}")
print(f"当前隐含波动率 (IV): {iv:.2%}")
print("-" * 50)
# 3. 获取标的资产的历史行情数据
# 我们需要获取足够的数据来计算最长周期(90天)的波动率
# 多取一些数据以防停牌等情况,这里取 120 个数据点
count = max(ContextInfo.periods) + 20
# 获取收盘价
market_data = ContextInfo.get_market_data_ex(
fields=['close'],
stock_code=[underlying_code],
period='1d',
count=count,
dividend_type='front' # 使用前复权数据计算收益率更准确
)
if underlying_code not in market_data or market_data[underlying_code].empty:
print(f"错误:无法获取标的 {underlying_code} 的行情数据")
return
close_prices = market_data[underlying_code]['close']
# 4. 计算历史波动率 (HV) 并比较
# 计算对数收益率: ln(Pt / Pt-1)
# np.log 是自然对数
log_returns = np.log(close_prices / close_prices.shift(1)).dropna()
print(f"{'周期(天)':<10} | {'历史波动率(HV)':<15} | {'IV - HV 差值':<15}")
print("-" * 50)
for days in ContextInfo.periods:
if len(log_returns) < days:
print(f"{days:<10} | 数据不足")
continue
# 取最近 N 天的收益率
recent_returns = log_returns.tail(days)
# 计算标准差 (std)
std_dev = np.std(recent_returns)
# 年化波动率 = 日波动率 * sqrt(252)
hv = std_dev * math.sqrt(252)
diff = iv - hv
print(f"{days:<12} | {hv:.2%} | {diff:.2%}")
print("=" * 50)
# 简单的分析逻辑
hv_30 = np.std(log_returns.tail(30)) * math.sqrt(252)
if iv > hv_30:
print(f"结论: 当前IV ({iv:.2%}) 高于过去30天HV ({hv_30:.2%}),期权可能相对昂贵。")
else:
print(f"结论: 当前IV ({iv:.2%}) 低于过去30天HV ({hv_30:.2%}),期权可能相对便宜。")
ContextInfo.get_option_iv(option_code):
ContextInfo.get_option_detail_data(option_code):
OptUndlCode 是标的代码(如 510050),OptUndlMarket 是市场代码(如 SH)。我们需要将它们拼接成 510050.SH 格式供后续行情接口使用。ContextInfo.get_market_data_ex(...):
dividend_type='front':非常重要。计算波动率时,必须使用复权价格(通常是前复权),否则分红除权造成的股价缺口会被误判为剧烈波动,导致 HV 计算虚高。波动率计算公式:
init 函数中的 ContextInfo.option_code 为你想要观察的实际期权合约代码(例如当前活跃的 ETF 期权合约)。Q: 为什么计算出来的 HV 和某些看盘软件上显示的不一样?
A: 历史波动率的计算有多种口径,差异通常来自:
Q: 如果 get_option_iv 返回 0 怎么办?
A: 这通常发生在期权合约流动性极差、刚刚上市或即将到期时。如果需要更精确的控制,可以使用 ContextInfo.bsm_iv 函数,自己传入标的价格、行权价、无风险利率等参数反推 IV。
Q: 这个脚本可以用于回测吗?
A: 可以。代码中使用了 ContextInfo.is_last_bar() 判断。如果在回测模式下,去掉这个判断,它就会在每一天的 K 线上计算当时的 IV 和当时的过去 N 天 HV,从而形成一条历史对比曲线。