策略想法:选择期货锌和期货铜2016年主力合约小时数据,如果买入 前一小时涨幅较大合约,假设A,买入前一小时涨幅较小合约,假设B,买入时实时保持两者价值相等(价格不相等,则买入份数不一样),如果A涨幅小于B涨幅,则平仓。
策略代码如下:
import pandas as pd
import pyodbc
from sqlalchemy import create_engine
import numpy as np
from statistics import median
import crash_on_ipy
import pdb
import matplotlib.pyplot as plt
from numpy import nan
data_cu=pd.read_csv('SQCU13.csv')
data_zn=pd.read_csv('SQZN13.csv')
data_zn.columns=['date','time','open','high','low','close','volumn','hold']
data_cu.columns=['date','time','open','high','low','close','volumn','hold']
data_zn['date_time']=data_zn['date']+data_zn['time']
data_cu['date_time']=data_cu['date']+data_cu['time']
del data_zn['date'],data_zn['time'],data_cu['date'],data_cu['time']
data_zn=data_zn.set_index('date_time')
data_cu=data_cu.set_index('date_time')
data_zn.rename(index=lambda x:str(x)[:12],inplace=True)
data_cu.rename(index=lambda x:str(x)[:12],inplace=True)
#取收盘价
data_zn=data_zn.loc[:,['close']]
data_cu=data_cu.loc[:,['close']]
new_data_zn=data_zn.groupby(data_zn.index).last()
new_data_cu=data_cu.groupby(data_cu.index).last()
data=pd.concat([new_data_zn,new_data_cu],axis=1)
data.columns=['zn_close','cu_close']
data_zn_array=np.array(new_data_zn['close'])
data_cu_array=np.array(new_data_cu['close'])
T=len(data_zn_array)
zn_return=[0]
cu_return=[0]
mark_enter=[0]*(T)
mark_leave=[0]*(T)
for i in range(1,T):
if new_data_zn.index[i]==new_data_cu.index[i]:
zn_return.append((data_zn_array[i]-data_zn_array[i-1])/data_zn_array[i])
cu_return.append((data_cu_array[i]-data_cu_array[i-1])/data_cu_array[i])
data['zn_return']=zn_return;data['cu_return']=cu_return
profit=[]
position=False
long_zn_positon=False
for i in range(1,T):
if data['zn_return'][i]<data['cu_return'][i] and not position:
position=True
long_zn_positon=True
mark_enter[i]=1
shares=data['cu_close'][i]/data['zn_close'][i]
long_price=data['zn_close'][i]
short_price=data['cu_close'][i]
elif data['zn_return'][i]>data['cu_return'][i] and not position:
position=True
long_zn_positon=False
shares = data['cu_close'][i]/ data['zn_close'][i]
mark_enter[i]=1
long_price = data['cu_close'][i]
short_price = data['zn_close'][i]
elif data['zn_return'][i]>data['cu_return'][i] and position and long_zn_positon:
position=False
long_zn_positon = False
mark_leave[i]=1
return_zn=(data['zn_close'][i]-long_price)*shares
return_cu=short_price-data['cu_close'][i]
profit.append((return_zn+return_cu)/(2*short_price))
elif data['zn_return'][i]<data['cu_return'][i] and position and not long_zn_positon:
position=False
long_zn_positon=False
mark_leave[i]=1
return_zn=(short_price-data['zn_close'][i])*shares
return_cu=long_price-data['cu_close'][i]
profit.append((return_zn + return_cu) / (2 * long_price))
#计算sharpe
#计算总回报
total_return=np.expm1(np.log1p(profit).sum())
#计算年化回报
annual_return=(1+total_return)**(365/365)-1
risk_free_rate=0.015
profit_std=np.array(profit).std()
volatility=profit_std*(len(profit)**0.5)
annual_factor=1
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(profit).cumsum())
max_return=np.maximum.accumulate(df_cum)
max_drawdown=((max_return-df_cum)/max_return).max()
print('-----------------')
print('最大回撤: {}'.format(max_drawdown))
#计算盈亏比plr
win_times=sum(x>0 for x in profit)
loss_times=sum(x<0 for x in profit)
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)
zn,=plt.plot(zn_return)
cu,=plt.plot(cu_return)
plt.legend([zn,cu],['zn_return','cu_return'])
for i in range(0,T):
if mark_enter[i]==0:
cu_return[i]=nan
plt.plot(cu_return,'*')
for i in range(0,T):
if mark_leave[i]==0:
zn_return[i]=nan
plt.plot(zn_return,'+')
plt.show()
pdb.set_trace()
策略运行结果如下图: