🚀 AI 一键生成 qmt 策略代码
立即体验

如何在QMT中使用bsm_iv函数计算期权隐含波动率并绘制微笑曲线?

qmt | 发布时间: 2026/8/12
以下内容由 EasyQuant 生成。

问题描述

QMT 期权定价进阶:利用 bsm_iv 实时计算隐含波动率曲面
如何在QMT中使用bsm_iv函数计算多只期权的隐含波动率并绘制波动率微笑曲线?

解决方案

QMT期权定价进阶:利用 bsm_iv 实时计算隐含波动率微笑曲线\n\n在期权交易中,隐含波动率(Implied Volatility, 简称 IV)是评估期权价格贵贱的核心指标。由于市场对不同行权价期权的避险需求不同,相同到期日的期权在不同行权价上会呈现出中间低、两边高的波动率分布,形似微笑,被称为波动率微笑曲线(Volatility Smile)。\n\n国信证券 QMT 平台内置了基于 Black-Scholes-Merton 模型的期权定价与计算接口。本文将教你如何利用 ContextInfo.bsm_iv 实时计算多只期权的隐含波动率,并绘制波动率微笑曲线。\n\n---\n\n## 1. 核心 API 介绍\n\n### (1) 计算隐含波动率:ContextInfo.bsm_iv\n* 用法ContextInfo.bsm_iv(optionType, objectPrices, strikePrice, optionPrice, riskFree, days, dividend)\n* 参数:\n * optionType:期权类型,认购为 'C',认沽为 'P'。\n * objectPrices:期权标的资产现价。\n * strikePrice:期权行权价。\n * optionPrice:期权最新市场现价。\n * riskFree:无风险收益率(如 0.03 代表 3%)。\n * days:距离到期的剩余天数。\n * dividend:标的分红率(可缺省,默认为 0)。\n\n### (2) 获取期权列表:ContextInfo.get_option_list\n* 用法ContextInfo.get_option_list(undl_code, dedate, opttype, isavailable)\n* 示例:获取 510300.SH 标的、2024年10月到期的认购期权。\n\n### (3) 获取期权详细信息:ContextInfo.get_option_detail_data\n* 用法:获取期权的行权价、到期日等静态数据。\n\n---\n\n## 2. QMT 完整策略源码\n\n以下是一个完整的 QMT Python 策略示例。该策略在盘中实时获取 510300.SH 对应月份的所有认购期权,计算其隐含波动率,并按行权价排序输出,最后展示如何使用 matplotlib 绘制微笑曲线。\n\npython\n#encoding:gbk\nimport pandas as pd\nimport numpy as np\nimport datetime\nimport matplotlib.pyplot as plt\n\ndef init(ContextInfo):\n # 设定标的资产(沪深300ETF)\n ContextInfo.underlying = '510300.SH'\n # 设定目标期权到期月份 (格式: YYYYMM)\n ContextInfo.target_month = '202410'\n # 无风险利率\n ContextInfo.rf = 0.025\n \n # 获取该月份的所有认购期权列表\n ContextInfo.option_list = ContextInfo.get_option_list(ContextInfo.underlying, ContextInfo.target_month, 'CALL')\n print(f'获取到 {ContextInfo.target_month} 认购期权共 {len(ContextInfo.option_list)} 只')\n\ndef handlebar(ContextInfo):\n if not ContextInfo.is_last_bar():\n return\n \n # 1. 获取标的最新价\n underlying_tick = ContextInfo.get_full_tick([ContextInfo.underlying])\n if not underlying_tick or ContextInfo.underlying not in underlying_tick:\n return\n underlying_price = underlying_tick[ContextInfo.underlying]['lastPrice']\n \n # 2. 获取所有期权的最新价\n option_ticks = ContextInfo.get_full_tick(ContextInfo.option_list)\n \n iv_results = []\n \n # 3. 循环计算每只期权的隐含波动率\n for option_code in ContextInfo.option_list:\n if option_code not in option_ticks:\n continue\n \n # 获取期权最新价\n opt_price = option_ticks[option_code]['lastPrice']\n if opt_price <= 0:\n continue\n \n # 获取期权详细静态数据\n detail = ContextInfo.get_option_detail_data(option_code)\n strike_price = detail['OptExercisePrice'] # 行权价\n expire_date_str = str(detail['ExpireDate']) # 到期日\n \n # 计算剩余天数\n today = datetime.date.today()\n expire_date = datetime.datetime.strptime(expire_date_str, '%Y%m%d').date()\n remaining_days = (expire_date - today).days\n \n if remaining_days <= 0:\n continue\n \n # 调用 BSM 隐含波动率计算函数\n try:\n iv = ContextInfo.bsm_iv(\n optionType='C',\n objectPrices=underlying_price,\n strikePrice=strike_price,\n optionPrice=opt_price,\n riskFree=ContextInfo.rf,\n days=remaining_days\n )\n \n if not np.isnan(iv) and iv > 0:\n iv_results.append({\n 'code': option_code,\n 'strike': strike_price,\n 'iv': iv * 100 # 转换为百分比\n })\n except Exception as e:\n pass\n \n # 4. 整理数据并排序\n if len(iv_results) > 0:\n df = pd.DataFrame(iv_results)\n df = df.sort_values(by='strike')\n print('\\n--- 实时隐含波动率数据 ---')\n print(df.to_string(index=False))\n \n # 5. 绘制波动率微笑曲线\n plt.figure(figsize=(10, 6))\n plt.plot(df['strike'], df['iv'], marker='o', linestyle='-', color='b')\n plt.title(f'{ContextInfo.underlying} Options Volatility Smile ({ContextInfo.target_month})')\n plt.xlabel('Strike Price')\n plt.ylabel('Implied Volatility (%)')\n plt.grid(True)\n plt.show()\n\n\n---\n\n## 3. 关键步骤与注意事项\n\n1. 数据补充:在运行此策略前,请确保通过 QMT 客户端的【数据管理】补充了期权标的(如 510300.SH)以及对应期权合约的日线和 Tick 历史数据。\n2. 过滤异常值:在实际交易中,深度实值或深度虚值的期权由于交易不活跃,其最新价可能无法真实反映市场定价,计算出的 IV 可能会出现 nan 或异常极值,代码中已通过 np.isnan(iv) 进行了过滤。\n3. 剩余天数计算bsm_iv 接收的 days 参数为实际自然日天数。如果期权临近到期(如剩余 1-2 天),由于时间价值极低,IV 计算会变得非常敏感,微笑曲线两端可能会出现剧烈上扬。