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-8
from __future__ import print_function, absolute_import
import pandas as pd
from 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 = data
def on_bar(context, bars):
# 获取止损价
STOP_LOSS_PRICE = context.stopLossPrice
# 设置参数
bBreak = context.bBreak
sSetup = context.sSetup
sEnter = context.sEnter
bEnter = context.bEnter
bSetup = context.bSetup
sBreak = context.sBreak
data = 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].close
elif 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].close
elif 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].close
if 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%以内,远远跑赢大盘指数。
注:此策略只用于学习、交流、演示,不构成任何投资建议。