真格这周是学习使用了不少,功能算是很不错,但在做的时候也发现了一个问题:
数据缺失:我在做回测,要求获取每天的delta值,并从中筛选条件值时,报错,显示无数据。不得不使用pass,影响我的回测连贯性。
现在开始讲下,我做的几个功能函数:
算起来,挺烦的,就是各种细节处理:

获取最接近指定delta值的期权合约。

用于风险偏好选择

def min_delta_c(df,n=1):
    
    #print('atm>0',df)
    df=df.sort_values(by='delta',ascending=True) 
    #print(df)
    if n ==0:
        dfn =df.head(n)
    elif n == 1:
        dfn=df.head(n)
    elif n ==2 :
        df1 = df[0:1]
        df2 = df[1:2]
        dfn=pd.merge(df1,df2,on='date')

    return dfn

def min_delta_p(df,n=1):
    
    #print('atm>0',df)
    df=df.sort_values(by='delta',ascending=True) 
    #print(df)
    if n ==0:
        dfn =df.head(n)
    elif n == 1:
        dfn=df.head(n)
    elif n ==2 :
        df1 = df[0:1]
        df2 = df[1:2]
        dfn=pd.merge(df1,df2,on='date')

    return dfn
#获取期权标的
g.biaodi = '510050.SHSE'
cutime = GetCurrentTime()#获取当前时间
b = CreateCalcObj()
    
#查询期权C合约列表
c_oplist = GetOptionContracts('510050.SHSE',cutime,0,'')
p_oplist = GetOptionContracts('510050.SHSE',cutime,1,'')
klinedata = GetHisData2(g.biaodi,BarType.Day)
lastclose = klinedata[-1].close 
#标的物价格
c_df = pd.DataFrame(columns = ['code','delta'])
for i in c_oplist:
    dela = GetOptionDeltaByCode(i,60,pricetype="now")
    df_insert = pd.DataFrame({ 'code':[i],
                             'delta':[dela]})
    c_df=c_df.append(df_insert,ignore_index=True)
c_df['s'] =  0.3
c_df['delta'] = abs(c_df['delta']-c_df['s'])

atmoc = min_delta_c(c_df)

p_df = pd.DataFrame(columns = ['code','delta'])
for i in p_oplist:
    dela = GetOptionDeltaByCode(i,60,pricetype="now")
    df_insert = pd.DataFrame({ 'code':[i],
                             'delta':[dela]})
    p_df=p_df.append(df_insert,ignore_index=True)
p_df['s'] = 0.3     
p_df['delta'] = abs(abs(p_df['delta'])-p_df['s'])   
atmop = min_delta_p(p_df)

print('c',atmoc,c_df['delta'])
print("p",atmop,p_df['delta'])
  

当前期权持仓delta(标的价)归零的函数

用于中性策略,也可以改为gamma(delta),vega(波动率),theta(时间),rho(利率)。
操作对象为期权合约

#令delta归0的动态对冲函数
def del_0():
    positions_buy = GetPositionsAsDF(context.accounts["回测期权"],buysellflag = '0')

    positions_sell = GetPositionsAsDF(context.accounts["回测期权"],buysellflag = '1')
    del_buy = 0 
    for i in range(len(positions_buy)):
        num = position_buy.iloc[i,2]
        optionDelta = GetOptionDeltaByCode(position_buy.iloc[i,1],60,'now')
        
        del_buy+=optionDelta*num
    del_sell = 0
    for i in range(len(positions_sell)):
        num = position_sell.iloc[i,2]
        optionDelta = GetOptionDeltaByCode(position_sell.iloc[i,1],60,'now')
      
        del_sell+=optionDelta*num    
    share = 0
    if del_buy+del_sell>0:
        share = int((del_buy+del_sell)/cal_del(g.atmop))
        QuickInsertOrder(context.myacc,g.atmop,'buy','open',PriceType(PbPriceType.Limit,2),share)
    elif del_buy+del_sell<0:
        share = int(abs(del_buy+del_sell)/cal_del(g.atmoc))
        QuickInsertOrder(context.myacc,g.atmoc,'buy','open',PriceType(PbPriceType.Limit,2),share)

