量化课堂对光大证券研报《基于阻力支撑相对强度(RSRS)的市场择时》,给出了RSRS斜率指标择时,以及在斜率基础上的标准化指标择时策略,如下:
【量化课堂】RSRS(阻力支撑相对强度)择时策略(上)
【量化课堂】RSRS(阻力支撑相对强度)择时策略(下)
但只提供了最终的策略代码,刚好今天整理资料发现了以前保存的RSRS研究文档,意外的是在聚宽的研究模块里Tushare是可以用的,所以原封不动的复制过来(除了日期略作改动),RSRS可以做什么,建议阅读原研报,
个人认为可以利用RSRS来对板块进行轮动,追踪强势板块,或者进行仓位管理,风控等。
import pandas as pdimport osimport datetimeimport numpy as np import statsmodels.formula.api as smlimport matplotlib.pyplot as pltimport tushare as tsimport scipy.stats as scsimport matplotlib.mlab as mlab#聚宽#import statsmodels.api as sm#from pandas.stats.api import ols
dateStart = datetime.date(2005,3,8)dateEnd = datetime.date(2019,3,8)HS300 = ts.get_k_data('000300', index=True,start = '{}'.format(dateStart),end = '{}'.format(dateEnd))HS300.head()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
date | open | close | high | low | volume | code | |
---|---|---|---|---|---|---|---|
0 | 2005-04-08 | 984.66 | 1003.45 | 1003.70 | 979.53 | 14762500.0 | sh000300 |
1 | 2005-04-11 | 1003.88 | 995.42 | 1008.73 | 992.77 | 15936100.0 | sh000300 |
2 | 2005-04-12 | 993.71 | 978.70 | 993.71 | 978.20 | 10226200.0 | sh000300 |
3 | 2005-04-13 | 987.95 | 1000.90 | 1006.50 | 987.95 | 16071700.0 | sh000300 |
4 | 2005-04-14 | 1004.64 | 986.97 | 1006.42 | 985.58 | 12945700.0 | sh000300 |
def getdata(dateStart,dateEnd,N,M):HS300 = ts.get_k_data('000300', index=True,start = '{}'.format(dateStart),end = '{}'.format(dateEnd))HS300=HS300[['date','high','low','open','close']]# 斜率HS300['beta'] = 0HS300['R2'] = 0for i in range(1,len(HS300)-1):df_ne=HS300.loc[ i- N+1:i + 1 ,:]model = sml.ols(formula='high~low',data = df_ne)result=model.fit()HS300.loc[i+1,'beta'] = result.params[1]HS300.loc[i+1,'R2'] = result.rsquared# 日收益率 HS300['ret'] = HS300.close.pct_change(1)# 标准分HS300['beta_norm'] = (HS300['beta'] - HS300.beta.rolling(M).mean().shift(1))/HS300.beta.rolling(M).std().shift(1)for i in range(M):HS300.loc[i,'beta_norm'] = (HS300.loc[i,'beta'] - HS300.loc[:i-1,'beta'].mean())/HS300.loc[:i-1,'beta'].std() HS300.loc[2,'beta_norm'] = 0HS300['RSRS_R2'] = HS300.beta_norm*HS300.R2HS300 = HS300.fillna(0)# 右偏标准分HS300['beta_right'] = HS300.RSRS_R2*HS300.betareturn(HS300)
dateStart = datetime.date(2005,3,8)dateEnd = datetime.date(2017,12,31)N = 18M = 600HS300 = getdata(dateStart,dateEnd,N,M)HS300.head()
/opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py:22: RuntimeWarning: divide by zero encountered in double_scalars
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
date | high | low | open | close | beta | R2 | ret | beta_norm | RSRS_R2 | beta_right | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2005-04-08 | 1003.70 | 979.53 | 984.66 | 1003.45 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
1 | 2005-04-11 | 1008.73 | 992.77 | 1003.88 | 995.42 | 0.000000 | 0.000000 | -0.008002 | 0.000000 | 0.000000 | 0.000000 |
2 | 2005-04-12 | 993.71 | 978.20 | 993.71 | 978.70 | 0.767238 | 0.653529 | -0.016797 | 0.000000 | 0.000000 | 0.000000 |
3 | 2005-04-13 | 1006.50 | 987.95 | 987.95 | 1000.90 | 0.791216 | 0.687122 | 0.022683 | 1.208831 | 0.830615 | 0.657196 |
4 | 2005-04-14 | 1006.42 | 985.58 | 1004.64 | 986.97 | 0.804497 | 0.670781 | -0.013917 | 0.921975 | 0.618444 | 0.497536 |
HS300 = HS300.loc[2:]HS300 =HS300.reset_index(drop = True)HS300.head()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
date | high | low | open | close | beta | R2 | ret | beta_norm | RSRS_R2 | beta_right | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2005-04-12 | 993.71 | 978.20 | 993.71 | 978.70 | 0.767238 | 0.653529 | -0.016797 | 0.000000 | 0.000000 | 0.000000 |
1 | 2005-04-13 | 1006.50 | 987.95 | 987.95 | 1000.90 | 0.791216 | 0.687122 | 0.022683 | 1.208831 | 0.830615 | 0.657196 |
2 | 2005-04-14 | 1006.42 | 985.58 | 1004.64 | 986.97 | 0.804497 | 0.670781 | -0.013917 | 0.921975 | 0.618444 | 0.497536 |
3 | 2005-04-15 | 982.61 | 971.93 | 982.61 | 974.08 | 1.214834 | 0.812732 | -0.013060 | 1.719667 | 1.397629 | 1.697887 |
4 | 2005-04-18 | 970.91 | 958.65 | 970.91 | 963.77 | 1.220131 | 0.923110 | -0.010584 | 1.271125 | 1.173388 | 1.431687 |
#斜率数据分布plt.figure(figsize=(15,5))plt.hist(HS300['beta'], bins= 100, range= None, normed= False, weights= None, cumulative= False, bottom= None, histtype= 'bar', align= 'mid', orientation= 'vertical', rwidth= None, log= False, color= 'r', label='直方图', stacked= False)plt.show()
/opt/conda/lib/python3.6/site-packages/matplotlib/axes/_axes.py:6521: MatplotlibDeprecationWarning: The 'normed' kwarg was deprecated in Matplotlib 2.1 and will be removed in 3.1. Use 'density' instead. alternative="'density'", removal="3.1")
#RSRS标准分和右偏变准分分布plt.figure(figsize=(15,5))plt.hist(HS300['beta_norm'], bins= 100, range= None, normed= False, weights= None, cumulative= False, bottom= None, histtype= 'bar', align= 'mid', orientation= 'vertical', rwidth= None, log= False, color= 'r', label='直方图', stacked= False)plt.show()plt.figure(figsize=(15,5))plt.hist(HS300['RSRS_R2'], bins= 100, range= None, normed= False, weights= None, cumulative= False, bottom= None, histtype= 'bar', align= 'mid', orientation= 'vertical', rwidth= None, log= False, color= 'r', label='直方图', stacked= False)plt.show()
/opt/conda/lib/python3.6/site-packages/matplotlib/axes/_axes.py:6521: MatplotlibDeprecationWarning: The 'normed' kwarg was deprecated in Matplotlib 2.1 and will be removed in 3.1. Use 'density' instead. alternative="'density'", removal="3.1")
/opt/conda/lib/python3.6/site-packages/matplotlib/axes/_axes.py:6521: MatplotlibDeprecationWarning: The 'normed' kwarg was deprecated in Matplotlib 2.1 and will be removed in 3.1. Use 'density' instead. alternative="'density'", removal="3.1")
sta = scs.describe(HS300.beta)stew = sta[4]kurtosis = sta[5]sta1 = scs.describe(HS300.beta_norm)stew1 = sta1[4]kurtosis1 = sta1[5]sta2 = scs.describe(HS300.RSRS_R2)stew2 = sta2[4]kurtosis2 = sta2[5]print('斜率的均值:%s' % (HS300['beta'].mean()))print('斜率的标准差:%s' % (HS300['beta'].std()))print('斜率的偏度:%s' % (stew))print('斜率的峰度:%s' % (kurtosis))print('')print('斜率标准分的均值:%s' % (HS300['beta_norm'].mean()))print('斜率标准分的标准差:%s' % (HS300['beta_norm'].std()))print('斜率标准分的偏度:%s' % (stew1))print('斜率标准分的峰度:%s' % (kurtosis1))print('')print('斜率标准分的均值:%s' % (HS300['RSRS_R2'].mean()))print('斜率标准分的标准差:%s' % (HS300['RSRS_R2'].std()))print('斜率标准分的偏度:%s' % (stew2))print('斜率标准分的峰度:%s' % (kurtosis2))
斜率的均值:0.9107300548852182 斜率的标准差:0.11510992220867003 斜率的偏度:-0.37650035325581255 斜率的峰度:0.880393019660489 斜率标准分的均值:-0.02022967957717388 斜率标准分的标准差:1.0215397882843733 斜率标准分的偏度:-0.44956956799879083 斜率标准分的峰度:1.2596938448054438 斜率标准分的均值:0.04386035016941067 斜率标准分的标准差:0.8333195496560563 斜率标准分的偏度:0.13435897885521442 斜率标准分的峰度:0.4567819364025256
#斜率指标过去250天均值曲线HS300['beta_mean'] = HS300.beta.rolling(250).mean().shift(1)for i in range(250):HS300.loc[i,'beta_mean'] = HS300.loc[:i-1,'beta'].mean()result = HS300.loc[10:].copy()result = result.reset_index(drop = True)xtick = np.arange(0,result.shape[0],int(result.shape[0]/7))xticklabel = pd.Series(result.date[xtick])plt.figure(figsize=(15,3))fig = plt.axes()plt.plot(np.arange(result.shape[0]),result.beta_mean,linewidth = 3,color = 'black')fig.set_xticks(xtick)fig.set_xticklabels(xticklabel,rotation = 45)plt.legend()plt.show()
#斜率指标交易策略标准分策略def RSRS1(HS300,S1 = 1.0,S2 = 0.8):data = HS300.copy()data['flag'] = 0 # 买卖标记data['position'] = 0 # 持仓标记position = 0 # 是否持仓,持仓:1,不持仓:0for i in range(1,data.shape[0]-1):# 开仓if data.loc[i,'beta']>S1 and position ==0:data.loc[i,'flag'] = 1data.loc[i+1,'position'] = 1position = 1# 平仓elif data.loc[i,'beta']<S2 and position ==1: data.loc[i,'flag'] = -1data.loc[i+1,'position'] = 0 position = 0# 保持else:data.loc[i+1,'position'] = data.loc[i,'position'] data['n*'] = (1+data.close.pct_change(1).fillna(0)*data.position).cumprod() return(data)
#标准分策略def RSRS2(HS300,S = 0.7):data = HS300.copy()data['flag'] = 0 # 买卖标记data['position'] = 0 # 持仓标记position = 0 # 是否持仓,持仓:1,不持仓:0for i in range(1,data.shape[0]-1):# 开仓if data.loc[i,'beta_norm']>S and position ==0:data.loc[i,'flag'] = 1data.loc[i+1,'position'] = 1position = 1# 平仓elif data.loc[i,'beta_norm']<-S and position ==1: data.loc[i,'flag'] = -1data.loc[i+1,'position'] = 0 position = 0# 保持else:data.loc[i+1,'position'] = data.loc[i,'position'] data['n*'] = (1+data.close.pct_change(1).fillna(0)*data.position).cumprod() return(data)
# 修正标准分策略def RSRS3(HS300,S = 0.7):data = HS300.copy()data['flag'] = 0 # 买卖标记data['position'] = 0 # 持仓标记position = 0 # 是否持仓,持仓:1,不持仓:0for i in range(1,data.shape[0]-1):# 开仓if data.loc[i,'RSRS_R2']>S and position ==0:data.loc[i,'flag'] = 1data.loc[i+1,'position'] = 1position = 1# 平仓elif data.loc[i,'RSRS_R2']<-S and position ==1: data.loc[i,'flag'] = -1data.loc[i+1,'position'] = 0 position = 0# 保持else:data.loc[i+1,'position'] = data.loc[i,'position'] data['n*'] = (1+data.close.pct_change(1).fillna(0)*data.position).cumprod() return(data)
#右偏标准分策略def RSRS4(HS300,S = 0.7):data = HS300.copy()data['flag'] = 0 # 买卖标记data['position'] = 0 # 持仓标记position = 0 # 是否持仓,持仓:1,不持仓:0for i in range(1,data.shape[0]-1):# 开仓if data.loc[i,'beta_right']>S and position ==0:data.loc[i,'flag'] = 1data.loc[i+1,'position'] = 1position = 1# 平仓elif data.loc[i,'beta_right']<-S and position ==1: data.loc[i,'flag'] = -1data.loc[i+1,'position'] = 0 position = 0# 保持else:data.loc[i+1,'position'] = data.loc[i,'position'] data['n*'] = (1+data.close.pct_change(1).fillna(0)*data.position).cumprod() return(data)
result = RSRS1(HS300)num = result.flag.abs().sum()/2n* = result.n*[result.shape[0]-1]print('交易次数 = ',num)print('策略净值为= ',n*)
交易次数 = 44.0 策略净值为= 11.211012175460354
xtick = np.arange(0,result.shape[0],int(result.shape[0]/7))xticklabel = pd.Series(result.date[xtick])plt.figure(figsize=(15,3))fig = plt.axes()plt.plot(np.arange(result.shape[0]),result.n*,label = 'RSRS1',linewidth = 2,color = 'red')plt.plot(np.arange(result.shape[0]),result.close/result.close[0],color = 'yellow',label = 'HS300',linewidth = 2)fig.set_xticks(xtick)fig.set_xticklabels(xticklabel,rotation = 45)plt.legend()plt.show()
result2 = RSRS2(HS300)num = result2.flag.abs().sum()/2n* = result2.n*[result.shape[0]-1]ret_year = (n* - 1)print('交易次数 = ',num)print('策略净值为= ',n*)
交易次数 = 49.5 策略净值为= 9.793926481255566
result3 = RSRS3(HS300)num = result3.flag.abs().sum()/2n* = result3.n*[result.shape[0]-1]ret_year = (n* - 1)print('交易次数 = ',num)print('策略净值为= ',n*)
交易次数 = 44.5 策略净值为= 8.58132605273418
dateStart = datetime.date(2005,3,8)dateEnd = datetime.date(2017,12,31)N = 16M = 300HS300 = getdata(dateStart,dateEnd,N,M)HS300 = HS300.loc[2:]HS300 =HS300.reset_index(drop = True)
/opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py:22: RuntimeWarning: divide by zero encountered in double_scalars
result4 = RSRS4(HS300)num = result4.flag.abs().sum()/2n* = result4.n*[result.shape[0]-1]ret_year = (n* - 1)print('交易次数 = ',num)print('策略净值为= ',n*)
交易次数 = 37.5 策略净值为= 9.946785407409507
xtick = np.arange(0,result.shape[0],int(result.shape[0]/7))xticklabel = pd.Series(result.date[xtick])plt.figure(figsize=(15,3))fig = plt.axes()plt.plot(np.arange(result.shape[0]),result.n*,label = 'RSRS1',linewidth = 2)plt.plot(np.arange(result.shape[0]),result2.n*,label = 'RSRS2',linewidth = 2)plt.plot(np.arange(result.shape[0]),result3.n*,label = 'RSRS3',linewidth = 2)plt.plot(np.arange(result.shape[0]),result4.n*,label = 'RSRS4',linewidth = 2)plt.plot(np.arange(result.shape[0]),result.close/result.close[0],color = 'yellow',label = 'HS300',linewidth = 2)fig.set_xticks(xtick)fig.set_xticklabels(xticklabel,rotation = 45)plt.legend()plt.show()
#四种策略时间更新到当前dateStart = datetime.date(2005,3,1)dateEnd = datetime.date(2019,3,8)N = 18M = 600HS300 = getdata(dateStart,dateEnd,N,M)HS300 = HS300.loc[2:]HS300 =HS300.reset_index(drop = True)HS300.head()
/opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py:22: RuntimeWarning: divide by zero encountered in double_scalars
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
date | high | low | open | close | beta | R2 | ret | beta_norm | RSRS_R2 | beta_right | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2005-04-12 | 993.71 | 978.20 | 993.71 | 978.70 | 0.767238 | 0.653529 | -0.016797 | 0.000000 | 0.000000 | 0.000000 |
1 | 2005-04-13 | 1006.50 | 987.95 | 987.95 | 1000.90 | 0.791216 | 0.687122 | 0.022683 | 1.208831 | 0.830615 | 0.657196 |
2 | 2005-04-14 | 1006.42 | 985.58 | 1004.64 | 986.97 | 0.804497 | 0.670781 | -0.013917 | 0.921975 | 0.618444 | 0.497536 |
3 | 2005-04-15 | 982.61 | 971.93 | 982.61 | 974.08 | 1.214834 | 0.812732 | -0.013060 | 1.719667 | 1.397629 | 1.697887 |
4 | 2005-04-18 | 970.91 | 958.65 | 970.91 | 963.77 | 1.220131 | 0.923110 | -0.010584 | 1.271125 | 1.173388 | 1.431687 |
#斜率指标策略result = RSRS1(HS300)num = result.flag.abs().sum()/2n* = result.n*[result.shape[0]-1]print('交易次数 = ',num)print('策略净值为= ',n*)
交易次数 = 47.5 策略净值为= 11.833232225885457
#标准分策略result2 = RSRS2(HS300)num = result2.flag.abs().sum()/2n* = result2.n*[result.shape[0]-1]ret_year = (n* - 1)print('交易次数 = ',num)print('策略净值为= ',n*)
交易次数 = 53.5 策略净值为= 10.546245684216888
#修正标准分策略result3 = RSRS3(HS300)num = result3.flag.abs().sum()/2n* = result3.n*[result.shape[0]-1]ret_year = (n* - 1)print('交易次数 = ',num)print('策略净值为= ',n*)
交易次数 = 46.5 策略净值为= 9.87532821653873
dateStart = datetime.date(2005,3,1)dateEnd = datetime.date(2019,3,8)N = 16M = 300HS300 = getdata(dateStart,dateEnd,N,M)HS300 = HS300.loc[2:]HS300 =HS300.reset_index(drop = True)HS300.head()
/opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py:22: RuntimeWarning: divide by zero encountered in double_scalars
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
date | high | low | open | close | beta | R2 | ret | beta_norm | RSRS_R2 | beta_right | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2005-04-12 | 993.71 | 978.20 | 993.71 | 978.70 | 0.767238 | 0.653529 | -0.016797 | 0.000000 | 0.000000 | 0.000000 |
1 | 2005-04-13 | 1006.50 | 987.95 | 987.95 | 1000.90 | 0.791216 | 0.687122 | 0.022683 | 1.208831 | 0.830615 | 0.657196 |
2 | 2005-04-14 | 1006.42 | 985.58 | 1004.64 | 986.97 | 0.804497 | 0.670781 | -0.013917 | 0.921975 | 0.618444 | 0.497536 |
3 | 2005-04-15 | 982.61 | 971.93 | 982.61 | 974.08 | 1.214834 | 0.812732 | -0.013060 | 1.719667 | 1.397629 | 1.697887 |
4 | 2005-04-18 | 970.91 | 958.65 | 970.91 | 963.77 | 1.220131 | 0.923110 | -0.010584 | 1.271125 | 1.173388 | 1.431687 |
result4 = RSRS4(HS300)num = result4.flag.abs().sum()/2n* = result4.n*[result.shape[0]-1]ret_year = (n* - 1)print('交易次数 = ',num)print('策略净值为= ',n*)
交易次数 = 39.5 策略净值为= 11.446891338270705
xtick = np.arange(0,result.shape[0],int(result.shape[0]/7))xticklabel = pd.Series(result.date[xtick])plt.figure(figsize=(15,3))fig = plt.axes()plt.plot(np.arange(result.shape[0]),result.n*,label = 'RSRS1',linewidth = 2)plt.plot(np.arange(result.shape[0]),result2.n*,label = 'RSRS2',linewidth = 2)plt.plot(np.arange(result.shape[0]),result3.n*,label = 'RSRS3',linewidth = 2)plt.plot(np.arange(result.shape[0]),result4.n*,label = 'RSRS4',linewidth = 2)plt.plot(np.arange(result.shape[0]),result.close/result.close[0],color = 'yellow',label = 'HS300',linewidth = 2)fig.set_xticks(xtick)fig.set_xticklabels(xticklabel,rotation = 45)plt.legend()plt.show()
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...
移动端课程