请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  量化平台 帖子:3352702 新帖:53

上证50ETF期权领口策略回测

舞蹈家2发表于:7 月 12 日 17:48回复(1)

期权领口交易策略¶

期权的策略回测系统来了,当前聚宽平台没有期权的模拟交易模块,我们在此只能通过获取历史行情,通过遍历日期的方式进行模拟测试。 1、策略构建时间:每个月的第一个交易日 2、合约选择:选择当月虚值8%左右的看跌期权和下个季度的相同点位的看跌期权的季度期权,构建领口交易策略。 3、交易数量,远期看跌期权1份,当前月看涨期权数量=远期看跌期权价格/当月看涨期权价格 4、开仓方式:双向同时开盘价下单, 5、平仓条件,条件一,当月看涨期权最高价格较买入价格涨幅超过10倍,条件二,当月看涨期权价格收盘价上涨超过5倍,条件三,交割日前2天平仓。 6、平仓方式:条件满足,双向同时平仓 这个策略主要在一些大事情要发生,但又不知道方向的时候采用,说白了就是市场行情波动率大的时候运用,效果比较好,每月定投,可以达到为自己的持仓买保险的效果,大家可以自动调试参数。 本次完成了期权合约的选择,期权行情数据的获取,以及回测模块,一个完整的期权回测体系基本完成了90%。后期做期权的策略的相关回测就简单了,当然还得加一个交易费用的模块,今天就介绍到这里。

from __future__ import print_function, division
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
from jqdata import *
import datetime
import matplotlib.pyplot as plt
import tushare as ts
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
#参数设置
shortcode=None
opentrade_s=[]
opentrade_l=[]
closetrade_s=[]
closetrade_l=[]

这里我们主要通过tushare金融数据库获得交易日信息,如果回测失败,没有数据,可能就是token过期,大家需要自己去申请新的token.

#获取每个月的第n个交易日的日期
def tradedate(start,end,n=1):
    'start,end均为str类型,如“20190102”,n为当月的第几个交易日'
    #如果回测失败,可能token如果过期,需要自己在Tushare上重新申请,不然没数据,建议注册自己注册一个。
    ts.set_token('384e878fadc6ad14225108d7a471360ffab5913e30378be6a7871c35')
    tradedate=[]
    b=[]
    pro = ts.pro_api()
    #获取
    a=pro.trade_cal(exchange='', start_date=start, end_date=end)
    x=0
    for i in a.index:
        if len(tradedate)==0:
            if a.is_open[i]==1:
                x+=1
                if x==n:
                    tradedate.append(a.cal_date[i])
                    x=0
        else:
            if a.is_open[i]==1 and tradedate[-1][4:6]!=a.cal_date[i][4:6]:
                x+=1
                if x==n:
                    tradedate.append(a.cal_date[i])
                    x=0
    if len(tradedate)>0:
        for c in tradedate:
            d=datetime.datetime(int(c[:4]),int(c[4:6]),int(c[6:]))
            b.append(d) 
    print('获取每个月的第n个交易日的日期')
    return b

这里主要是进行远期季度合约的时间选择。

#获取远期合约时间
def time_change(current):
    dt=current.month
    if dt in [2,3,4]:
        longdata=[0,9]
    elif dt in [5,6,7]:
        longdata=[0,12]
    elif dt in [8,9,10]:
        longdata=[1,3]
    elif dt in [11,12]:
        longdata=[1,6]
    elif dt ==1:
        longdata=[0,6]
    return longdata

这里我们通过当前上证50ETF价格,选择目标合约,但由于期权合约代码变化的无规律性,我们只能先拼接目标合约的trading_code,通过trading_code,来找到对应合约的code,从而获取合约的行情数据。

#获取交易的合约的trading_code  
def check_seed(current):
    dt=str(current.month)
    it=time_change(current)
    x=it[0]+current.year
    x=str(x)[2:]
    y=str(it[1])
    if len(y)==1:
        y='0'+y
    security='510050.XSHG'
    current_price=get_bars(security,1, unit='1d',
            fields=['open', 'close', 'high', 'low', 'volume', 'money'],
            include_now=False, end_dt=current, fq_ref_date=None)[0][3]
    #print('上证50当前价格:%s:%s'%(current,current_price))
    a=current_price*1000
    b=a*1.08
    c=round(b/50)*50
    c=int(c)
    d=str(c)
    if len(dt)==1:
        dt='0'+dt
    shortcode='510050C'+str(current.year)[2:]+dt+'M0'+d
    longcode='510050P'+x+y+'M0'+d
    return shortcode,longcode
#选择交易合约代码,交割日
def contract(current,code):
    date=current.strftime('%Y-%m-%d')
    q=query(opt.OPT_DAILY_PREOPEN.code,
    opt.OPT_DAILY_PREOPEN.expire_date,
    opt.OPT_DAILY_PREOPEN.trading_code,
    opt.OPT_DAILY_PREOPEN.date,
    ).filter(opt.OPT_DAILY_PREOPEN.trading_code==code,
    opt.OPT_DAILY_PREOPEN.date==date,
    )
    df=opt.run_query(q)
    return df