当前期权持仓delta(标的价)归零的函数

操作对象为期货

#标的买卖对冲
def del_0(context,atmoc,atmop):
atmop = atmop
atmoc = atmoc
positions_buy = GetPositionsAsDF(context.accounts["回测期权"],buysellflag = '0')
positions_sell = GetPositionsAsDF(context.accounts["回测期权"],buysellflag = '1')
del_buy = 0 
for i in range(len(positions_buy)):
num = positions_buy.iloc[i,2]
optionDelta = GetOptionDeltaByCode(positions_buy.iloc[i,1],60,'now')
del_buy+=optionDelta*num
del_sell = 0
for i in range(len(positions_sell)):
num = positions_sell.iloc[i,2]
optionDelta = GetOptionDeltaByCode(positions_sell.iloc[i,1],60,'now')
del_sell+=optionDelta*num    
share = 0
if del_buy+del_sell>0:
#做空头
share = int(del_buy+del_sell)
df = GetPositionsAsDF(context.accounts["回测期货"]) 
if len(df)==2:
df_buy = GetPositionsAsDF(context.accounts["回测期货"],buysellflag ='buy')
QuickInsertOrder(context.myacc1,g.biaodi2,'sell','close',PriceType(PbPriceType.Limit,2),df_buy.iloc[0,2])
df_sell = GetPositionsAsDF( context.accounts["回测期货"],buysellflag = 'sell')
if df_sell.iloc[0,2]>share:
QuickInsertOrder(context.myacc1,g.biaodi2,'sell','close',PriceType(PbPriceType.Limit,2),df_sell.iloc[0,2]-share)
else:
QuickInsertOrder(context.myacc1,g.biaodi2,'sell','open',PriceType(PbPriceType.Limit,2),share-df_sell.iloc[0,2])  
elif len(df)==1:
if len(GetPositionsAsDF( context.accounts["回测期货"],buysellflag = 'buy'))==1:
df_buy = GetPositionsAsDF(context.accounts["回测期货"],buysellflag ='buy')    
QuickInsertOrder(context.myacc1,g.biaodi2,'sell','close',PriceType(PbPriceType.Limit,2),df_buy.iloc[0,2])
QuickInsertOrder(context.myacc1,g.biaodi2,'sell','open',PriceType(PbPriceType.Limit,2),share)
else:
df_sell = GetPositionsAsDF( context.accounts["回测期货"],buysellflag = 'sell')
if df_sell.iloc[0,2]>share:
QuickInsertOrder(context.myacc1,g.biaodi2,'buy','close',PriceType(PbPriceType.Limit,2),df_sell.iloc[0,2]-share)
else:
QuickInsertOrder(context.myacc1,g.biaodi2,'sell','open',PriceType(PbPriceType.Limit,2),share-df_sell.iloc[0,2])    
elif len(df)==0:
QuickInsertOrder(context.myacc1,g.biaodi2,'sell','open',PriceType(PbPriceType.Limit,2),share) 
elif del_buy+del_sell<0:
#做多头
share = int(abs(del_buy+del_sell))
df = GetPositionsAsDF(context.accounts["回测期货"]) 
if len(df)==2:
df_buy = GetPositionsAsDF( context.accounts["回测期货"],buysellflag = 'buy')
df_sell = GetPositionsAsDF( context.accounts["回测期货"],buysellflag = 'sell')
QuickInsertOrder(context.myacc1,g.biaodi2,'buy','close',PriceType(PbPriceType.Limit,2),df_sell.iloc[0,2])        
if df_buy.iloc[0,2]>share:
QuickInsertOrder(context.myacc1,g.biaodi2,'sell','close',PriceType(PbPriceType.Limit,2),df_buy.iloc[0,2]-share)
else:
QuickInsertOrder(context.myacc1,g.biaodi2,'buy','open',PriceType(PbPriceType.Limit,2),share-df_buy.iloc[0,2])  
elif len(df)==1:
if len(GetPositionsAsDF( context.accounts["回测期货"],buysellflag = 'sell'))==1:
QuickInsertOrder(context.myacc1,g.biaodi2,'buy','close',PriceType(PbPriceType.Limit,2),df_sell.iloc[0,2])
QuickInsertOrder(context.myacc1,g.biaodi2,'buy','open',PriceType(PbPriceType.Limit,2),share)
else:
df_sell = GetPositionsAsDF( context.accounts["回测期货"],buysellflag = 'buy')
if df_sell.iloc[0,2]>share:
QuickInsertOrder(context.myacc1,g.biaodi2,'sell','close',PriceType(PbPriceType.Limit,2),df_sell.iloc[0,2]-share)
else:
QuickInsertOrder(context.myacc1,g.biaodi2,'buy','open',PriceType(PbPriceType.Limit,2),share-df_sell.iloc[0,2])    
elif len(df)==0:
QuickInsertOrder(context.myacc1,g.biaodi2,'buy','open',PriceType(PbPriceType.Limit,2),share) 
#K线事件

