返回列表 发布新帖

【QMT玩转期权】如何利用QMT计算期权希腊值

2954 9
发表于 2023-12-28 10:25:50 | 显示全部楼层 阅读模式

本帖最后由 Liwu 于 2023-12-29 11:41 编辑

不少朋友用 QMT 在玩期权,那期权最重要的一些指标,我们常叫做希腊字母值,目前QMT还没有直接提供,那我们如何才能得到呢?今天就给大家分享一个例子,先看效果:

image.png

在K线下方的指标区域,我们就很方便地显示出了该只期权对应的希腊字母值,具体的代码如下:

还有要跟大家分享的就是,迅投研

#coding:gbk
from math import log, pow,sqrt,exp,pi
from scipy import stats
import datetime

"""
计算股票期权希腊值
"""

print('-\n\n')

def init(C):
    C.target_option = C.stockcode + '.' + C.market
    option_basic_info = C.get_option_detail_data(C.target_option)
    print ('期权基本信息', option_basic_info)
    C.etf_code = option_basic_info['OptUndlCode'] + '.' + option_basic_info['OptUndlMarket']
    C.exercise_price = option_basic_info['OptExercisePrice'] #行权价格 float类型
    C.exercise_date = str(option_basic_info['ExpireDate'])
    C.rf = float(option_basic_info['OptUndlRiskFreeRate'])
    name =  C.get_stock_name(C.target_option)
    #print (11111,option_basic_info['ExpireDate'])
    C.cp = 'call'
    if '购' in name:
        C.cp = 'call'
    elif '沽' in name:
        C.cp = 'put'#认沽put 认购call str类型
    else:
        print ('认沽认购type not found')
    C.given_dividend = 0 #存续期内标的证券将付股利 默认为零 float
    print (C.exercise_price, C.exercise_date)
    #

def handlebar(C):
    try:
        d = C.barpos
        t = C.get_bar_timetag(d)
        bar_time = timetag_to_datetime(t,'%Y%m%d')
        actual_price = C.get_market_data(['close'],stock_code =[C.target_option],period=C.period)
        s = C.get_market_data(["close"],stock_code = [C.etf_code],period=C.period)
        s = round(s,4)
        k = C.exercise_price
        due_date = C.exercise_date
        t = ((datetime.datetime.strptime(due_date, "%Y%m%d") - datetime.datetime.strptime(bar_time, "%Y%m%d")).days)  / 365.0
        print ('days',((datetime.datetime.strptime(due_date, "%Y%m%d") - datetime.datetime.strptime(bar_time, "%Y%m%d")).days))
        print ('t', t)
        r = C.rf
        divid_rate = C.given_dividend / s
        cp = C.cp
        iv = calculate_implied_volatility(s,k,t,r,divid_rate,actual_price,C.cp)
        if iv == 0:
            print (bar_time,'iv = 0')
            return
        C.paint('iv',iv,-1,0)
        print((bar_time, 's',s,'actual_price',actual_price,'k',k,'t',t,'r',r,'divid_rate',divid_rate,'iv',iv)) 
        d1_result=d1(s,k,t,r,divid_rate,iv)
        d2_result=d2(s,k,t,r,divid_rate,iv)
        delta_result=delta(s,k,t,r,divid_rate,iv,cp)
        theta_result=theta(s,k,t,r,divid_rate,iv,cp)
        gamma_result=gamma(s,k,t,r,divid_rate,iv)
        vega_result= vega(s,k,t,r,divid_rate,iv)
        rho_result=rho(s,k,t,r,divid_rate,iv,cp)
        print ('d1_result',d1_result)
        print ('d2_result',d2_result)
        print ('delta_result',delta_result)
        print ('theta_result',theta_result)
        print ('gamma_result',gamma_result)
        print ('vega_result',vega_result)
        print ('rho_result',rho_result)
        if C.is_last_bar():
            print(1111, s, k, t, r, iv)
        C.paint('delta',delta_result,-1,0)
        C.paint('theta',theta_result,-1,0)
        C.paint('gamma',gamma_result,-1,0)
        C.paint('vega',vega_result,-1,0)
        C.paint('rho',rho_result,-1,0)
    except:
        import traceback
        print(bar_time, traceback.format_exc())

def get_fourth_wednesday(year, month):
    """
    获取指定月份第四个周三
    """
    n = 0
    for i in range(31):
        delta = datetime.timedelta(days=i)
        exercise_date = datetime.datetime(year, month, 1) + delta
        if exercise_date.weekday() == 2 and n < 3:
            n += 1
            continue
        if exercise_date.weekday() == 2 and n == 3:
            return exercise_date.strftime('%Y%m%d')

def d1(s,k,t,r,d,sigma):
    """计算BS price的中间变量"""
    result = (log(s/k) + (r-d) * t) / (sigma * sqrt(t)) + 0.5 * sigma * sqrt(t)
    return result

def d2(s,k,t,r,d,sigma):
    """计算BS price的中间变量"""
    result = d1(s,k,t,r,d,sigma) - sigma * sqrt(t)
    return result

