🚀 AI 一键生成 qmt 策略代码

QMT API 教程:使用 bsm_price 计算期权理论价格

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

问题描述

怎么在策略里计算期权的 BSM 理论价格?

解决方案

在 QMT 策略中计算期权的 BSM(Black-Scholes-Merton)理论价格,可以直接使用平台内置的 ContextInfo.bsm_price() 函数。

该函数基于 BSM 模型,通过输入标的价格、行权价、无风险利率、波动率、剩余天数等参数,快速计算出期权的理论价格。

核心函数说明

函数名: ContextInfo.bsm_price(optionType, objectPrices, strikePrice, riskFree, sigma, days, dividend)

参数详解:

  1. optionType (str): 期权类型。认购期权为 'C',认沽期权为 'P'
  2. objectPrices (float/list): 期权标的资产的当前价格。
  3. strikePrice (float): 期权的行权价。
  4. riskFree (float): 无风险利率(年化,例如 3% 写作 0.03)。
  5. sigma (float): 标的资产的年化波动率(例如 20% 写作 0.2)。
  6. days (float): 距离到期日的剩余天数。
  7. dividend (float): 标的分红率(通常填 0)。

完整策略代码示例

以下代码展示了如何获取期权的基础信息(行权价、到期日、标的代码),获取标的实时价格,计算剩余天数,并最终调用 BSM 公式计算理论价格。

# -*- coding: gbk -*-
import datetime
import numpy as np

def init(ContextInfo):
    # 设置要计算的期权代码 (此处以某上证50ETF期权为例,实际使用请替换为有效合约)
    # 注意:请确保该合约在回测或实盘的时间段内是存在的
    ContextInfo.option_code = '10005264.SHO' 
    
    # 设置无风险利率 (例如 2.5%)
    ContextInfo.risk_free_rate = 0.025
    
    # 设置预估波动率 (例如 20%)
    # 注意:实际策略中,波动率通常需要根据历史数据计算(历史波动率)或使用隐含波动率
    ContextInfo.sigma = 0.20

def handlebar(ContextInfo):
    # 仅在最后一根K线(实时行情或回测当前步)计算,避免重复打印
    if not ContextInfo.is_last_bar():
        return

    # 1. 获取期权详细信息 (行权价、到期日、标的代码等)
    # get_option_detail_data 返回字典,包含 OptExercisePrice, ExpireDate, OptUndlCode 等
    detail = ContextInfo.get_option_detail_data(ContextInfo.option_code)
    
    if not detail:
        print(f"未获取到合约 {ContextInfo.option_code} 的详细信息")
        return

    strike_price = detail['OptExercisePrice']       # 行权价
    expire_date_str = str(detail['ExpireDate'])     # 到期日 (格式 YYYYMMDD)
    undl_code = detail['OptUndlCode'] + '.' + detail['OptUndlMarket'] # 标的代码
    opt_type_raw = detail['optType']                # 类型 CALL 或 PUT
    
    # 转换期权类型格式为 BSM 函数需要的 'C' 或 'P'
    bsm_opt_type = 'C' if opt_type_raw == 'CALL' else 'P'

    # 2. 获取标的资产最新价格
    # 使用 get_market_data_ex 获取标的最新收盘价
    market_data = ContextInfo.get_market_data_ex(
        ['close'], 
        [undl_code], 
        period='1d', 
        count=1, 
        subscribe=True
    )
    
    if undl_code not in market_data or market_data[undl_code].empty:
        print(f"未获取到标的 {undl_code} 的行情数据")
        return
        
    undl_price = market_data[undl_code].iloc[-1]['close']

    # 3. 计算剩余天数 (Days)
    # 获取当前回测或实盘的时间
    current_timetag = ContextInfo.get_bar_timetag(ContextInfo.barpos)
    current_date = datetime.datetime.fromtimestamp(current_timetag / 1000)
    
    # 解析到期日
    expire_date = datetime.datetime.strptime(expire_date_str, '%Y%m%d')
    
    # 计算差值
    delta = expire_date - current_date
    days_remaining = delta.days + (delta.seconds / 86400.0)
    
    # 如果已经过期,不再计算
    if days_remaining <= 0:
        print(f"合约 {ContextInfo.option_code} 已过期")
        return

    # 4. 调用 BSM 公式计算理论价格
    # 参数:类型, 标的价格, 行权价, 无风险利率, 波动率, 剩余天数, 分红率
    theoretical_price = ContextInfo.bsm_price(
        bsm_opt_type, 
        undl_price, 
        strike_price, 
        ContextInfo.risk_free_rate, 
        ContextInfo.sigma, 
        days_remaining, 
        0  # 分红率设为0
    )

    print("=" * 30)
    print(f"期权代码: {ContextInfo.option_code}")
    print(f"当前时间: {current_date}")
    print(f"标的价格: {undl_price:.4f}")
    print(f"行权价格: {strike_price:.4f}")
    print(f"剩余天数: {days_remaining:.2f} 天")
    print(f"BSM理论价: {theoretical_price:.4f}")
    print("=" * 30)

关键点解析

  1. 数据获取 (get_option_detail_data):

    • 这是计算 BSM 的前提,必须通过此接口获取期权的行权价 (OptExercisePrice)到期日 (ExpireDate)
    • 同时需要获取 标的代码 (OptUndlCode) 以便查询标的现价。
  2. 剩余天数计算:

    • BSM 模型中的 days 参数通常指剩余的自然日天数。
    • 代码中通过 ContextInfo.get_bar_timetag 获取当前策略运行的时间,并与到期日进行减法运算得出。
  3. 波动率 (sigma):

    • 在上述示例中,波动率被硬编码为 0.20 (20%)。
    • 在实际量化策略中,你通常需要编写额外的逻辑来计算历史波动率(使用标的历史收盘价计算标准差),或者使用 ContextInfo.get_option_iv(optioncode) 获取市场的隐含波动率作为参考。
  4. 无风险利率 (riskFree):

    • 可以使用固定值(如国债收益率),也可以通过 ContextInfo.get_risk_free_rate(index) 动态获取。

Q&A

Q: 如何获取期权的实时隐含波动率而不是自己设定波动率?
A: 可以使用 ContextInfo.get_option_iv(optioncode) 接口。例如:iv = ContextInfo.get_option_iv(ContextInfo.option_code),然后将 iv 传入 bsm_price 函数的 sigma 参数中。

Q: bsm_price 函数计算出的价格单位是什么?
A: 计算出的价格单位与标的资产价格单位一致(通常是元)。对于 ETF 期权,通常精确到小数点后 4 位。

Q: 如果我想反推隐含波动率怎么办?
A: QMT 提供了 ContextInfo.bsm_iv(optionType, objectPrices, strikePrice, optionPrice, riskFree, days, dividend) 函数,输入期权的当前市场价格 (optionPrice) 即可反推隐含波动率。