跨期套利策略
策略想法:選取某一期貨品種的主力合約和次主力合約,得到兩個合約價格的價差,運用布林帶指標,取前20分鐘和2倍標準差,如果價差在布林帶之外,入場,回到均值出場。
如下為策略代碼:
?
#選取zn1701和zn1702合約的11月份交易分鐘數據#數據經過excel處理,兩個合約數據按時間合并
#設置手續費和滑點為10元(兩個合約買賣一次),平倉時扣除,
import pandas as pd
from pandas import Series,DataFrame
import numpy as np
import matplotlib.pyplot as plt
from numpy import nan
data=pd.read_excel('zn01_zn02.xlsx')
data['spread']=data['ZN01']-data['ZN02']
T=len(data.index)
#記錄每次交易收益率
minute_return=[]
up_cross_up_limit=False
down_cross_down_limit=False
result_up= DataFrame(columns=['ZN01', 'ZN02', 'spread', 'ZN01買賣方向', 'ZN01開平', 'ZN02買賣方向', 'ZN02開平'])
result_down= DataFrame(columns=['ZN01', 'ZN02', 'spread', 'ZN01買賣方向', 'ZN01開平', 'ZN02買賣方向', 'ZN02開平'])
total_mean_line=[]
total_up_line=[]
total_down_line=[]
#生成T-20個元素為0列表,
a=[0]*(T-20)
for i in range(20,T):
#得到第i個spread前20個數據,并計算均值、方差、up_line、down_line
#計算結果均為整數
data_spread=data.iloc[i-20:i,2].values
# print(data_spread)
mean_20day_spread=data_spread.mean()
total_mean_line.append(mean_20day_spread)
# print(mean_20day_spread)
std_20day_spread=data_spread.std()
up_line=mean_20day_spread+2*std_20day_spread
total_up_line.append(up_line)
down_line=mean_20day_spread-2*std_20day_spread
total_down_line.append(down_line)
#將第i個spread與前20個spread得到up_line比較,決定是否開倉
if data.iloc[i,2]>up_line and not up_cross_up_limit:
up_open=data.iloc[i:i+1,:]
up_open = DataFrame(up_open,columns=['ZN01', 'ZN02', 'spread', 'ZN01買賣方向', 'ZN01開平', 'ZN02買賣方向', 'ZN02開平'])
up_open['ZN01買賣方向'] = '賣出'
up_open['ZN01開平'] = '開倉'
up_open['ZN02買賣方向'] = '買入'
up_open['ZN02開平'] = '開倉'
#匯總
result_up=pd.concat([result_up,up_open])
#得到開倉spread
hold_spread = data.iloc[i, 2]
up_cross_up_limit=True
#i從20開始
a[i-20]=1
# 將第i個spread與前20個spread得到mean_20day_spread比較,決定是否平倉
elif data.iloc[i,2]<=mean_20day_spread and up_cross_up_limit:
down_close=data.iloc[i:i+1,:]
down_close = DataFrame(down_close,columns=['ZN01', 'ZN02', 'spread', 'ZN01買賣方向', 'ZN01開平', 'ZN02買賣方向', 'ZN02開平'])
down_close['ZN01買賣方向'] = '買入'
down_close['ZN01開平'] = '平倉'
down_close['ZN02買賣方向'] = '賣出'
down_close['ZN02開平'] = '平倉'
result_up=pd.concat([result_up,down_close])
profit_yield = (hold_spread - data.iloc[i, 2] - 20) / (data.iloc[i, 0] + data.iloc[i, 1])
minute_return.append(profit_yield)
up_cross_up_limit=False
a[i-20] = 1
# 將第i個spread與前20個spread得到down_line比較,決定是否開倉
elif data.iloc[i,2]<down_line and not down_cross_down_limit:
down_open=data.iloc[i:i+1,:]
down_open = DataFrame(down_open,columns=['ZN01', 'ZN02', 'spread', 'ZN01買賣方向', 'ZN01開平', 'ZN02買賣方向', 'ZN02開平'])
down_open['ZN01買賣方向'] = '買入'
down_open['ZN01開平'] = '開倉'
down_open['ZN02買賣方向'] = '賣出'
down_open['ZN02開平'] = '開倉'
#匯總
result_down=pd.concat([result_down,down_open])
hold_spread = data.iloc[i, 2]
down_cross_down_limit=True
a[i-20] = 1
# 將第i個spread與前20個spread得到down_line比較,決定是否平倉
elif data.iloc[i,2]>=mean_20day_spread and down_cross_down_limit:
up_close=data.iloc[i:i+1,:]
up_close = DataFrame(up_close,columns=['ZN01', 'ZN02', 'spread', 'ZN01買賣方向', 'ZN01開平', 'ZN02買賣方向', 'ZN02開平'])
up_close['ZN01買賣方向'] = '賣出'
up_close['ZN01開平'] = '平倉'
up_close['ZN02買賣方向'] = '買入'
up_close['ZN02開平'] = '平倉'
result_down=pd.concat([result_down,up_close])
profit_yield = (data.iloc[i, 2] - hold_spread - 20)/ (data.iloc[i, 0] + data.iloc[i, 1])
minute_return.append(profit_yield)
down_cross_down_limit=False
a[i-20] = 1
print('-------------')
transation=pd.concat([result_up,result_down]).sort_index()
# transation.to_csv('transation_detail.csv')
#計算sharpe
#計算總回報
total_return=np.expm1(np.log1p(minute_return).sum())
#計算年化回報
annual_return=(1+total_return)**(365/30)-1
risk_free_rate=0.015
std=np.array(minute_return).std()
volatility=std*(len(minute_return)**0.5)
annual_factor=12
annual_volatility=volatility*((annual_factor)**0.5)
sharpe=(annual_return-risk_free_rate)/annual_volatility
# print(total_return,annual_return,std,volatility,annual_volatility,sharpe)
print('夏普比率:{}'.format(sharpe))
#計算最大回撤
#計算
df_cum=np.exp(np.log1p(minute_return).cumsum())
max_return=np.maximum.accumulate(df_cum)
max_drawdown=((max_return-df_cum)/max_return).max()
print('-----------------')
print('最大回撤: {}'.format(max_drawdown))
#計算盈虧比plr
from collections import Counter
# win_times=Counter(x>0 for x in minute_return)
# loss_times=Counter(x<0 for x in minute_return)
win_times=sum(x>0 for x in minute_return)
loss_times=sum(x<0 for x in minute_return)
plr=win_times/loss_times
print('----------------------------')
print('盈利次數:{}'.format(win_times))
print('虧損次數:{}'.format(loss_times))
print('盈虧比:{}'.format(plr))
#畫出凈值走勢圖
fig=plt.figure()
ax1=fig.add_subplot(2,1,1)
cum_net_worth,=plt.plot(df_cum,label='cum_net_worth')
plt.legend([cum_net_worth],['cum_net_worth'])
ax2=fig.add_subplot(2,1,2)
spread=data.iloc[20:,2].values
plt.plot(total_mean_line)
plt.plot(total_up_line)
plt.plot(total_down_line)
plt.plot(spread)
#標記進場、出場位置,先將格式轉換為list
spread_mark=spread.tolist()
for i in range(T-20):
if a[i]==0:
spread_mark[i]=nan
elif a[i]==1:
spread_mark[i]=spread_mark[i]
plt.plot(spread_mark,'*')
plt.show()
下面為運行結果圖:
?
?
?
?進場出場放大圖:
?
轉載于:https://www.cnblogs.com/bawu/p/6789402.html
總結
- 上一篇: 电脑打开播放器提示服务器运行失败,电脑中
- 下一篇: 用普通话软件测试为什么分数都很低,有没有