def bs_price(s,k,t,r,d,sigma,cp):
    """计算BS price"""
    if cp == 'call':
        return s * exp(-d*t) * stats.norm.cdf(d1(s,k,t,r,d,sigma)) - k * exp(-r * t) * stats.norm.cdf(d2(s,k,t,r,d,sigma))
    if cp == 'put':
        return s * exp(-d*t) * stats.norm.cdf(d1(s,k,t,r,d,sigma)) - k * exp(-r * t) * stats.norm.cdf(d2(s,k,t,r,d,sigma)) + k * exp(-r * t) - s * exp(-d*t)

def calculate_implied_volatility(s,k,t,r,d,actual_price,cp, epsilon = 0.00001):
    """二分法求隐含波动率"""
    high = 2.0
    low = 0.0
    while high - low > epsilon:
        if bs_price(s,k,t,r,d,(high + low)/2,cp) > actual_price:
            high = (high + low) / 2
        else:
            low = (high + low) / 2
    return (high + low) / 2

def std_normal_pdf(x):
    """标准正态分布的概率密度函数"""
    return exp(- x ** 2 / 2) / (2 * pi) ** 0.5

def delta(s,k,t,r,d,sigma,cp):
    """希腊值 delta"""
    call_delta = exp(-d * t) * stats.norm.cdf(d1(s,k,t,r,d,sigma))
    if cp == 'call':
        return call_delta
    if cp == 'put':
        return call_delta - 1

def gamma(s,k,t,r,d,sigma):
    """希腊值 gamma"""
    return exp(-d*t) * std_normal_pdf(d1(s,k,t,r,d,sigma)) / (s * sigma * t ** 0.5) 

def vega(s,k,t,r,d,sigma):
    """希腊值 vega"""
    return exp(-d*t) * s * t ** 0.5 * std_normal_pdf(d1(s,k,t,r,d,sigma)) 

def theta(s,k,t,r,d,sigma,cp):
    """希腊值 theta"""
    part1 = -s * std_normal_pdf(d1(s,k,t,r,d,sigma)) * sigma * exp(-d*t) / (2 * t ** 0.5)
    part2 = d * s * stats.norm.cdf(d1(s,k,t,r,d,sigma)) * exp(-d*t) - r * k * exp(-r*t) * stats.norm.cdf(d2(s,k,t,r,d,sigma))
    if cp == 'call':
        return part1 + part2
    if cp == 'put':
        return part1 - part2

def rho(s,k,t,r,d,sigma,cp):
    """希腊值 rho"""
    if cp == 'call':
        return k * t * exp(-r*t) * stats.norm.cdf(d2(s,k,t,r,d,sigma))
    if cp == 'put':
        return -k * t * exp(-r*t) * stats.norm.cdf(d2(s,k,t,r,d,sigma))







提供更全面的期权数据,包括过期期权,期权连续,这些数据具体可以参考:期权数据

image.png

评论9

Liwu楼主
发表于 2023-12-28 10:27:04 | 显示全部楼层
主图选择etf期权日线, 点击运行, 会在附图绘制各希腊值的数值。
*******2671
发表于 2023-12-28 21:55:07 | 显示全部楼层
感谢李老师
*******2671
发表于 2024-1-11 16:06:29 | 显示全部楼层
运行了下,发现和汇点、东方财富网站的期权数据差距较大,方向相反,数字差距也有点大,以下2,3图是汇点和东方财富的数据
期权希腊字母1.jpg
期权希腊字母2.jpg
期权希腊字母3.jpg
*******6310
发表于 2024-1-18 11:06:46 | 显示全部楼层
*******2671 发表于 2024-1-11 16:06
运行了下,发现和汇点、东方财富网站的期权数据差距较大,方向相反,数字差距也有点大,以下2,3图是汇点和 ...
miniQMT.com申请
发表于 2024-1-19 09:46:23 | 显示全部楼层
:qiang:
*******2671
发表于 2024-1-20 13:07:20 | 显示全部楼层
*******6310 发表于 2024-1-18 11:06
看下k线选择的哪一天 是否是最后一天

和哪天没关系,看delta,认沽合约应该是负的
芸芸123
发表于 2024-1-22 19:55:05 来自手机 | 显示全部楼层
哪里可以免费提供QMT呢,berry巴要巴留要留
*******6310
发表于 2024-3-1 16:42:18 | 显示全部楼层
*******2671 发表于 2024-1-20 13:07
和哪天没关系,看delta,认沽合约应该是负的

认沽的之前有点问题 修复了
*******2671
发表于 2024-5-10 09:55:21 | 显示全部楼层
国金qmt升级后出现错误[2024-05-10 09:33:52][计算希腊字母][90003459][日线] 20240510 Traceback (most recent call last):
  File "<string>", line 43, in handlebar
  File "D:\国金证券QMT交易端\bin.x64\python36.zip\_strptime.py", line 565, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)
  File "D:\国金证券QMT交易端\bin.x64\python36.zip\_strptime.py", line 365, in _strptime
    data_string[found.end():])
ValueError: unconverted data remains: 3647

回复

您需要登录后才可以回帖 登录 | 立即注册

客服专线

400-080-8112

用思考的速度交易,用真诚的态度合作,我们是认真的!
  • 关注公众号
  • 添加微信客服
Copyright © 2001-2025 迅投QMT社区 版权所有 All Rights Reserved. 蜀ICP备19002686号-2
关灯 快速发帖
扫一扫添加微信客服
QQ客服返回顶部
快速回复 返回顶部 返回列表