【无标题】

均值回归套利

基差套利,现货运用期权合成,与期货可以进行双方向套利
手续费按照3.5计算

读取数据

import pandas as pd
import numpy as np
import time
import datetime as dt
from datetime import date, datetime, timedelta
from math import exp
import matplotlib.pyplot as plt
from scipy.stats import norm
import seaborn as sns


df= pd.read_excel(r"C:\Users\zhang\Desktop\中泰证券\2021-07\基差套利\需要用到数据集_08013_new.xlsx",index_label=False)
#df = df_jc
df = df.dropna()
df.set_index(["Time"], inplace=True)
df.index = df.index.strftime('%Y-%m-%d %H:%M:%S')

df['jc'] = 0.0000
df['mspread'] = 0.0000
df['jz'] = 0
df['mavg4700'] = df['4700'].rolling(window=600, min_periods=600, center=False).mean()
df['mavg4800'] = df['4800'].rolling(window=600, min_periods=600, center=False).mean()
df['mavg4900'] = df['4900'].rolling(window=600, min_periods=600, center=False).mean()
df['mavg5000'] = df['5000'].rolling(window=600, min_periods=600, center=False).mean()
df['mavg5250'] = df['5250'].rolling(window=600, min_periods=600, center=False).mean()
df['ms4700'] = df['4700']-df['mavg4700']
df['ms4800'] = df['4800']-df['mavg4800']
df['ms4900'] = df['4900']-df['mavg4900']
df['ms5000'] = df['5000']-df['mavg5000']
df['ms5250'] = df['5250']-df['mavg5250']
df = df.dropna()
sigma = 1.3
#删除变动过大的异常值
df['diff'] = 0
df['diff'][1:len(df.index)] = np.diff(df['ms4700'])
df = df[abs(df['diff'])<5]
df['diff'][1:len(df.index)] = np.diff(df['ms4800'])
df = df[abs(df['diff'])<5]
df['diff'][1:len(df.index)] = np.diff(df['ms4900'])
df = df[abs(df['diff'])<5]
df['diff'][1:len(df.index)] = np.diff(df['ms5000'])
df = df[abs(df['diff'])<5]
df['diff'][1:len(df.index)] = np.diff(df['ms5250'])
df = df[abs(df['diff'])<5]



#mispread矩阵
df_ms = pd.DataFrame()
df_ms['4700'] =  df['4700']-df['mavg4700']
df_ms['4800'] =  df['4800']-df['mavg4800']
df_ms['4900'] =  df['4900']-df['mavg4900']
df_ms['5000'] =  df['5000']-df['mavg5000']
df_ms['5250'] =  df['5250']-df['mavg5250']

计算基差

首先根据当前期货价格水平找到平值期权,计算合成现货,计算基差
画图看基差水平变化。

def findjz(F):
    if F <4700:
        jz = 4700
        return 0
    elif F <4800:
        if F -4700 <4800-F :
            jz  = 4700
            return 0
        else:
            jz  = 4800
            return 1
    elif F <4900:
        if F-4800 <4900-F :
            jz  = 4800
            return 1
        else:
            jz  = 4900
            return 2
        if F-4900 <5000-F :
            jz  = 4900
            return 2
        else:
            jz  = 5000
            return 3
    else:
        if F-5000 <5250-F :
            jz  = 5000
            return 3
        else:
            jz  = 5250
            return 4


for i in range(len(df.index)):
    if df['F'][i] <4700:
        df['jc'][i] = df['4700'][i] 
        df['jz'][i] = 4700
        df['mspread'][i] = df['4700'][i] - df['mavg4700'][i]
    elif df['F'][i] <4800:
        if df['F'][i]-4700 <4800-df['F'][i] :
            df['jc'][i] = df['4700'][i] 
            df['jz'][i]  = 4700
            df['mspread'][i] = df['4700'][i] - df['mavg4700'][i]
        else:
            df['jc'][i] = df['4800'][i] 
            df['jz'][i]  = 4800
            df['mspread'][i] = df['4800'][i] - df['mavg4800'][i]
    elif df['F'][i] <4900:
        if df['F'][i]-4800 <4900-df['F'][i] :
            df['jc'][i] = df['4800'][i] 
            df['jz'][i]  = 4800
            df['mspread'][i] = df['4800'][i] - df['mavg4800'][i]
        else:
            df['jc'][i] = df['4900'][i] 
            df['jz'][i]  = 4900
            df['mspread'][i] = df['4900'][i] - df['mavg4900'][i]
    elif df['F'][i] <5000:
        if df['F'][i]-4900 <5000-df['F'][i] :
            df['jc'][i] = df['4900'][i] 
            df['jz'][i]  = 4900
            df['mspread'][i] = df['4900'][i] - df['mavg4900'][i]
        else:
            df['jc'][i] = df['5000'][i] 
            df['jz'][i]  = 5000
            df['mspread'][i] = df['5000'][i] - df['mavg5000'][i]
    else:
        if df['F'][i]-5000 <5250-df['F'][i] :
            df['jc'][i] = df['5000'][i] 
            df['jz'][i]  = 5000
            df['mspread'][i] = df['5000'][i] - df['mavg5000'][i]
        else:
            df['jc'][i] = df['5250'][i] 
            df['jz'][i]  = 5250
            df['mspread'][i] = df['5250'][i] - df['mavg5250'][i]
            
