概述
本篇基于光大证券研报《基于阻力支撑相对强度(RSRS)的市场择时》,给出了RSRS斜率指标择时,以及在斜率基础上的标准化指标择时策略。
一、阻力支撑相关概念
阻力位是指指标价格上涨时可能遇到的压力,即交易者认为卖方力量开始反超买方,从而价格难以继续上涨或从此回调下跌的价位;支撑位则是交易者认为买方力量开始反超卖方,从而止跌或反弹上涨的价位。
常见的确定阻力支撑位的方法有,布林带上下轨突破策略(突破上轨建仓买入,突破下轨卖出平仓)和均线策略(如超过20日均线建仓买入,低于20日均线卖出平仓)。然而,布林带突破策略在震荡期间出现了持续亏损,均线策略交易交易成本巨大,且在震荡期间的回撤很大。
二、阻力支撑相对强度(RSRS)
阻力支撑相对强度(Resistance Support Relative Strength, RSRS)是另一种阻力位与支撑位的运用方式,它不再把阻力位与支撑位当做一个定值,而是看做一个变量,反应了交易者对目前市场状态顶底的一种预期判断。
从直觉上看,如果这种预期判断极易改变,则表明支撑位或阻力位的强度小,有效性弱;而如果众多交易者预期较为一致、变动不大,则表明支撑位或阻力位强度高,有效性强。
我们按照不同市场状态分类来说明支撑阻力相对强度的应用逻辑:
1.市场在上涨牛市中:
如果支撑明显强于阻力,牛市持续,价格加速上涨
如果阻力明显强于支撑,牛市可能即将结束,价格见顶
2. 市场在震荡中:
如果支撑明显强于阻力,牛市可能即将启动
如果阻力明显强于支撑,熊市可能即将启动
3.市场在下跌熊市中:
如果支撑明显强于阻力,熊市可能即将结束,价格见底
如果阻力明显强于支撑,熊市持续,价格加速下跌
每日最高价和最低价是一种阻力位与支撑位,它是当日全体市场参与者的交易行为所认可的阻力与支撑。一个很自然的想法是建立最高价和最低价的线性回归,并计算出斜率。即:
那么 beta 值就是我们所需要的斜率。其中 N 的取法不能太小,不然不能过滤掉足够多的噪音;但也不能太大,因为我们希望得到的是体现目前市场的支撑阻力相对强度,若取值太大,则滞后性太高。
当斜率值很大时,支撑强度大于阻力强度。在牛市中阻力渐小,上方上涨空间大;在熊市中支撑渐强,下跌势头欲止。
当斜率值很小时,阻力强度大于支撑强度。在牛市中阻力渐强,上涨势头渐止;在熊市中支撑渐送,下方下跌空间渐大。
三、阻力支撑相对强度(RSRS)指标择时策略
在确定阻力与支撑的代理变量以及相对强度的定义之后,我们依此建立RSRS 指标的择时策略,以下回测参数均设置为:
时间:2014-01-01至2018-01-01
调仓频率:1天
基准指数:沪深三百指数(SHSE.000300)
标的:沪深三百指数
滑点:0
手续费:0
第一种方法是直接将斜率作为指标值。当日RSRS斜率指标择时策略如下:
1、取前N日最高价与最低价序列。(N = 18)
2、将两个序列进行OLS线性回归。
3、将拟合后的β值作为当日RSRS斜率指标值。4、根据历史数据算出Sbuy和Ssell
Sbuy=mu+sigma;
Ssell=mu-sigma;
Mu为历史RSRS斜率的平均值,sigma是历史RSRS斜率的标准差
5、当RSRS斜率大于Sbuy时,全仓买入,小于Ssell时,卖出平仓。(Sbuy=1,Ssell=0.8)
上述斜率阈值策略中,上下阈值的选取参考了整个斜率历史数据的均值与标准差。然而在实际中,并不能保证未来数据的均值与标准差不会随着市场发展而改变。同时交易者也可能更关心在当前市场在近期的环境中处在什么样的位置,或者接下来一段时间市场相比于目前将会有怎么的发展。
第二种方法是在斜率基础上进行标准化,取标准分作为指标值。RSRS斜率标准分指标择时策略如下:
1、取前M日的RSRS斜率时间序列。(M = 600)
2、计算当日RSRS斜率的标准分RSRSstd:
其中μM为前M日的斜率均值,σM为前M日的标准差。
3、若RSRSstd大于Sbuy,则全仓买入;若RSRSstd小于Ssell,则卖出平仓。
(Sbuy=0.7,Ssell=−0.7,来自光大证券研报)
四、后记
可以看出,RSRS标准分策略要好于斜率策略,并且,我们可以看出,在15年牛市顶部时,两个策略都事先预知了大跌,避免了损失,这才是两个策略表现优秀的关键,也正是RSRS指标优秀左侧预测能力的体现。
附:RSRS标准分与RSRS斜率源码
RSRS标准分
from __future__ import print_function, absolute_import
from gm.api import *
import statsmodels.api as sm
import numpy as np
def init(context):
# 设置参数
context.N=18
context.M=600
context.ans=[]
context.buy=0.7
context.sell=-0.7
#获取历史数据及历史斜率
prices = history_n(symbol='SHSE.000300', frequency='1d', count=context.M, end_time='2014-01-01', fields='high,low',skip_suspended=True,
fill_missing=None,adjust=ADJUST_PREV,df=True)
highs = prices.high
lows = prices.low
context.ans = []
for i in range(len(highs))[context.N:]:
data_high = highs.iloc[i - context.N + 1:i + 1]
data_low = lows.iloc[i - context.N + 1:i + 1]
X = sm.add_constant(data_low)
model = sm.OLS(data_high, X)
results = model.fit()
context.ans.append(results.params[1])
schedule(schedule_func=algo, date_rule='1d', time_rule='09:40:00')
def algo(context):
# 获取上一个交易日的日期
last_day = get_previous_trading_date(exchange='SHSE', date=context.now)
# 计算前一日的RSRS斜率
prices = history_n(symbol='SHSE.000300', frequency='1d', count=context.N, end_time=last_day, fields='', skip_suspended=True,
fill_missing=None, adjust=ADJUST_PREV, adjust_end_time='', df=True)
#做回归计算
highs = prices.high
lows = prices.low
X = sm.add_constant(lows)
model = sm.OLS(highs, X)
results = model.fit()
context.ans.append(results.params[1])
# 计算标准化的RSRS指标
# 计算均值序列
section = context.ans[-context.M:]
# 计算均值序列
mu = np.mean(section)
# 计算标准化RSRS指标序列
sigma = np.std(section)
zscore = (section[-1] - mu) / sigma
if zscore > context.buy:
order_target_percent(symbol='SHSE.000300', percent=1, order_type=OrderType_Market,
position_side=PositionSide_Long)
if zscore < context.sell:
order_close_all()
if __name__ == '__main__':
run(strategy_id='73bb5bf2-a536-11e8-bd52-9cd21ef04ea9',
filename='RSRS.py',
mode=MODE_BACKTEST,
token='c395247a76e8a5caeee699d668d6f550213bc418',
backtest_start_time='2014-01-01 08:00:00',
backtest_end_time='2018-01-01 16:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0,
backtest_slippage_ratio=0)
RSRS斜率
from __future__ import print_function, absolute_import
from gm.api import *
import statsmodels.api as sm
import numpy as np
def init(context):
#设置参数
context.N=18
context.M=3600
context.ans=[]
#获取历史数据及历史斜率
prices = history_n(symbol='SHSE.000300', frequency='1d', count=context.M, end_time='2014-01-01', fields='high,low',skip_suspended=True,
fill_missing=None,adjust=ADJUST_PREV,df=True)
highs = prices.high
lows = prices.low
context.ans = []
for i in range(len(highs))[context.N:]:
data_high = highs.iloc[i - context.N + 1:i + 1]
data_low = lows.iloc[i - context.N + 1:i + 1]
X = sm.add_constant(data_low)
model = sm.OLS(data_high, X)
results = model.fit()
context.ans.append(results.params[1])
mu=np.mean(context.ans)
sigama=np.std(context.ans)
#求阈值
context.buy=mu+sigama
context.sell=mu-sigama
schedule(schedule_func=algo, date_rule='1d', time_rule='09:40:00')
def algo(context):
# 获取上一个交易日的日期
last_day = get_previous_trading_date(exchange='SHSE', date=context.now)
#计算前一日的RSRS斜率
prices = history_n(symbol='SHSE.000300', frequency='1d', count=context.N, end_time=last_day, fields='', skip_suspended=True,
fill_missing=None, adjust=ADJUST_PREV, adjust_end_time='', df=True)
#做回归计算
highs = prices.high
lows = prices.low
X = sm.add_constant(lows)
model = sm.OLS(highs, X)
results = model.fit().params[1]
if results > context.buy:
order_target_percent(symbol='SHSE.000300', percent=1, order_type=OrderType_Market,
position_side=PositionSide_Long)
if results < context.sell:
order_close_all()
if __name__ == '__main__':
run(strategy_id='73bb5bf2-a536-11e8-bd52-9cd21ef04ea9',
filename='789.py',
mode=MODE_BACKTEST,
token='c395247a76e8a5caeee699d668d6f550213bc418',
backtest_start_time='2014-01-01 08:00:00',
backtest_end_time='2018-01-01 16:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0,
backtest_slippage_ratio=0)
来源:掘金量化 myquan.cn
相关阅读: | 量化交易 | 期货模拟交易 | python量化交易 | 股票数据 | 量化交易策略 | 机器学习算法 | 多因子选股 |
| 双均线策略 | 网格交易法 | 海龟交易法 | 跨期套利 | 行业轮动 | 指数增强 | 跨品种套利 | 日内交易 |