R Breaker
1. 原理
1.1 原理
R Breaker是一种日内回转交易策略,属于短线交易。日内回转交易是指当天买入或卖出标的后于当日再卖出或买入标的。日内回转交易通过标的短期波动盈利,低买高卖,时间短、投机性强,适合短线投资者。
R Breaker主要分为分为反转和趋势两部分。空仓时进行趋势跟随,持仓时等待反转信号反向开仓。
由于我国A股采用的是“T+1”交易制度,为了方便起见,以期货为例演示R Breaker策略。
反转和趋势突破的价位点根据前一交易日的收盘价、最高价和最低价数据计算得出,分别为:突破买入价、观察卖出价、反转卖出价、反转买入价、观察买入价和突破卖出价。计算方法如下:
| 指标计算方法 |
|---|
| 中心价位P = (H + C + L)/3 |
| 突破买入价 = H + 2P -2L |
| 观察卖出价 = P + H - L |
| 反转卖出价 = 2P - L |
| 反转买入价 = 2P - H |
| 观察买入价 = P - (H - L) |
| 突破卖出价 = L - 2(H - P) |
1.2 触发条件
空仓时:突破策略
空仓时,当盘中价格>突破买入价,则认为上涨的趋势还会继续,开仓做多;
空仓时,当盘中价格<突破卖出价,则认为下跌的趋势还会继续,开仓做空。
持仓时:反转策略
持多单时:当日内最高价>观察卖出价后,盘中价格回落,跌破反转卖出价构成的支撑线时,采取反转策略,即做空;
持空单时:当日内最低价<观察买入价后,盘中价格反弹,超过反转买入价构成的阻力线时,采取反转策略,即做多。
如下图所示:
1.3 背后逻辑解析
首先看一下这6个价格与前一日价格之间的关系。
反转卖出价和反转买入价
根据公式推导,发现这两个价格和前一日最高最低价没有确定的大小关系。观察卖出价和观察买入价。
用观察卖出价 - 前一交易日最高价发现,(H+P-L)-H = P - L >0,说明观察卖出价>前一交易日最高价;同理可证,观察买入价<前一交易日最低价。突破买入价和突破卖出价
突破买入价>观察卖出价>前一交易日最高价,可以说明突破买入价>>前一交易日最高价。做差后可以发现,突破买入价 - 前一交易日最高价 = 2[(C-L)+(H-L)]/3。
用K线形态表示:
前一交易日K线越长,上影线越长,突破卖入价越高。
这样一来就可以解释R Breaker背后的逻辑了。
当今日的价格突破前一交易日的最高点,形态上来看会是上涨趋势,具备一定的开多仓条件,但还不够。若前一交易日的下影线越长,说明多空方博弈激烈,多方力量强大。因此可以设置更高的突破买入价,一旦突破说明多方力量稳稳地占据了上风,那么就有理由相信未来会继续上涨。同理可解释突破卖出价背后的逻辑。
持有多仓时,若标的价格持续走高,则在当天收盘之前平仓获利离场。若价格不升反降,跌破观察卖出价时,此时价格仍处于前一交易日最高价之上,继续观望。若继续下跌,直到跌破反转卖出价时,平仓止损。
持有空仓时,若标的价格持续走低,则在当天收盘之前平仓获利离场。若价格不降反升,升至观察买入价时,此时价格仍处于前一交易日最低价之下,继续观望。若继续上涨,直到升至反转买入价时,平仓止损。
2、策略逻辑
第一步:根据收盘价、最高价和最低价数据计算六个价位。
第二步:如果是空仓条件下,如果价格超过突破买入价,则开多仓;如果价格跌破突破卖出价,则开空仓。
第三步:在持仓条件下:
持空单时,当最低价低于观察买入价,盘中价格进一步超过反转买入价,反手做空。
第四步:接近收盘时,全部平仓。
回测标的:SHFE.rb2010
回测期:2019-10-1 15:00:00 到 2020-04-16 15:00:00
回测初始资金:100万
注意:若修改回测期,需要修改对应的回测标的。
3、策略代码
# coding=utf-8from __future__ import print_function, absolute_importimport pandas as pdfrom gm.api import *from datetime import datetime, timedelta"""R-Breaker是一种短线日内交易策略根据前一个交易日的收盘价、最高价和最低价数据通过一定方式计算出六个价位,从大到小依次为:突破买入价、观察卖出价、反转卖出价、反转买入、观察买入价、突破卖出价。以此来形成当前交易日盘中交易的触发条件。追踪盘中价格走势,实时判断触发条件。具体条件如下:突破在空仓条件下,如果盘中价格超过突破买入价,则采取趋势策略,即在该点位开仓做多。在空仓条件下,如果盘中价格跌破突破卖出价,则采取趋势策略,即在该点位开仓做空。反转持多单,当日内最高价超过观察卖出价后,盘中价格出现回落,且进一步跌破反转卖出价构成的支撑线时,采取反转策略,即在该点位反手做空。持空单,当日内最低价低于观察买入价后,盘中价格出现反弹,且进一步超过反转买入价构成的阻力线时,采取反转策略,即在该点位反手做多。设定止损条件。当亏损达到设定值后,平仓。注意:1:为回测方便,本策略使用了on_bar的一分钟来计算,实盘中可能需要使用on_tick。2:实盘中,如果在收盘的那一根bar或tick触发交易信号,需要自行处理,实盘可能不会成交。3:本策略使用在15点收盘时全平的方式来处理不持有隔夜单的情况,实际使用中15点是无法平仓的。"""def init(context):# 设置交易品种context.symbol = 'SHFE.ag'# 设置止损点数context.stopLossPrice = 50# 获取前一交易日的主力合约startDate = get_previous_trading_date(exchange='SHFE', date=context.now.date())continuous_contract = get_continuous_contracts(context.symbol, startDate, startDate)context.mainContract = continuous_contract[0]['symbol']# 获取当前时间time = context.now.strftime('%H:%M:%S')# 如果当前时间是非交易时间段,则直接执行algo,以防直接进入on_bar()导致context.bBreak等未定义if '09:00:00' < time < '15:00:00' or '21:00:00' < time < '23:00:00':algo(context)# 如果是交易时间段,等到开盘时间确保进入algo()schedule(schedule_func = algo, date_rule = '1d', time_rule = '09:00:00')schedule(schedule_func = algo, date_rule = '1d', time_rule = '21:00:00')# 订阅行情subscribe(continuous_contract[0]['symbol'], frequency='60s', count=1)def algo(context):# 检查主力和约,发生变化则更换订阅# 由于主力合约在盘后才公布,为了防止未来函数,选择上一交易日的主力合约。startDate = get_previous_trading_date(exchange='SHFE', date=context.now.date())contractInfo = get_continuous_contracts(context.symbol, startDate, startDate)if context.mainContract != contractInfo[0]['symbol']:context.mainContract = contractInfo[0]['symbol']subscribe(context.mainContract, frequency='60s', count=1, unsubscribe_previous=True)# 获取历史数据data = history_n(symbol=context.mainContract, frequency='1d',end_time=context.now, fields='high,low,open,symbol,close', count=2, df=True)high = data['high'].iloc[0] # 前一日的最高价low = data['low'].iloc[0] # 前一日的最低价close = data['close'].iloc[0] # 前一日的收盘价pivot = (high + low + close) / 3 # 枢轴点context.bBreak = high + 2 * (pivot - low) # 突破买入价context.sSetup = pivot + (high - low) # 观察卖出价context.sEnter = 2 * pivot - low # 反转卖出价context.bEnter = 2 * pivot - high # 反转买入价context.bSetup = pivot - (high - low) # 观察买入价context.sBreak = low - 2 * (high - pivot) # 突破卖出价context.data = datadef on_bar(context, bars):# 获取止损价STOP_LOSS_PRICE = context.stopLossPrice# 设置参数bBreak = context.bBreaksSetup = context.sSetupsEnter = context.sEnterbEnter = context.bEnterbSetup = context.bSetupsBreak = context.sBreakdata = context.data# 获取现有持仓position_long = context.account().position(symbol=context.mainContract, side=PositionSide_Long)position_short = context.account().position(symbol=context.mainContract, side=PositionSide_Short)# 突破策略:if not position_long and not position_short: # 空仓条件下if bars[0].close > bBreak:# 在空仓的情况下,如果盘中价格超过突破买入价,则采取趋势策略,即在该点位开仓做多order_volume(symbol=context.mainContract, volume=10, side=OrderSide_Buy,order_type=OrderType_Market, position_effect=PositionEffect_Open) # 做多print("空仓,盘中价格超过突破买入价: 开仓做多")context.open_position_price = bars[0].closeelif bars[0].close < sBreak:# 在空仓的情况下,如果盘中价格跌破突破卖出价,则采取趋势策略,即在该点位开仓做空order_volume(symbol=context.mainContract, volume=10, side=OrderSide_Sell,order_type=OrderType_Market, position_effect=PositionEffect_Open) # 做空print("空仓,盘中价格跌破突破卖出价: 开仓做空")context.open_position_price = bars[0].close# 设置止损条件else: # 有持仓时# 开仓价与当前行情价之差大于止损点则止损if (position_long and context.open_position_price - bars[0].close >= STOP_LOSS_PRICE) or \(position_short and bars[0].close - context.open_position_price >= STOP_LOSS_PRICE):print('达到止损点,全部平仓')order_close_all() # 平仓# 反转策略:if position_long: # 多仓条件下if data.high.iloc[1] > sSetup and bars[0].close < sEnter:# 多头持仓,当日内最高价超过观察卖出价后,# 盘中价格出现回落,且进一步跌破反转卖出价构成的支撑线时,# 采取反转策略,即在该点位反手做空order_close_all() # 平仓order_volume(symbol=context.mainContract, volume=10, side=OrderSide_Sell,order_type=OrderType_Market, position_effect=PositionEffect_Open) # 做空print("多头持仓,当日内最高价超过观察卖出价后跌破反转卖出价: 反手做空")context.open_position_price = bars[0].closeelif position_short: # 空头持仓if data.low.iloc[1] < bSetup and bars[0].close > bEnter:# 空头持仓,当日内最低价低于观察买入价后,# 盘中价格出现反弹,且进一步超过反转买入价构成的阻力线时,# 采取反转策略,即在该点位反手做多order_close_all() # 平仓order_volume(symbol=context.mainContract, volume=10, side=OrderSide_Buy,order_type=OrderType_Market, position_effect=PositionEffect_Open) # 做多print("空头持仓,当日最低价低于观察买入价后超过反转买入价: 反手做多")context.open_position_price = bars[0].closeif context.now.hour == 14 and context.now.minute == 59:order_close_all()print('全部平仓')if __name__ == '__main__':run(strategy_id='strategy_id',filename='main.py',mode=MODE_BACKTEST,token='token_id',backtest_start_time='2019-10-1 15:00:00',backtest_end_time='2020-04-16 15:00:00',backtest_initial_cash=1000000,backtest_commission_ratio=0.0001,backtest_slippage_ratio=0.0001)
4、回测结果与稳健性分析
设定初始资金100万,手续费率为0.01%,滑点比率为0.01%。回测结果如下图所示:

回测期间累计收益为17.69%,年化收益率为32.44%,基准收益率为-0.92%,整体跑赢指数。最大回撤为6.11%,胜率为45.00%。
改变回测期间,观察回测结果如下表所示。
| 标的 | 回测期 | 年化收益率 | 最大回撤 |
|---|---|---|---|
| SHFE.ag2010 | 2019.10.01-2020.04.16 | 32.44% | 6.11% |
| SHFE.rb2010 | 2019.10.01-2020.04.16 | 0.08% | 1.07% |
| SHFE.sn2010 | 2019.10.01-2020.04.16 | 19.59% | 2.39% |
| SHFE.cu2010 | 2019.10.01-2020.04.16 | 31.91% | 4.80% |
| SHFE.ni2010 | 2019.10.01-2020.04.16 | -1.98% | 6.81% |
由上表可看出,除了ni2010合约以外,其他几个合约均能保持正收益率,尤其是ag2010合约和cu2010合约,年化收益率达到30%以上,最大回撤却只有10%以内,远远跑赢大盘指数。
注:此策略只用于学习、交流、演示,不构成任何投资建议。