for i in range(len(df.index)):
    if df['F'][i] <4700:
        df['jc'][i] = df['4700'][i] 
        df['jz'][i] = 4700
        df['std'] = df_ms['sigma4700']
    elif df['F'][i] <4800:
        if df['F'][i]-4700 <4800-df['F'][i] :
            df['jc'][i] = df['4700'][i] 
            df['jz'][i]  = 4700
            df['std'] = df_ms['sigma4700']
        else:
            df['jc'][i] = df['4800'][i] 
            df['jz'][i]  = 4800
            df['std'] = df_ms['sigma4800']
    elif df['F'][i] <4900:
        if df['F'][i]-4800 <4900-df['F'][i] :
            df['jc'][i] = df['4800'][i] 
            df['jz'][i]  = 4800
            df['std'] = df_ms['sigma4800']
        else:
            df['jc'][i] = df['4900'][i] 
            df['jz'][i]  = 4900
            df['std'] = df_ms['sigma4900']
    elif df['F'][i] <5000:
        if df['F'][i]-4900 <5000-df['F'][i] :
            df['jc'][i] = df['4900'][i] 
            df['jz'][i]  = 4900
            df['std'] = df_ms['sigma4900']
        else:
            df['jc'][i] = df['5000'][i] 
            df['jz'][i]  = 5000
            df['std'] = df_ms['sigma5000']
    else:
        if df['F'][i]-5000 <5250-df['F'][i] :
            df['jc'][i] = df['5000'][i] 
            df['jz'][i]  = 5000
            df['std'] = df_ms['sigma5000']
        else:
            df['jc'][i] = df['5250'][i] 
            df['jz'][i]  = 5250
            df['std'] = df_ms['sigma5250']

#df['mavg'] = df['jc'].mean()
#df['mavg'] = df['jc'].rolling(window=80, min_periods=20, center=False).mean()
#df['mspread'] = df['jc']-df['mavg']
#sigma = np.std(df['mspread'])
     
   
#观察异常值boxplot
pd.DataFrame(df['ms4700']).describe()
percentile = np.percentile(df['ms4900'],[0,5,50,95,100])
IQR = percentile[3]-percentile[1]
Uplimit = percentile[3]+IQR*3.5
Dowmlimit = percentile[1]-IQR*3.5
f,ax = plt.subplots(figsize=(10,8))
sns.boxplot(data =df['mspread'])
plt.show
'''
#删除变动过大的异常值
df['diff'] = 0
df['diff'][1:len(df.index)] = np.diff(df['mspread'])
df = df[abs(df['diff'])<5]
'''
b=2.5
s=2.5
df['jc'].plot(figsize=(12,8),label='rolling600')
plt.title('std_mean_revert',fontsize=15)
plt.plot(df.mavg4900, color='r',label='mean')
plt.plot(df.mavg4900+b, color='g',label='begin=1.5*sigma')
plt.plot(df.mavg4900-b, color='g')
plt.plot(df.mavg4900+s, color='b',label='stop=2.5*sigma')
plt.plot(df.mavg4900-s, color='b')
plt.legend()
ax = plt.gca()  
ax.spines['right'].set_color('none') 
ax.spines['top'].set_color('none')    
plt.show()

df['jc'].plot() 

策略

#%%梯度建仓
#超过3就建一个,5+再建一口。不留隔夜仓位

