0.0
我们用相对位置变化程度,即类似 delta(high)/delta(low)的值来描述支撑位与阻力位的相对强度,即最低价每变动 1 的时候,最高价变动的幅度。实际上,delta(high)/delta(low)是连接高低价格平面上的两点(low[0],high[0])与(low[1],high[1])的斜率。由于市场量价本身噪音的存在,通过两点得到的斜率也包含了太大的噪音。我们考虑通过最近 N 个(low,high)的数据点来得到信噪比较高的最高最低价相对变化程度,自然而然的想法即是使用线性回归。如果我们建立如下般最高价与最低价之间的线性模型:
high = alpha + beta*low + epsilon, epsilon ~ N(0,sigma) (1)
那么 beta 值就是我们所需要的斜率。其中 N 的取法不能太小,不然不能过滤掉足够多的噪音;但也不能太大,因为我们希望得到的是体现目前市场的支撑阻力相对强度,若取值太大,则滞后性太高。 当斜率值很大时,支撑强度强于阻力强度。从最高价最低价序列来看,最高价变动比最低价迅速。在上涨牛市中与下跌熊市中很可能以下图中两种 走势体现:在牛市中阻力渐小,上方上涨空间大;在熊市中支撑渐强,下跌势头欲止。
import statsmodels.api as sm
from jqdata import *
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
在确定阻力与支撑的代理变量以及相对强度的定义之后,我们依此建立 RSRS 指标。一种即是直接利用斜率的本身作为指标值。 当日斜率指标的计算方式:
prices = get_price('RB8888.XSGE', start_date='2011-01-01', end_date='2019-06-12', frequency='1d', fields=None,
skip_paused=False, fq='pre', count=None)#RB9999.XSGE//
prices.head()
open | close | high | low | volume | money | |
---|---|---|---|---|---|---|
2011-01-04 | 4838.051 | 4833.245 | 4852.405 | 4815.801 | 310108.0 | 1.498835e+10 |
2011-01-05 | 4814.745 | 4810.921 | 4834.319 | 4803.001 | 268464.0 | 1.296841e+10 |
2011-01-06 | 4828.098 | 4831.611 | 4846.706 | 4823.152 | 227804.0 | 1.102504e+10 |
2011-01-07 | 4820.718 | 4815.868 | 4849.022 | 4800.042 | 417424.0 | 2.009288e+10 |
2011-01-10 | 4832.823 | 4868.282 | 4889.586 | 4832.331 | 589132.0 | 2.873228e+10 |
N = 24 #设置周期
betas=[]
rsquared=[]
for i in range(N-1,len(prices)):
highs = prices.iloc[i-23:i].high
lows = prices.iloc[i-23:i].low
x = sm.add_constant(lows)
model = sm.OLS(highs, x)
beta = model.fit().params.iloc[-1] # beta值
r2 = model.fit().rsquared # 决定系数值
betas.append(beta)
rsquared.append(r2)
betas=pd.Series(betas)
print(betas.max(),betas.min())
1.3836441507595802 0.34250621423126404
按照阈值交易框架,我们需要确定上下两个阈值。为了能找到比较合理的阈值,我们观察斜率的历史数据分布(以 N=24 计算):
plt.hist(betas,bins=50)
plt.title('11年 至 19年 斜率数据分布')
Text(0.5, 1.0, '11年 至 19年 斜率数据分布')
print('11年 至 19年 历史 RSRS 斜率数据低阶矩统计','\n',
'batas 均值:', betas.mean(),'\n',
'betas 标准差:', betas.std(),'\n',
'batas 偏度:', betas.skew(),'\n',
'batas 峰度:', betas.kurt(),'\n',)
11年 至 19年 历史 RSRS 斜率数据低阶矩统计 batas 均值: 0.9399496191208246 betas 标准差: 0.12044712500613271 batas 偏度: -0.35473290389140893 batas 峰度: 2.2292155484149805
df=pd.DataFrame(prices.close.iloc[N-1:])
df['beta']=betas.tolist()
df.tail()
close | beta | |
---|---|---|
2019-06-05 | 3670.645 | 1.063328 |
2019-06-06 | 3659.382 | 1.092090 |
2019-06-10 | 3638.421 | 1.065440 |
2019-06-11 | 3750.432 | 1.068782 |
2019-06-12 | 3695.206 | 1.037648 |
fig1,ax = plt.subplots(figsize = (20,16)) #plt.subplot会返回一个figure对象和一个坐标轴对象;
plt.plot(df['close'], lw=1.5, label='line1')
plt.grid(True)
plt.legend()
ax2 = ax.twinx() #复制上一张子图的横坐标轴;
plt.plot(df['beta'], 'y', lw=1.5, label='line2')
plt.legend()
plt.title('RB收盘价与RSRS走势图')
Text(0.5, 1.0, 'RB收盘价与RSRS走势图')
从统计数据出发,一个看上去比较合理的阈值选取即均值加减一个标准差,我们取 S1=1.0,S2=0.8。 则 RSRS 斜率指标交易策略为:
df['return']=df['close'].pct_change()
df.head()
close | beta | return | |
---|---|---|---|
2011-02-11 | 5130.158 | 1.043683 | NaN |
2011-02-14 | 5118.474 | 1.059407 | -0.002278 |
2011-02-15 | 5124.553 | 1.043988 | 0.001188 |
2011-02-16 | 5074.524 | 1.020823 | -0.009763 |
2011-02-17 | 4993.865 | 1.040178 | -0.015895 |
df['signal']=np.where(df.beta>1,1,np.nan)
df['signal']=np.where(df.beta<0.8,-1,df['signal'])
df.head()
close | beta | return | signal | |
---|---|---|---|---|
2011-02-11 | 5130.158 | 1.043683 | NaN | 1.0 |
2011-02-14 | 5118.474 | 1.059407 | -0.002278 | 1.0 |
2011-02-15 | 5124.553 | 1.043988 | 0.001188 | 1.0 |
2011-02-16 | 5074.524 | 1.020823 | -0.009763 | 1.0 |
2011-02-17 | 4993.865 | 1.040178 | -0.015895 | 1.0 |
df=df.fillna(method='ffill')
df['strategy_return']=df['return']*df['signal'].shift(1)
df['strategy_cum_return']=(1 + df['strategy_return']).cumprod()
df['strategy_cum_return'].plot(figsize=(20,16))
<matplotlib.axes._subplots.AxesSubplot at 0x7ff3b9063588>
print('在不计成本的情况下 净值 ', df['strategy_cum_return'].iloc[-1] )
annual_yield=df['strategy_return'].mean() * 252 #年化收益率;
print('年化收益率:', annual_yield)
annual_risk=df['strategy_return'].std() * 252 ** 0.5 #年化风险;
print('年化风险: ', annual_risk)
trade_count=0
for i in range(0,len(df)-1):
if df.signal.iloc[i]*df.signal.iloc[i+1] != 1:
trade_count+=1
print('交易次数: ', trade_count)
#计算夏普比率
sharperatio=np.sqrt(252)*(annual_yield-0.04)/annual_risk
print('夏普率为: ', sharperatio)
df['cumret'] = df['return'].cumsum().apply(np.exp)
df['cummax'] = df['cumret'].cummax()
max_drown = (df['cummax'] - df['cumret']).max()
print('最大回撤:',max_drown)
在不计成本的情况下 净值 2.616265204755879 年化收益率: 0.14571056196291293 年化风险: 0.22880534240296319 交易次数: 34 夏普率为: 7.33419565215002 最大回撤: 0.6643126450165031
df['beta_normal']=(df['beta']-df['beta'].rolling(300).mean())/df['beta'].rolling(300).std()
df.tail()
close | beta | return | signal | strategy_return | strategy_cum_return | cumret | cummax | beta_normal | |
---|---|---|---|---|---|---|---|---|---|
2019-06-05 | 3670.645 | 1.063328 | 0.000381 | 1.0 | 0.000381 | 2.598876 | 0.882765 | 1.048277 | 1.111056 |
2019-06-06 | 3659.382 | 1.092090 | -0.003068 | 1.0 | -0.003068 | 2.590901 | 0.880060 | 1.048277 | 1.369409 |
2019-06-10 | 3638.421 | 1.065440 | -0.005728 | 1.0 | -0.005728 | 2.576061 | 0.875034 | 1.048277 | 1.114218 |
2019-06-11 | 3750.432 | 1.068782 | 0.030786 | 1.0 | 0.030786 | 2.655366 | 0.902391 | 1.048277 | 1.137511 |
2019-06-12 | 3695.206 | 1.037648 | -0.014725 | 1.0 | -0.014725 | 2.616265 | 0.889201 | 1.048277 | 0.843464 |
# df[df.beta_normal==np.inf]=0
df.beta_normal.min()
-5.377582720548235
plt.hist(df.beta_normal,bins=50)
plt.title('11年 至 19年 标准分数据分布')
/opt/conda/lib/python3.6/site-packages/numpy/lib/function_base.py:780: RuntimeWarning: invalid value encountered in greater_equal keep = (tmp_a >= first_edge) /opt/conda/lib/python3.6/site-packages/numpy/lib/function_base.py:781: RuntimeWarning: invalid value encountered in less_equal keep &= (tmp_a <= last_edge)
Text(0.5, 1.0, '11年 至 19年 标准分数据分布')
print('11年 至 19年 历史 RSRS 标准分数据统计','\n',
'标准分 batas 均值:', df.beta_normal.mean(),'\n',
'标准分 batas 标准差:', df.beta_normal.std(),'\n',
'标准分 batas 偏度:', df.beta_normal.skew(),'\n',
'标准分 batas 峰度:', df.beta_normal.kurt(),'\n',)
11年 至 19年 历史 RSRS 标准分数据统计 标准分 batas 均值: 0.057697635792595944 标准分 batas 标准差: 1.067676127284525 标准分 batas 偏度: -0.48906058808530584 标准分 batas 峰度: 1.41318615951353
df['signal_normal']=np.where(df.beta_normal > 1.8,1,np.nan)
df['signal_normal']=np.where(df.beta_normal < -1.8,-1,df['signal_normal'])
df.tail()
close | beta | return | signal | strategy_return | strategy_cum_return | cumret | cummax | beta_normal | signal_normal | |
---|---|---|---|---|---|---|---|---|---|---|
2019-06-05 | 3670.645 | 1.063328 | 0.000381 | 1.0 | 0.000381 | 2.598876 | 0.882765 | 1.048277 | 1.111056 | NaN |
2019-06-06 | 3659.382 | 1.092090 | -0.003068 | 1.0 | -0.003068 | 2.590901 | 0.880060 | 1.048277 | 1.369409 | NaN |
2019-06-10 | 3638.421 | 1.065440 | -0.005728 | 1.0 | -0.005728 | 2.576061 | 0.875034 | 1.048277 | 1.114218 | NaN |
2019-06-11 | 3750.432 | 1.068782 | 0.030786 | 1.0 | 0.030786 | 2.655366 | 0.902391 | 1.048277 | 1.137511 | NaN |
2019-06-12 | 3695.206 | 1.037648 | -0.014725 | 1.0 | -0.014725 | 2.616265 | 0.889201 | 1.048277 | 0.843464 | NaN |
df=df.fillna(method='ffill').dropna()
df.tail()
close | beta | return | signal | strategy_return | strategy_cum_return | cumret | cummax | beta_normal | signal_normal | |
---|---|---|---|---|---|---|---|---|---|---|
2019-06-05 | 3670.645 | 1.063328 | 0.000381 | 1.0 | 0.000381 | 2.598876 | 0.882765 | 1.048277 | 1.111056 | -1.0 |
2019-06-06 | 3659.382 | 1.092090 | -0.003068 | 1.0 | -0.003068 | 2.590901 | 0.880060 | 1.048277 | 1.369409 | -1.0 |
2019-06-10 | 3638.421 | 1.065440 | -0.005728 | 1.0 | -0.005728 | 2.576061 | 0.875034 | 1.048277 | 1.114218 | -1.0 |
2019-06-11 | 3750.432 | 1.068782 | 0.030786 | 1.0 | 0.030786 | 2.655366 | 0.902391 | 1.048277 | 1.137511 | -1.0 |
2019-06-12 | 3695.206 | 1.037648 | -0.014725 | 1.0 | -0.014725 | 2.616265 | 0.889201 | 1.048277 | 0.843464 | -1.0 |
df['normal_return']=df['return']*df['signal_normal'].shift(1)
df['normal_cum_return']=(1 + df['normal_return']).cumprod()
df['normal_cum_return'].plot(figsize=(20,16))
<matplotlib.axes._subplots.AxesSubplot at 0x7ff3b9049e80>
print('在不计成本的情况下 净值 ', df['normal_cum_return'].iloc[-1] * 1)
annual_yield=df['normal_return'].mean() * 252 #年化收益率;
print('年化收益率:', annual_yield)
annual_risk=df['normal_return'].std() * 252 ** 0.5 #年化风险;
print('年化风险: ', annual_risk)
trade_count=0
for i in range(0,len(df)-1):
if df.signal_normal.iloc[i]*df.signal_normal.iloc[i+1] != 1:
trade_count+=1
print('交易次数: ', trade_count)
#计算夏普比率
sharperatio=np.sqrt(252)*(annual_yield-0.04)/annual_risk
print('夏普率为: ', sharperatio)
df['cumret'] = df['normal_return'].cumsum().apply(np.exp)
df['cummax'] = df['cumret'].cummax()
max_drown = (df['cummax'] - df['cumret']).max()
print('最大回撤:',max_drown)
在不计成本的情况下 净值 3.6341273103397116 年化收益率: 0.22207598097666353 年化风险: 0.24359596752458723 交易次数: 12 夏普率为: 11.86541231230577 最大回撤: 1.8306793286511196
len(df)
1691
df['beta_modify']=df['beta_normal']*rsquared[-len(df):]
#df[df.beta_right==np.inf]=0
#df[df.beta_right==-np.inf]=0
#df.head()
df[df.beta_modify==np.inf]
df[df.beta_modify==-np.inf]
close | beta | return | signal | strategy_return | strategy_cum_return | cumret | cummax | beta_normal | signal_normal | normal_return | normal_cum_return | beta_modify |
---|
plt.hist(df.beta_modify, bins=50, normed=True)
plt.title('11年 至 19年 修正标准分数据分布')
/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")
Text(0.5, 1.0, '11年 至 19年 修正标准分数据分布')
print('batas 修正均值:', df.beta_modify.mean(),'\n',
'batas 修正标准差:', df.beta_modify.mean(),'\n',
'batas 修正偏度:', df.beta_modify.skew(),'\n',
'batas 修正峰度:', df.beta_modify.kurt(),'\n',)
batas 修正均值: 0.10017940112218975 batas 修正标准差: 0.10017940112218975 batas 修正偏度: 0.0850981193604876 batas 修正峰度: -0.007994364584743785
df['signal_modify']=np.where(df.beta_modify>1,1,np.nan)
df['signal_modify']=np.where(df.beta_modify<-1,-1,df['signal_modify'])
df=df.fillna(method='ffill').dropna()
df.tail()
close | beta | return | signal | strategy_return | strategy_cum_return | cumret | cummax | beta_normal | signal_normal | normal_return | normal_cum_return | beta_modify | signal_modify | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2019-06-05 | 3670.645 | 1.063328 | 0.000381 | 1.0 | 0.000381 | 2.598876 | 4.466401 | 5.535877 | 1.111056 | -1.0 | -0.000381 | 3.662863 | 0.983060 | 1.0 |
2019-06-06 | 3659.382 | 1.092090 | -0.003068 | 1.0 | -0.003068 | 2.590901 | 4.480127 | 5.535877 | 1.369409 | -1.0 | 0.003068 | 3.674103 | 1.210240 | 1.0 |
2019-06-10 | 3638.421 | 1.065440 | -0.005728 | 1.0 | -0.005728 | 2.576061 | 4.505863 | 5.535877 | 1.114218 | -1.0 | 0.005728 | 3.695148 | 0.988048 | 1.0 |
2019-06-11 | 3750.432 | 1.068782 | 0.030786 | 1.0 | 0.030786 | 2.655366 | 4.369261 | 5.535877 | 1.137511 | -1.0 | -0.030786 | 3.581390 | 1.016182 | 1.0 |
2019-06-12 | 3695.206 | 1.037648 | -0.014725 | 1.0 | -0.014725 | 2.616265 | 4.434075 | 5.535877 | 0.843464 | -1.0 | 0.014725 | 3.634127 | 0.728275 | 1.0 |
df['modify_return']=df['return']*df['signal_modify'].shift(1)
df['modify_cum_return']=(1 + df['modify_return']).cumprod()
df['modify_cum_return'].plot(figsize=(20,16))
<matplotlib.axes._subplots.AxesSubplot at 0x7ff3b8632198>
print('在不计成本的情况下\n净值 ', df['modify_cum_return'].iloc[-1])
annual_yield=df['modify_return'].mean() * 252 #年化收益率;
print('年化收益率:', annual_yield)
annual_risk=df['modify_return'].std() * 252 ** 0.5 #年化风险;
print('年化风险: ', annual_risk)
trade_count=0
for i in range(0,len(df)-1):
if df.signal_modify.iloc[i]*df.signal_modify.iloc[i+1] != 1:
trade_count+=1
print('交易次数: ', trade_count)
#计算夏普比率
sharperatio=np.sqrt(252)*(annual_yield-0.04)/annual_risk
print('夏普率为: ', sharperatio)
df['cumret'] = df['modify_return'].cumsum().apply(np.exp)
df['cummax'] = df['cumret'].cummax()
max_drown = (df['cummax'] - df['cumret']).max()
print('最大回撤:',max_drown)
在不计成本的情况下 净值 1.2839902592854109 年化收益率: 0.06700791269102259 年化风险: 0.24401967925320286 交易次数: 29 夏普率为: 1.7569784690335326 最大回撤: 1.7485859510230237
df.head()
close | beta | return | signal | strategy_return | strategy_cum_return | cumret | cummax | beta_normal | signal_normal | normal_return | normal_cum_return | beta_modify | signal_modify | modify_return | modify_cum_return | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2012-07-02 | 4033.034 | 0.656530 | -0.006676 | -1.0 | 0.006676 | 1.101804 | NaN | NaN | -1.864575 | -1.0 | 0.006676 | 1.006676 | -1.515561 | -1.0 | NaN | NaN |
2012-07-03 | 4069.243 | 0.590931 | 0.008978 | -1.0 | -0.008978 | 1.091912 | 0.991062 | 0.991062 | -2.452583 | -1.0 | -0.008978 | 0.997638 | -1.941138 | -1.0 | -0.008978 | 0.991022 |
2012-07-04 | 4079.173 | 0.590827 | 0.002440 | -1.0 | -0.002440 | 1.089248 | 0.988647 | 0.991062 | -2.420966 | -1.0 | -0.002440 | 0.995204 | -1.981758 | -1.0 | -0.002440 | 0.988604 |
2012-07-05 | 4085.269 | 0.604350 | 0.001494 | -1.0 | -0.001494 | 1.087620 | 0.987170 | 0.991062 | -2.267913 | -1.0 | -0.001494 | 0.993716 | -1.905444 | -1.0 | -0.001494 | 0.987126 |
2012-07-06 | 4078.412 | 0.609326 | -0.001678 | -1.0 | 0.001678 | 1.089446 | 0.988829 | 0.991062 | -2.196319 | -1.0 | 0.001678 | 0.995384 | -1.826887 | -1.0 | 0.001678 | 0.988783 |
fig1,ax = plt.subplots(figsize = (20,12)) #plt.subplot会返回一个figure对象和一个坐标轴对象;
plt.plot(df.strategy_cum_return)
plt.plot(df.normal_cum_return)
plt.plot(df.modify_cum_return)
plt.grid(True)
plt.legend()
ax2 = ax.twinx() #复制上一张子图的横坐标轴;
plt.plot(df.close, 'y.')
plt.legend(loc = 'upper left')
plt.title('RB收盘价与RSRS斜率策略、标准分、修正走势图')
Text(0.5, 1.0, 'RB收盘价与RSRS斜率策略、标准分、修正走势图')
由上图可以看出修正的无偏标准分策略表现并没有比标准分策略来的好,甚至不如基础的斜率策略。 虽然基于拟合效果的指标优化结果不尽人意,但优化的方式本质上是改变了标准分分布。我们期望能通过研究标准分分布对未来市场收益的预测性 来继续优化指标本身。 我们通过研究标准分以及对应其后未来 10 日的市场涨跌概率及预期收益率来判断比较指标对未来市场收益的预测性。
df['10_normal_return']=df['normal_return'].rolling(10).sum().shift(-10)
df.head()
close | beta | return | signal | strategy_return | strategy_cum_return | cumret | cummax | beta_normal | signal_normal | normal_return | normal_cum_return | beta_modify | signal_modify | modify_return | modify_cum_return | 10_normal_return | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2012-07-02 | 4033.034 | 0.656530 | -0.006676 | -1.0 | 0.006676 | 1.101804 | NaN | NaN | -1.864575 | -1.0 | 0.006676 | 1.006676 | -1.515561 | -1.0 | NaN | NaN | 0.031559 |
2012-07-03 | 4069.243 | 0.590931 | 0.008978 | -1.0 | -0.008978 | 1.091912 | 0.991062 | 0.991062 | -2.452583 | -1.0 | -0.008978 | 0.997638 | -1.941138 | -1.0 | -0.008978 | 0.991022 | 0.049036 |
2012-07-04 | 4079.173 | 0.590827 | 0.002440 | -1.0 | -0.002440 | 1.089248 | 0.988647 | 0.991062 | -2.420966 | -1.0 | -0.002440 | 0.995204 | -1.981758 | -1.0 | -0.002440 | 0.988604 | 0.050499 |
2012-07-05 | 4085.269 | 0.604350 | 0.001494 | -1.0 | -0.001494 | 1.087620 | 0.987170 | 0.991062 | -2.267913 | -1.0 | -0.001494 | 0.993716 | -1.905444 | -1.0 | -0.001494 | 0.987126 | 0.061999 |
2012-07-06 | 4078.412 | 0.609326 | -0.001678 | -1.0 | 0.001678 | 1.089446 | 0.988829 | 0.991062 | -2.196319 | -1.0 | 0.001678 | 0.995384 | -1.826887 | -1.0 | 0.001678 | 0.988783 | 0.080699 |
plt.bar(df.beta_normal, df['10_normal_return'], width=0.1)
plt.title('RSRS 标准分对应其后未来 10 日期望收益')
Text(0.5, 1.0, 'RSRS 标准分对应其后未来 10 日期望收益')
df['10_modify_return']=df['modify_return'].rolling(10).sum().shift(-10)
df.head()
close | beta | return | signal | strategy_return | strategy_cum_return | cumret | cummax | beta_normal | signal_normal | normal_return | normal_cum_return | beta_modify | signal_modify | modify_return | modify_cum_return | 10_normal_return | 10_modify_return | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2012-07-02 | 4033.034 | 0.656530 | -0.006676 | -1.0 | 0.006676 | 1.101804 | NaN | NaN | -1.864575 | -1.0 | 0.006676 | 1.006676 | -1.515561 | -1.0 | NaN | NaN | 0.031559 | 0.031559 |
2012-07-03 | 4069.243 | 0.590931 | 0.008978 | -1.0 | -0.008978 | 1.091912 | 0.991062 | 0.991062 | -2.452583 | -1.0 | -0.008978 | 0.997638 | -1.941138 | -1.0 | -0.008978 | 0.991022 | 0.049036 | 0.049036 |
2012-07-04 | 4079.173 | 0.590827 | 0.002440 | -1.0 | -0.002440 | 1.089248 | 0.988647 | 0.991062 | -2.420966 | -1.0 | -0.002440 | 0.995204 | -1.981758 | -1.0 | -0.002440 | 0.988604 | 0.050499 | 0.050499 |
2012-07-05 | 4085.269 | 0.604350 | 0.001494 | -1.0 | -0.001494 | 1.087620 | 0.987170 | 0.991062 | -2.267913 | -1.0 | -0.001494 | 0.993716 | -1.905444 | -1.0 | -0.001494 | 0.987126 | 0.061999 | 0.061999 |
2012-07-06 | 4078.412 | 0.609326 | -0.001678 | -1.0 | 0.001678 | 1.089446 | 0.988829 | 0.991062 | -2.196319 | -1.0 | 0.001678 | 0.995384 | -1.826887 | -1.0 | 0.001678 | 0.988783 | 0.080699 | 0.080699 |
plt.bar(df.beta_modify, df['10_modify_return'], width=0.1)
plt.title('RSRS 修正标准分对应其后未来 10 日期望收益')
Text(0.5, 1.0, 'RSRS 修正标准分对应其后未来 10 日期望收益')
对标准分进行拟合效果的修正使得指标与 未来 10 日收益率的整体相关性得以改善。观察指标值域的改变,一个大胆的想法是,是否右侧数据值域越广,其对未来收益率的预测越好?是否左侧数据值域越窄越好?能否通过改变标准分的分布来达到改善整体指标预测性的目的?
df['right_beta']=df['beta']*df['beta_modify']
df.head()
close | beta | return | signal | strategy_return | strategy_cum_return | cumret | cummax | beta_normal | signal_normal | normal_return | normal_cum_return | beta_modify | signal_modify | modify_return | modify_cum_return | 10_normal_return | 10_modify_return | right_beta | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2012-07-02 | 4033.034 | 0.656530 | -0.006676 | -1.0 | 0.006676 | 1.101804 | NaN | NaN | -1.864575 | -1.0 | 0.006676 | 1.006676 | -1.515561 | -1.0 | NaN | NaN | 0.031559 | 0.031559 | -0.995012 |
2012-07-03 | 4069.243 | 0.590931 | 0.008978 | -1.0 | -0.008978 | 1.091912 | 0.991062 | 0.991062 | -2.452583 | -1.0 | -0.008978 | 0.997638 | -1.941138 | -1.0 | -0.008978 | 0.991022 | 0.049036 | 0.049036 | -1.147079 |
2012-07-04 | 4079.173 | 0.590827 | 0.002440 | -1.0 | -0.002440 | 1.089248 | 0.988647 | 0.991062 | -2.420966 | -1.0 | -0.002440 | 0.995204 | -1.981758 | -1.0 | -0.002440 | 0.988604 | 0.050499 | 0.050499 | -1.170876 |
2012-07-05 | 4085.269 | 0.604350 | 0.001494 | -1.0 | -0.001494 | 1.087620 | 0.987170 | 0.991062 | -2.267913 | -1.0 | -0.001494 | 0.993716 | -1.905444 | -1.0 | -0.001494 | 0.987126 | 0.061999 | 0.061999 | -1.151556 |
2012-07-06 | 4078.412 | 0.609326 | -0.001678 | -1.0 | 0.001678 | 1.089446 | 0.988829 | 0.991062 | -2.196319 | -1.0 | 0.001678 | 0.995384 | -1.826887 | -1.0 | 0.001678 | 0.988783 | 0.080699 | 0.080699 | -1.113170 |
plt.hist(df.right_beta,bins=50, normed=True)
plt.title('11年 至 19年 右偏修正标准分数据分布')
/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")
Text(0.5, 1.0, '11年 至 19年 右偏修正标准分数据分布')
df['10_right_return']=df['modify_return'].rolling(10).sum().shift(-10)
plt.bar(df.right_beta, df['10_right_return'], width=0.1)
plt.title('RSRS 右偏修正标准分对应其后未来 10 日期望收益')
Text(0.5, 1.0, 'RSRS 右偏修正标准分对应其后未来 10 日期望收益')
我们尝试在右偏标准分指标上应用阈值交易策略,参数选取较标准分策 略有所改变,N 取 24,M 取 300,阈值不变。 右偏标准分指标交易策略:
df['signal_right']=np.where(df.right_beta>1.8,1,np.nan)
df['signal_right']=np.where(df.right_beta<-1.8,-1,df['signal_right'])
df=df.fillna(method='ffill').dropna()
df.tail()
close | beta | return | signal | strategy_return | strategy_cum_return | cumret | cummax | beta_normal | signal_normal | normal_return | normal_cum_return | beta_modify | signal_modify | modify_return | modify_cum_return | 10_normal_return | 10_modify_return | right_beta | 10_right_return | signal_right | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2019-06-05 | 3670.645 | 1.063328 | 0.000381 | 1.0 | 0.000381 | 2.598876 | 1.555580 | 3.227134 | 1.111056 | -1.0 | -0.000381 | 3.662863 | 0.983060 | 1.0 | 0.000381 | 1.275456 | 0.019763 | -0.019763 | 1.045315 | -0.019763 | 1.0 |
2019-06-06 | 3659.382 | 1.092090 | -0.003068 | 1.0 | -0.003068 | 2.590901 | 1.550814 | 3.227134 | 1.369409 | -1.0 | 0.003068 | 3.674103 | 1.210240 | 1.0 | -0.003068 | 1.271542 | 0.019763 | -0.019763 | 1.321691 | -0.019763 | 1.0 |
2019-06-10 | 3638.421 | 1.065440 | -0.005728 | 1.0 | -0.005728 | 2.576061 | 1.541957 | 3.227134 | 1.114218 | -1.0 | 0.005728 | 3.695148 | 0.988048 | 1.0 | -0.005728 | 1.264259 | 0.019763 | -0.019763 | 1.052706 | -0.019763 | 1.0 |
2019-06-11 | 3750.432 | 1.068782 | 0.030786 | 1.0 | 0.030786 | 2.655366 | 1.590165 | 3.227134 | 1.137511 | -1.0 | -0.030786 | 3.581390 | 1.016182 | 1.0 | 0.030786 | 1.303180 | 0.019763 | -0.019763 | 1.086077 | -0.019763 | 1.0 |
2019-06-12 | 3695.206 | 1.037648 | -0.014725 | 1.0 | -0.014725 | 2.616265 | 1.566921 | 3.227134 | 0.843464 | -1.0 | 0.014725 | 3.634127 | 0.728275 | 1.0 | -0.014725 | 1.283990 | 0.019763 | -0.019763 | 0.755693 | -0.019763 | 1.0 |
df['right_return']=df['return']*df['signal_right'].shift(1)
df['right_cum_return']=(1 + df['right_return']).cumprod()
df['right_cum_return'].plot(figsize=(20,16))
<matplotlib.axes._subplots.AxesSubplot at 0x7ff3afafa9b0>
print('在不计成本的情况下 净值 ', df['right_cum_return'].iloc[-1])
annual_yield=df['right_return'].mean() * 252 #年化收益率;
print('年化收益率:', annual_yield)
annual_risk=df['right_return'].std() * 252 ** 0.5 #年化风险;
print('年化风险: ', annual_risk)
trade_count=0
for i in range(0,len(df)-1):
if df.signal_right.iloc[i]*df.signal_right.iloc[i+1] != 1:
trade_count+=1
print('交易次数: ', trade_count)
#计算夏普比率
sharperatio=np.sqrt(252)*(annual_yield-0.04)/annual_risk
print('夏普率为: ', sharperatio)
df['cumret'] = df['right_return'].cumsum().apply(np.exp)
df['cummax'] = df['cumret'].cummax()
max_drown = (df['cummax'] - df['cumret']).max()
print('最大回撤:',max_drown)
在不计成本的情况下 净值 1.037056349854957 年化收益率: 0.035761401277096226 年化风险: 0.24597335296060116 交易次数: 0 夏普率为: -0.2735486098771588 最大回撤: 0.7198899754028613
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...
移动端课程