请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  量化平台 帖子:3364737 新帖:1

RSRS指标的运用

我太难了发表于:7 月 1 日 10:00回复(1)

0.0

1、阻力支撑代理变量的定义¶

我们用相对位置变化程度,即类似 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

2、阻力支撑相对强度(RSRS )指标的构建¶

在确定阻力与支撑的代理变量以及相对强度的定义之后,我们依此建立 RSRS 指标。一种即是直接利用斜率的本身作为指标值。 当日斜率指标的计算方式:

  1. 取前 N 日的最高价序列与最低价序列。
  2. 将两列数据按式(1)的模型进行 OLS 线性回归。
  3. 将拟合后的 beta 值作为当日 RSRS 斜率指标值。 另一种则为将斜率标准化,取其标准分作为指标值。 当日标准分指标的计算方式:
  4. 取前 M 日的斜率时间序列。
  5. 以此样本计算当日斜率的标准分。
  6. 将计算得到的标准分 z 作为当日 RSRS 标准分指标值。

以rb螺纹钢为例进行分析¶

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()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
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()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
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走势图')

RSRS指标择时初步效果¶

1、基础斜率数据¶

从统计数据出发,一个看上去比较合理的阈值选取即均值加减一个标准差,我们取 S1=1.0,S2=0.8。 则 RSRS 斜率指标交易策略为:

  1. 计算 RSRS 斜率。
  2. 如果斜率大于 1,则若持有空仓先平空仓,并开仓做多。
  3. 如果斜率小于 0.8,则若有多仓先平多仓,并开仓做空。
df['return']=df['close'].pct_change()
df.head()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
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()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
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

2、标准分数据¶

df['beta_normal']=(df['beta']-df['beta'].rolling(300).mean())/df['beta'].rolling(300).std()
df.tail()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
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()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
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()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
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

3、修正标准分¶

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]
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
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()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
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()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
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()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
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()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
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()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
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,阈值不变。 右偏标准分指标交易策略:

  1. 计算右偏标准分(N=24,M=300)。
  2. 如果右偏标准分大于 S(S=1.8),则买入做多。
  3. 如果右偏标准分小于-S,则卖出做空。
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()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
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
 

全部回复

0/140

量化课程

    移动端课程