本策略为波动率与价格想结合的策略,策略想法较为复杂,交易次数较少。
代码如下:
import pandas as pdimport pyodbcfrom sqlalchemy import create_engineimport numpy as npfrom statistics import medianimport crash_on_ipyimport pdbimport matplotlib.pyplot as plt# import matplotlib_finance as mpf# from matplotlib.finance import candlestickfrom numpy import nan#SERVER服务器地址,DATABASE数据库名,UID用户名,PWD登录密码con = pyodbc.connect(‘DRIVER={SQL Server};SERVER=192.168.60.5;DATABASE=data_history;UID=gx;PWD=01‘)# querystring="select * from [data_history].[dbo].[ag1612]"querystring="select top (20000000) [time],[price] from [data_history].[dbo].[ag1612]"engine = create_engine(‘mssql+pyodbc://scott:[email protected]‘)data=pd.read_sql(querystring, con, index_col=‘time‘)# data=pd.read_csv(‘data.csv‘,index_col=‘ID‘)print(data.head())print(data.tail()) # data=data.iloc[:,0:3]# data[‘date_time‘]=data[‘date‘]+data[‘time‘]# del data[‘date‘],data[‘time‘]data=data.sort_index()# data=data.set_index(‘date_time‘)data.rename(index=lambda x:str(x)[:16],inplace=True)# #得到每小时K线数据的开盘价、最高价、最低价、收盘价 new_data=data.groupby(data.index).last()new_data[‘open_price‘]=data.groupby(data.index).first()new_data[‘high_price‘]=data.groupby(data.index).max()new_data[‘low_price‘]=data.groupby(data.index).min()new_data.columns=[‘close_price‘,‘open_price‘, ‘high_price‘, ‘low_price‘]print(‘new_date.head():{}‘.format(new_data.head()))new_data.drop(new_data.index[152:181],inplace=True)# new_data.to_csv(‘new_data1.csv‘) # 得到周期为10的标准差# 得到所有数据的行数# 策略判断标准前面需要至少(3*24+10)h,即82h,当天需要6根k线,即6h,总共88h,取前88h,i从87开始。T=len(new_data.index)print(‘T:{}‘.format(T))std=[]std_mean=[]#记录开平仓位置position_locat=[0]*Tprofit=[]#定义前三日第二大方差差值、区间最大值、区间最小值、开仓价second_diff=0x=0;y=0;z=0;z1=0;z2=0;m=0;m1=0;m2=0interval_data_max=0interval_data_min=0open_price=0 #std数据为T-10个for i in range(10,T): data_close=new_data[‘close_price‘].iloc[i-10:i].values std.append(data_close.std())# print(std)#得到std的均值,为T-10-24个,即T-34个for i in range(24,len(std)): std_mean.append(np.mean(std[i-24:i]))# print(std_mean)print(len(new_data),len(std),len(std_mean))#new_data比std数据多10个,std数据比mean多24个,把所有数据量统一,去掉前面多于的数据new_data=new_data.iloc[34:,:]std=std[24:]print(len(new_data),len(std),len(std_mean)) T=len(new_data)mark_enter=[0]*(T)mark_leave=[0]*(T) def vol(i): vol_open_condition = False second_diff = median([np.max(std[i - 77:i - 53]) - np.mean(std[i - 77:i - 53]), np.max(std[i - 53:i - 29]) - np.mean(std[i - 53:i - 29]), np.max(std[i - 29:i - 5]) - np.mean(std[i - 77:i - 53])]) interval_data=0;std_high=0;std_low=0;interval_data_max=0;interval_data_min=0;interval_begin_time=0;interval_close_time=0 if std[i - 4] > 0.8 * second_diff and std[i - 4] >= std[i - 5] and std[i - 4] > std[i - 3] > std[i - 2] > std[ i - 1]: # 记录区间的开始位置,(i-4)为高点,(i-5)是高点前一根K线 x = i - 5 b = True while b: if std[i - 1] >= std[i]: i += 1 else: b = False break # 记录区间的结束位置,i-1为低点位置 y = i - 1 interval_data = new_data.iloc[x:y+1, :] std_high = std[x - 4] std_low = std[y] second_diff_satisfy_std = second_diff interval_data_max = interval_data[‘high_price‘].max() interval_data_min = interval_data[‘low_price‘].min() interval_begin_time=interval_data.index[0] interval_close_time=interval_data.index[-1] # interval_std_high=std[i-4] print(x, y, std_high,std_low,interval_data_max, interval_data_min,interval_begin_time,interval_close_time) vol_open_condition = True return second_diff,interval_data,std_high,std_low,interval_data_max,interval_data_min,vol_open_condition return second_diff,interval_data,std_high,std_low,interval_data_max,interval_data_min,vol_open_condition# interval_data,std_high,std_low,interval_data_max,interval_data_min=vol(22) #得到所有最高点和最低点,即对应价格区间(x:y)open_long=Falseopen_long_number=Falseopen_short_number=Falseopen_condition=Falsesecond_diff_satisfy_std=0interval_data_satisfy_std=0std_high_satisfy_std=0std_low_satisfy_std=0interval_data_max_satisfy_std=0interval_data_min_satisfy_std=0# pdb.set_trace()#79开始for i in range(91, T - 10): if not open_condition and vol(i)[6]: # vol_condition = vol(i) # vol_condition[6] open_condition = True second_diff_satisfy_std=vol(i)[0] interval_data_satisfy_std=vol(i)[1] std_high_satisfy_std=vol(i)[2] std_low_satisfy_std=vol(i)[3] interval_data_max_satisfy_std=vol(i)[4] interval_data_min_satisfy_std=vol(i)[5] #向上突破后回调情况 if open_condition and not open_long_number and not open_short_number and \ interval_data_min_satisfy_std<new_data.iloc[i,0]<interval_data_max_satisfy_std and new_data.iloc[i-1,3]>interval_data_max_satisfy_std: open_price=new_data.iloc[i,0] # 开多,记录开仓价格,i+2期收盘价 print(‘买入开仓,开仓价为:{},开仓位为:{}‘.format(open_price,i)) mark_enter[i]=1 open_condition=False open_long_number=True # 得到向下突破后回调情况 if open_condition and not open_long_number and not open_short_number and \ interval_data_min_satisfy_std<new_data.iloc[i, 0]<interval_data_max_satisfy_std and new_data.iloc[i-1,2]<interval_data_min_satisfy_std: #开空,记录开仓价格,i+2期收盘价 open_price=new_data.iloc[i,0] print(‘卖出开仓,开仓价为:{},开仓位为:{}‘.format(open_price,i)) print(‘i:{}‘.format(i)) # position_locat[i+3]=2 open_condition=False open_short_number =True mark_enter[i] = 1 #得到波动率大于前高的位置z3 if open_condition and std[i-1] > std_high_satisfy_std: open_condition=False std_high_satisfy_std=std[i-1] print(‘波动率大于前高位置,重置区间,重置点为:{}‘.format(i)) #出场 #出场分四种情况,分别是多头(正常出场和止损出场)和空头(正常出场和止损出场) #多头正常出场 if open_long_number and std[i-3]>0.3*second_diff_satisfy_std and std[i-1]>std[i-2] and std[i-1]>std[i]: # 平多,记录平仓位置 # m1=i+4 profit_yield = (new_data.iloc[i, 0] - open_price) / open_price print(‘正常卖出平仓,平仓价为:{},平仓位为:{}‘.format(new_data.iloc[i, 0],i)) profit.append(profit_yield) open_long_number=False mark_leave[i] = 1 #多头止损出场 if open_long_number and (new_data.iloc[i,3]>interval_data_max_satisfy_std or new_data.iloc[i,2]<interval_data_min_satisfy_std): #平多,记录平仓位置 # m2=i profit_yield = (new_data.iloc[i, 0] - open_price) / open_price print(‘止损卖出平仓,平仓价为:{},平仓位为:{}‘.format(new_data.iloc[i, 0],i)) profit.append(profit_yield) open_long_number=False mark_leave[i] = 1 #空头正常出场 if open_short_number and std[i]>0.3*second_diff_satisfy_std and std[i-1]>std[i-2] and std[i-1]>std[i]: #平空,记录平仓位置 # m1=i+4 profit_yield = (open_price - new_data.iloc[i, 0]) / open_price print(‘正常买入平仓,平仓价为:{},平仓位为:{}‘.format(new_data.iloc[i, 0],i)) profit.append(profit_yield) open_short_number=False mark_leave[i] = 1 #空头止损出场 if open_short_number and (new_data.iloc[i,3]>interval_data_max_satisfy_std or new_data.iloc[i,2]<interval_data_min_satisfy_std): #平空,记录平仓位置 # m2=i profit_yield = (open_price - new_data.iloc[i, 0]) / open_price print(‘止损买入平仓,平仓价为:{},平仓位为:{}‘.format(new_data.iloc[i, 0],i)) profit.append(profit_yield) open_short_number=False mark_leave[i] = 1 #计算sharpe#计算总回报total_return=np.expm1(np.log1p(profit).sum())#计算年化回报annual_return=(1+total_return)**(365/30)-1risk_free_rate=0.015profit_std=np.array(profit).std()volatility=profit_std*(len(profit)**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(profit).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 profit)loss_times=sum(x<0 for x in profit)plr=win_times/loss_timesprint(‘----------------------------‘)print(‘盈利次数:{}‘.format(win_times))print(‘亏损次数:{}‘.format(loss_times))print(‘盈亏比:{}‘.format(plr)) # #画出净值走势图fig=plt.figure()ax1=fig.add_subplot(3,1,1)ag_close_price,=plt.plot(new_data[‘close_price‘].values,label=‘close_price‘)ag_open_price,=plt.plot(new_data[‘open_price‘].values,label=‘open_price‘)ag_high_price,=plt.plot(new_data[‘high_price‘].values,label=‘high_price‘)ag_low_price,=plt.plot(new_data[‘low_price‘].values,label=‘low_price‘)plt.legend([ag_close_price,ag_open_price,ag_high_price,ag_low_price],[‘close_price‘,‘open_price‘,‘high_price‘,‘low_price‘])ag_close_price_mark_enter=new_data.iloc[:,0].values.tolist()ag_close_price_mark_leave=new_data.iloc[:,0].values.tolist()# print(type(spread),type(spread_mark))for i in range(0,T): if mark_enter[i]==0: ag_close_price_mark_enter[i]=nanplt.plot(ag_close_price_mark_enter,‘*‘)for i in range(0,T): if mark_leave[i]==0: ag_close_price_mark_leave[i]=nanplt.plot(ag_close_price_mark_leave,‘+‘) ax2=fig.add_subplot(3,1,2)ag_std,=plt.plot(std,label=‘std‘)ag_std_mean,=plt.plot(std_mean,label=‘std_mean‘)plt.legend([ag_std,ag_std_mean],[‘std‘,‘std_mean‘])ax3=fig.add_subplot(3,1,3)cum_net_worth,=plt.plot(df_cum,label=‘cum_net_worth‘)plt.legend([cum_net_worth],[‘cum_net_worth‘]) plt.show()pdb.set_trace() 下面为运行结果图:
时间: 2024-10-25 06:45:36