RSRS阻力支撑相对强度策略
一、阻力支撑相关概念
阻力位又称压力位,是指价格上涨到某个价位附近时,价格停止上涨甚至回落;其指指标价格上涨时可能遇到的压力,即交易者认为卖方力量开始反超买方,从而价格难以继续上涨或从此回调下跌的价位;支撑位则是交易者认为买方力量开始反超卖方,从而止跌或反弹上涨的价位。
常见的确定阻力支撑位的方法有,布林带上下轨突破策略(突破上轨建仓买入,突破下轨卖出平仓)和均线策略(如超过20日均线建仓买入,低于20日均线卖出平仓)。然而,布林带突破策略在震荡期间出现了持续亏损,均线策略交易交易成本巨大,且在震荡期间的回撤很大。
二、阻力支撑相对强度(RSRS)
阻力支撑相对强度(Resistance Support Relative Strength, RSRS)是另一种阻力位与支撑位的运用方式,它不再把阻力位与支撑位当做一个定值,而是看做一个变量,反应了交易者对目前市场状态顶底的一种预期判断。
我们按照不同市场状态分类来说明支撑阻力相对强度的应用逻辑:
1.市场在上涨牛市中:
如果支撑明显强于阻力,牛市持续,价格加速上涨
如果阻力明显强于支撑,牛市可能即将结束,价格见顶
2.市场在震荡中:
如果支撑明显强于阻力,牛市可能即将启动
如果阻力明显强于支撑,熊市可能即将启动
3.市场在下跌熊市中:
如果支撑明显强于阻力,熊市可能即将结束,价格见底
如果阻力明显强于支撑,熊市持续,价格加速下跌
每日最高价和最低价是一种阻力位与支撑位,它是当日全体市场参与者的交易行为所认可的阻力与支撑。一个很自然的想法是建立最高价和最低价的线性回归,并计算出斜率。即:
high=α+β·low+ϵ,ϵ∼N(0,δ2)
当斜率值很大时,支撑强度大于阻力强度。在牛市中阻力渐小,上方上涨空间大;在熊市中支撑渐强,下跌势头欲止。
当斜率值很小时,阻力强度大于支撑强度。在牛市中阻力渐强,上涨势头渐止;在熊市中支撑渐送,下方下跌空间渐大。
可参考光大研究报告。
三、阻力支撑相对强度(RSRS)指标择时策略
第一种方法是直接将斜率作为指标值。当日RSRS斜率指标择时策略如下:
1、取前N日最高价与最低价序列。(N = 18)
2、将两个序列进行OLS线性回归。
3、将拟合后的 β值作为当日RSRS斜率指标值。
4、当RSRS斜率大于 Sbuy时,全仓买入,小于 Ssell时,卖出平仓。(Sbuy=1,Ssell=0.8)
由于市场处于不同时期时,斜率的均值有比较大的波动。因此,直接采用斜率均值作为择时指标并不太合适。我们尝试下面的方法。
第二种方法是在斜率基础上进行标准化,取标准分作为指标值。RSRS斜率标准分指标择时策略如下:
1、取前M日的RSRS斜率时间序列。(M = 600)
2、计算当日RSRS斜率的标准分 RSRSstd:
RSRSstd=RSRS−μMσM
其中 μM 为前M日的斜率均值,σM为前M日的标准差。
3、若 RSRSstd大于 Sbuy,则全仓买入;若 RSRSstd小于 Ssell,则卖出平仓。(Sbuy=0.7,Ssell=−0.7)
注:benchmark和标的股票均为沪深300指数,尝试N取自10-30,M取自400-800,发现N=18,M=600时收益率最高。
N,M,Sbuy 的取值范围:18,252,0.6 , 或者:16,300,0.7
该策略从2010-01-01至2017-12-15,开平仓35次,总收益186.67%,年化收益14.58%,胜率0.556,盈亏比4.568,最大回撤20.031%。
# 导入函数库 import statsmodels.api as sm # 初始化函数,设定基准等等 def initialize(context): # 设定上证指数作为基准 set_benchmark('000300.XSHG') # 开启动态复权模式(真实价格) set_option('use_real_price', True) # 输出内容到日志 log.info() log.info('初始函数开始运行且全局只运行一次') # 过滤掉order系列API产生的比error级别低的log # log.set_level('order', 'error') ### 股票相关设定 ### # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱 set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock') ## 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入'000300.XSHG'或'510300.XSHG'是一样的) # 开盘前运行 run_daily(before_market_open, time='before_open', reference_security='000300.XSHG') # 开盘时运行 run_daily(market_open, time='open', reference_security='000300.XSHG') # 收盘后运行 run_daily(after_market_close, time='after_close', reference_security='000300.XSHG') # 设置RSRS指标中N, M的值 g.N = 18 g.M = 600 g.init = True # 要操作的股票:平安银行(g.为全局变量) g.security = '000300.XSHG' # 买入阈值 g.buy = 0.7 g.sell = -0.7 g.ans = [] # 计算2005年1月5日至回测开始日期的RSRS斜率指标 prices = get_price(g.security, '2005-01-05', context.previous_date, '1d', ['high', 'low']) highs = prices.high lows = prices.low for i in range(len(highs))[g.N:]: data_high = highs.iloc[i-g.N+1:i+1] data_low = lows.iloc[i-g.N+1:i+1] X = sm.add_constant(data_low) model = sm.OLS(data_high,X) results = model.fit() # print("params is :",results.params) # print("params.low is:",results.params['low']) g.ans.append(results.params['low']) ## 开盘前运行函数 def before_market_open(context): # 输出运行时间 log.info('函数运行时间(before_market_open):'+str(context.current_dt.time())) ## 开盘时运行函数 def market_open(context): log.info('函数运行时间(market_open):'+str(context.current_dt.time())) security = g.security # 取得当前的现金 cash = context.portfolio.available_cash # 填入各个日期的RSRS斜率值 security = g.security if g.init: g.init = False else: # RSRS斜率指标定义 prices = attribute_history(security, g.N, '1d', ['high', 'low']) highs = prices.high lows = prices.low X = sm.add_constant(lows) model = sm.OLS(highs, X) beta = model.fit().params[1] g.ans.append(beta) # 计算标准化的RSRS指标 # 计算均值序列 section = g.ans[-g.M:] # 计算均值序列 mu = np.mean(section) # 计算标准化RSRS指标序列 sigma = np.std(section) zscore = (section[-1]-mu)/sigma # 如果上一时间点的RSRS斜率大于买入阈值, 则全仓买入 if zscore > g.buy: # 记录这次买入 log.info("标准化RSRS斜率大于买入阈值, 买入 %s" % (security)) # 用所有 cash 买入股票 order_value(security, cash) # 如果上一时间点的RSRS斜率小于卖出阈值, 则空仓卖出 elif zscore < g.sell and context.portfolio.positions[security].closeable_amount > 0: # 记录这次卖出 log.info("标准化RSRS斜率小于卖出阈值, 卖出 %s" % (security)) # 卖出所有股票,使这只股票的最终持有量为0 order_target(security, 0) ## 收盘后运行函数 def after_market_close(context): log.info(str('函数运行时间(after_market_close):'+str(context.current_dt.time()))) #得到当天所有成交记录 trades = get_trades() for _trade in trades.values(): log.info('成交记录:'+str(_trade)) log.info('一天结束') log.info('##############################################################')