策略想法:选取某一期货品种的主力合约和次主力合约,得到两个合约价格的价差,运用布林带指标,取前20分钟和2倍标准差,如果价差在布林带之外,入场,回到均值出场。
如下为策略代码:
#选取zn1701和zn1702合约的11月份交易分钟数据#数据经过excel处理,两个合约数据按时间合并#设置手续费和滑点为10元(两个合约买卖一次),平仓时扣除,import pandas as pdfrom pandas import Series,DataFrameimport numpy as npimport matplotlib.pyplot as pltfrom numpy import nandata=pd.read_excel(‘zn01_zn02.xlsx‘)data[‘spread‘]=data[‘ZN01‘]-data[‘ZN02‘]T=len(data.index)#记录每次交易收益率minute_return=[]up_cross_up_limit=Falsedown_cross_down_limit=Falseresult_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] = 1print(‘-------------‘)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)-1risk_free_rate=0.015std=np.array(minute_return).std()volatility=std*(len(minute_return)**0.5)annual_factor=12annual_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)) #计算盈亏比plrfrom 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_timesprint(‘----------------------------‘)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].valuesplt.plot(total_mean_line)plt.plot(total_up_line)plt.plot(total_down_line)plt.plot(spread)#标记进场、出场位置,先将格式转换为listspread_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() 下面为运行结果图:
进场出场放大图:
时间: 2024-08-27 21:30:24