#获取合约的日行情数据
def quotation(current,code,expire_date):
    df_price=get_bars(code,count=50,unit='1d',
        fields=['date','open','high','low','close'],
        include_now=False, end_dt=expire_date)
    #把numpy数据类型,转化为pd类型
    df_price=pd.DataFrame(df_price,columns=['date','open','high','low','close'])
    #注意datetime.datetime和datetime.date不能比较,需要用方法date()转化。
    #选取当前时间之后的数据
    df_price=df_price[df_price.date>(current-datetime.timedelta(1)).date()]
    #重置索引,丢掉原来的索引
    df_price = df_price.reset_index(drop = True)
    #返回行情数据
    return df_price
#获取交易数据结果
def trede():
    monthdate=tradedate(start='20180101',end='20190630',n=7)
    for current in monthdate:
        shortdata,longdata=check_seed(current)
        df1=contract(current,shortdata)
        df2=contract(current,longdata)
        #因为有的月份数据没有,我被聚宽坑惨了,
        if df1.shape[0]!=0 and df2.shape[0]!=0:
            #获取合约交割日期
            expire_date=df1['expire_date'][0]
            #获取合约代码
            shortcode=df1['code'][0]
            longcode=df2['code'][0]
            #获取日行情数据
            df_price1=quotation(current,shortcode,expire_date)
            df_price2=quotation(current,longcode,expire_date)
            #因为有的月份数据缺失,所有需要判断
            if df_price1.shape[0]!=0 and df_price2.shape[0]!=0:
                a=df_price1.close[0]
                b=df_price2.close[0]
                num=int(b/a)
                c=a*10000*num
                c=round(c,2)
                d=b*10000
                d=round(d,2)
                ct=current.strftime('%Y-%m-%d')#时间格式转换
                opentrade_s.append({'date':ct,'so':c})
                opentrade_l.append({'date':ct,'lo':d})
                #卖出条件,盘中最高价涨10倍,收盘涨5倍,到期前两天
                for i in range(len(df_price1)-2):
                    if df_price1.high[i]>10*a:
                        x=round(df_price1.high[i]*10000*num)
                        y=round(df_price2.high[i]*10000)
                        closetrade_s.append({'date':ct,'sc':x})
                        closetrade_l.append({'date':ct,'lc':y})
                        break
                    elif df_price1.close[i]>5*a or i==len(df_price1)-3:
                        x=round(df_price1.close[i]*10000*num)
                        y=round(df_price2.close[i]*10000)
                        closetrade_s.append({'date':ct,'sc':x})
                        closetrade_l.append({'date':ct,'lc':y})
                        break
    s_1=pd.DataFrame(opentrade_s)
    s_2=pd.DataFrame(closetrade_s)
    l_1=pd.DataFrame(opentrade_l)
    l_2=pd.DataFrame(closetrade_l)
    #合并数据表
    #fally=pd.concat([s_1,s_2,l_1,l_2],axis=1,ignore_index=True)
    fally=s_1.merge(s_2,on='date')
    fally=fally.merge(l_1,on='date')
    fally=fally.merge(l_2,on='date')
    return fally
if __name__=='__main__':
    fally=trede()
    fally['share']=fally['sc']+fally['lc']-fally['so']-fally['lo']
    fally['profit']=fally.share.cumsum()
    print(fally)
    plt.figure()
    plt.plot(fally.date,fally.profit,label='profit')
    plt.plot(fally.date,fally.share,color='red',linewidth=1.0,linestyle='--',label='share')
    plt.legend(loc='best')#打印图例
    plt.xlabel('日期')
    plt.ylabel('元')
    plt.show()
获取每个月的第n个交易日的日期
          date      so       sc      lo      lc    share   profit
0   2018-01-10  2178.0  24926.0  2180.0  1777.0  22345.0  22345.0
1   2018-03-09  2590.0    175.0  2615.0  4211.0   -819.0  21526.0
2   2018-04-12  3135.0    495.0  3149.0  3871.0  -1918.0  19608.0
3   2018-05-10  2552.0    290.0  2560.0  2144.0  -2678.0  16930.0
4   2018-06-11  2241.0    249.0  2267.0  2819.0  -1440.0  15490.0
5   2018-07-10  2262.0    858.0  2270.0  1814.0  -1860.0  13630.0
6   2018-08-09  2407.0     87.0  2434.0  3319.0  -1435.0  12195.0
7   2018-09-11  2646.0    540.0  2692.0  1915.0  -2883.0   9312.0
8   2018-10-16  2379.0   1464.0  2390.0  2319.0   -986.0   8326.0
9   2018-11-09  3404.0    230.0  3432.0  3355.0  -3251.0   5075.0
10  2018-12-11  2133.0    395.0  2142.0  3046.0   -834.0   4241.0
11  2019-01-10  1974.0   1128.0  1984.0  1539.0  -1291.0   2950.0
12  2019-02-18  1960.0   1862.0  1989.0  1821.0   -266.0   2684.0
13  2019-03-11  2717.0    780.0  2776.0  2515.0  -2198.0    486.0
14  2019-05-14  3072.0   1152.0  3084.0  2918.0  -2086.0  -1600.0
15  2019-06-12  2415.0  11865.0  2444.0  1792.0   8798.0   7198.0
 
 
 

全部回复

0/140

量化课程

    移动端课程