计算剩余时间

引用真格函数,在此感谢,用处很大

#自定义函数,用于计算合约截至到期剩余天数
def stime(op):
#获取合约信息 
info1 = GetContractInfo(op)
#获取该合约的行权到期日
kill = info1['行权到期日']
#获取当前时间
cutime = GetCurrentTime()
#获取当前时间的日期
c = cutime.date()
#计算当前日期与行权到期日相差天数
n = (kill - c).days
#print(n)
#返回合约截至到期剩余天数
return n

获取主力或次主力合约函数
同样为引用真格函数,多谢。

#自定义函数, 用于获取当前所有主力或者次主力合约 
def Getop(code):
#获取实时行情
dyndata = GetQuote(g.code)
#获取最新价
now1 = dyndata.now
#获取当前时间
cutime = GetCurrentTime()
#获取当月期权到期时间
#该段功能时换月,如果不足10天,换下个月合约。
#若当前时间处于当月15号之后,则到期月份向后推一个月
if cutime.day >15 and cutime.month<12:
tim = cutime.month + 1
month_time = datetime.datetime(month=tim, year=cutime.year,day = 20)
#若当前时间处于12.15之后,则取下一年的1.20为到期时间
elif cutime.day >15 and cutime.month==12:
tim = 1
yea = cutime.year + 1
month_time = datetime.datetime(month=tim, year=yea,day = 20)
#若当前时间处于上半月,则取当前时间
else:
month_time = cutime
clist = GetOptionContracts(g.code,month_time,0,'M')
plist = GetOptionContracts(g.code,month_time,1,'M')
return clist,plist

根据成交量获取合约

此函数源于博主的一个脑洞,主力跟随,选择成交量适当的合约,进行买卖。对不起,我错了,输的一塌糊涂。欢迎交流。

#自定义函数,获取第n档成交量合约
def get_volume_opt(context,clist,plist):
df = pd.DataFrame(columns = ['opt','volume'])
for i in clist:
df.loc[len(df),'opt'] = i
df.loc[len(df)-1,'volume']=GetQuote(i).amount
df=df.sort_values(by='volume')
c1 = df.loc[context.param['n'],'opt']
c2 = df.loc[context.param['n']+1,'opt']
df1 = pd.DataFrame(columns = ['opt','volume'])
for i in plist:
df1.loc[len(df1),'opt'] = i
df1.loc[len(df1)-1,'volume']=GetQuote(i).amount
df1=df1.sort_values(by='volume')
p1 = df1.loc[context.param['n'],'opt']
p2 = df1.loc[context.param['n']+1,'opt']
return c1,c2,p1,p2

检测合约是否依旧为符合条件的合约

#检查是否还是成交量前n+1档
def stoploss(context,list1,op):
df = pd.DataFrame(columns = ['opt','volume'])
for i in list1:
df.loc[len(df),'opt'] = i
df.loc[len(df)-1,'volume']=GetQuote(i).amount
df=df.sort_values(by='volume').head(context.param['n']+1)
if op in df['opt']:
return True
else:
return False

本博主现在在使用真格进行量化回测,研究学习,欢迎大家交流讨论。博主真格id:中性策略研究

本文地址:https://blog.csdn.net/qq_26742269/article/details/109902330