b = 2.5#开仓点
s = 2.5#平仓
b2 = 5#稳定能盈利的点位
h = 1.2#划价
def mrETF2(df, b, s, b2, h):
    df['account'] = 0
    open_4700 = []
    open_4800 = []
    open_4900 = []
    open_5000 = []
    open_5250 = []
    open_list = [open_4700,open_4800,open_4900,open_5000,open_5250]
    df['hold_state'] = 0
    hold = 0
    option = 0
    for i in range(1,len(df.index)):             
        if hold == 0:
            if i < len(df.index)-1:                                        
                if df['mspread'][i] >= b: 
                    #在原有基础上空一手,空期货多现货
                    df.loc[df.index[i],'hold_state'] = df['hold_state'][i-1] - 1
                    #account去掉期货保证金+期权权利金+滑点/2
                    df['account'][i]= df['account'][i-1] - df['F'][i]*4.8/1000/365*300 - 30*10000*4.8/365/100*0.1 - 1.2*300 - df['F'][i]*0.23/10000*300
                    option = option + 1
                    hold = hold - 1    
                    t = findjz(df['F'][i]) 
                    open_list[t].append(df_ms.iloc[i,t])#记录开仓时的基差
                elif df['mspread'][i] <= -b:
                    #在原有基础上多一手,买期货空现货
                    df.loc[df.index[i],'hold_state'] = df['hold_state'][i-1] + 1
                    #account去掉期权保证金+滑点/2
                    df['account'][i]= df['account'][i-1] - 30*10000*4.8/365/100 - 1.2*300 - df['F'][i]*0.23/10000*300
                    t = findjz(df['F'][i]) 
                    open_list[t].append(df_ms.iloc[i,t])#记录开仓时的基差
                    hold = hold + 1
                    option = option + 1
                else:
                    df.loc[df.index[i],'hold_state'] = df['hold_state'][i-1]
                    df['account'][i]= df['account'][i-1]
            else:
                df.loc[df.index[i],'hold_state'] = df['hold_state'][i-1]
                df['account'][i]= df['account'][i-1]                       
        elif hold < 0:   
            zongchange = 0
            n = 0
            #account去掉 期货手续费+滑点/2
            for t in range(len(open_list)):
                change = 300*(df.iloc[i,t]-df.iloc[i-1,t])*len(open_list[t])
                n = n+len(open_list[t])
                zongchange = change+zongchange                
            #平仓,基差减少止盈or换天清仓
            if i < len(df.index)-1:                              
                if (df['mspread'][i] <= -s)|(df['Date'][i] != df['Date'][i+1]):   
                    df.loc[df.index[i],'account'] = df['account'][i-1] +(- 1.2*300 - df['F'][i]*3.45/10000*300)*n - zongchange
                    df.loc[df.index[i],'hold_state'] = 0
                    hold = 0
                    open_4700 = []
                    open_4800 = []
                    open_4900 = []
                    open_5000 = []
                    open_5250 = []
                    open_list = [open_4700,open_4800,open_4900,open_5000,open_5250]                    
                #加仓,基差更大了,再空一手
                elif df['mspread'][i] >= b2: 
                    #在原有基础上空一手,空期货多现货
                    df.loc[df.index[i],'hold_state'] = df['hold_state'][i-1] - 1  
                    #account去掉期货保证金+期权权利金
                    df['account'][i]= df['account'][i-1] - df['F'][i]*4.8/1000/365*300 - 30*10000*4.8/365/100*0.1 -1.2*300  - zongchange - df['F'][i]*0.23/10000*300
                    t = findjz(df['F'][i]) 
                    open_list[t].append(df_ms.iloc[i,t])#记录开仓时的点位
                    hold = hold - 1
                    option = option + 1    
                else:              
                    df['account'][i] = df['account'][i-1]-zongchange
                    df.loc[df.index[i],'hold_state'] = df['hold_state'][i-1]
            else:
                df.loc[df.index[i],'account'] = df['account'][i-1] +(- 1.2*300 - df['F'][i]*3.45/10000*300)*n - zongchange
                df.loc[df.index[i],'hold_state'] = 0
                hold = 0
                open_4700 = []
                open_4800 = []
                open_4900 = []
                open_5000 = []
                open_5250 = []
                open_list = [open_4700,open_4800,open_4900,open_5000,open_5250]                       
        elif hold > 0:#本身基差过小,多一手
            zongchange = 0
            n = 0
            #account去掉 期货手续费+滑点/2
            for t in range(len(open_list)):
                change = 300*(df.iloc[i,t]-df.iloc[i-1,t])*len(open_list[t])
                n = n+len(open_list[t])
                zongchange = change+zongchange         
            if i < len(df.index)-1:                   
                if (df['mspread'][i] >= s)|(df['Date'][i] != df['Date'][i+1]):            
                    #account去掉 期货手续费+滑点/2
                    df.loc[df.index[i],'account'] = df['account'][i-1] - 1.2*300 - df['F'][i]*3.45/10000*300 + zongchange
                    df.loc[df.index[i],'hold_state'] = 0
                    hold = 0
                    open_4700 = []
                    open_4800 = []
                    open_4900 = []
                    open_5000 = []
                    open_5250 = []
                    open_list = [open_4700,open_4800,open_4900,open_5000,open_5250]                    
                #加仓,基差更小了,再多一手
                elif df['mspread'][i] <= -b2:
                    #在原有基础上多一手,买期货空现货
                    df.loc[df.index[i],'hold_state'] = df['hold_state'][i-1] + 1
                    df['account'][i]= df['account'][i-1] - 30*10000*4.8/365/100 - 1.2*300 + zongchange- df['F'][i]*0.23/10000*300
                    t = findjz(df['F'][i]) 
                    open_list[t].append(df['jc'][i])
                    hold = hold + 1
                    option = option+1    
                else:       
                    df['account'][i] =df['account'][i-1]+zongchange
                    df.loc[df.index[i],'hold_state'] = df['hold_state'][i-1]                
            else:
                df.loc[df.index[i],'account'] = df['account'][i-1] - 1.2*300 - df['F'][i]*3.45/10000*300 + zongchange
                df.loc[df.index[i],'hold_state'] = 0
                hold = 0
                open_4700 = []
                open_4800 = []
                open_4900 = []
                open_5000 = []
                open_5250 = []
                open_list = [open_4700,open_4800,open_4900,open_5000,open_5250]                        

    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(range(len(df['account'])), df['account'])
    plt.show()

    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(range(len(df['account'])),df['hold_state'])
    plt.show()
    return (df['account'][-1], option)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值