PDF下载 下载

R-Breaker(期货)

阅读 13398

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线越长,下影线越长,突破买入价越高。
前一交易日K线越长,上影线越长,突破卖入价越高。

这样一来就可以解释R Breaker背后的逻辑了。

当今日的价格突破前一交易日的最高点,形态上来看会是上涨趋势,具备一定的开多仓条件,但还不够。若前一交易日的下影线越长,说明多空方博弈激烈,多方力量强大。因此可以设置更高的突破买入价,一旦突破说明多方力量稳稳地占据了上风,那么就有理由相信未来会继续上涨。同理可解释突破卖出价背后的逻辑。

持有多仓时,若标的价格持续走高,则在当天收盘之前平仓获利离场。若价格不升反降,跌破观察卖出价时,此时价格仍处于前一交易日最高价之上,继续观望。若继续下跌,直到跌破反转卖出价时,平仓止损。

持有空仓时,若标的价格持续走低,则在当天收盘之前平仓获利离场。若价格不降反升,升至观察买入价时,此时价格仍处于前一交易日最低价之下,继续观望。若继续上涨,直到升至反转买入价时,平仓止损。

2、策略逻辑

第一步:根据收盘价、最高价和最低价数据计算六个价位。
第二步:如果是空仓条件下,如果价格超过突破买入价,则开多仓;如果价格跌破突破卖出价,则开空仓。
第三步:在持仓条件下:

持多单时,当最高价超过观察卖出价,盘中价格进一步跌破反转卖出价,反手做多;
持空单时,当最低价低于观察买入价,盘中价格进一步超过反转买入价,反手做空。

第四步:接近收盘时,全部平仓。

回测标的:SHFE.rb2010
回测期:2019-10-1 15:00:00 到 2020-04-16 15:00:00
回测初始资金:100万
注意:若修改回测期,需要修改对应的回测标的。

3、策略代码

  1. # coding=utf-8
  2. from __future__ import print_function, absolute_import
  3. import pandas as pd
  4. from gm.api import *
  5. from datetime import datetime, timedelta
  6. """
  7. R-Breaker是一种短线日内交易策略
  8. 根据前一个交易日的收盘价、最高价和最低价数据通过一定方式计算出六个价位,从大到小依次为:
  9. 突破买入价、观察卖出价、反转卖出价、反转买入、观察买入价、突破卖出价。以此来形成当前交易
  10. 日盘中交易的触发条件。
  11. 追踪盘中价格走势,实时判断触发条件。具体条件如下:
  12. 突破
  13. 在空仓条件下,如果盘中价格超过突破买入价,则采取趋势策略,即在该点位开仓做多。
  14. 在空仓条件下,如果盘中价格跌破突破卖出价,则采取趋势策略,即在该点位开仓做空。
  15. 反转
  16. 持多单,当日内最高价超过观察卖出价后,盘中价格出现回落,且进一步跌破反转卖出价构成的支撑线时,采取反转策略,即在该点位反手做空。
  17. 持空单,当日内最低价低于观察买入价后,盘中价格出现反弹,且进一步超过反转买入价构成的阻力线时,采取反转策略,即在该点位反手做多。
  18. 设定止损条件。当亏损达到设定值后,平仓。
  19. 注意:
  20. 1:为回测方便,本策略使用了on_bar的一分钟来计算,实盘中可能需要使用on_tick。
  21. 2:实盘中,如果在收盘的那一根bar或tick触发交易信号,需要自行处理,实盘可能不会成交。
  22. 3:本策略使用在15点收盘时全平的方式来处理不持有隔夜单的情况,实际使用中15点是无法平仓的。
  23. """
  24. def init(context):
  25. # 设置交易品种
  26. context.symbol = 'SHFE.ag'
  27. # 设置止损点数
  28. context.stopLossPrice = 50
  29. # 获取前一交易日的主力合约
  30. startDate = get_previous_trading_date(exchange='SHFE', date=context.now.date())
  31. continuous_contract = get_continuous_contracts(context.symbol, startDate, startDate)
  32. context.mainContract = continuous_contract[0]['symbol']
  33. # 获取当前时间
  34. time = context.now.strftime('%H:%M:%S')
  35. # 如果当前时间是非交易时间段,则直接执行algo,以防直接进入on_bar()导致context.bBreak等未定义
  36. if '09:00:00' < time < '15:00:00' or '21:00:00' < time < '23:00:00':
  37. algo(context)
  38. # 如果是交易时间段,等到开盘时间确保进入algo()
  39. schedule(schedule_func = algo, date_rule = '1d', time_rule = '09:00:00')
  40. schedule(schedule_func = algo, date_rule = '1d', time_rule = '21:00:00')
  41. # 订阅行情
  42. subscribe(continuous_contract[0]['symbol'], frequency='60s', count=1)
  43. def algo(context):
  44. # 检查主力和约,发生变化则更换订阅
  45. # 由于主力合约在盘后才公布,为了防止未来函数,选择上一交易日的主力合约。
  46. startDate = get_previous_trading_date(exchange='SHFE', date=context.now.date())
  47. contractInfo = get_continuous_contracts(context.symbol, startDate, startDate)
  48. if context.mainContract != contractInfo[0]['symbol']:
  49. context.mainContract = contractInfo[0]['symbol']
  50. subscribe(context.mainContract, frequency='60s', count=1, unsubscribe_previous=True)
  51. # 获取历史数据
  52. data = history_n(symbol=context.mainContract, frequency='1d',
  53. end_time=context.now, fields='high,low,open,symbol,close', count=2, df=True)
  54. high = data['high'].iloc[0] # 前一日的最高价
  55. low = data['low'].iloc[0] # 前一日的最低价
  56. close = data['close'].iloc[0] # 前一日的收盘价
  57. pivot = (high + low + close) / 3 # 枢轴点
  58. context.bBreak = high + 2 * (pivot - low) # 突破买入价
  59. context.sSetup = pivot + (high - low) # 观察卖出价
  60. context.sEnter = 2 * pivot - low # 反转卖出价
  61. context.bEnter = 2 * pivot - high # 反转买入价
  62. context.bSetup = pivot - (high - low) # 观察买入价
  63. context.sBreak = low - 2 * (high - pivot) # 突破卖出价
  64. context.data = data
  65. def on_bar(context, bars):
  66. # 获取止损价
  67. STOP_LOSS_PRICE = context.stopLossPrice
  68. # 设置参数
  69. bBreak = context.bBreak
  70. sSetup = context.sSetup
  71. sEnter = context.sEnter
  72. bEnter = context.bEnter
  73. bSetup = context.bSetup
  74. sBreak = context.sBreak
  75. data = context.data
  76. # 获取现有持仓
  77. position_long = context.account().position(symbol=context.mainContract, side=PositionSide_Long)
  78. position_short = context.account().position(symbol=context.mainContract, side=PositionSide_Short)
  79. # 突破策略:
  80. if not position_long and not position_short: # 空仓条件下
  81. if bars[0].close > bBreak:
  82. # 在空仓的情况下,如果盘中价格超过突破买入价,则采取趋势策略,即在该点位开仓做多
  83. order_volume(symbol=context.mainContract, volume=10, side=OrderSide_Buy,
  84. order_type=OrderType_Market, position_effect=PositionEffect_Open) # 做多
  85. print("空仓,盘中价格超过突破买入价: 开仓做多")
  86. context.open_position_price = bars[0].close
  87. elif bars[0].close < sBreak:
  88. # 在空仓的情况下,如果盘中价格跌破突破卖出价,则采取趋势策略,即在该点位开仓做空
  89. order_volume(symbol=context.mainContract, volume=10, side=OrderSide_Sell,
  90. order_type=OrderType_Market, position_effect=PositionEffect_Open) # 做空
  91. print("空仓,盘中价格跌破突破卖出价: 开仓做空")
  92. context.open_position_price = bars[0].close
  93. # 设置止损条件
  94. else: # 有持仓时
  95. # 开仓价与当前行情价之差大于止损点则止损
  96. if (position_long and context.open_position_price - bars[0].close >= STOP_LOSS_PRICE) or \
  97. (position_short and bars[0].close - context.open_position_price >= STOP_LOSS_PRICE):
  98. print('达到止损点,全部平仓')
  99. order_close_all() # 平仓
  100. # 反转策略:
  101. if position_long: # 多仓条件下
  102. if data.high.iloc[1] > sSetup and bars[0].close < sEnter:
  103. # 多头持仓,当日内最高价超过观察卖出价后,
  104. # 盘中价格出现回落,且进一步跌破反转卖出价构成的支撑线时,
  105. # 采取反转策略,即在该点位反手做空
  106. order_close_all() # 平仓
  107. order_volume(symbol=context.mainContract, volume=10, side=OrderSide_Sell,
  108. order_type=OrderType_Market, position_effect=PositionEffect_Open) # 做空
  109. print("多头持仓,当日内最高价超过观察卖出价后跌破反转卖出价: 反手做空")
  110. context.open_position_price = bars[0].close
  111. elif position_short: # 空头持仓
  112. if data.low.iloc[1] < bSetup and bars[0].close > bEnter:
  113. # 空头持仓,当日内最低价低于观察买入价后,
  114. # 盘中价格出现反弹,且进一步超过反转买入价构成的阻力线时,
  115. # 采取反转策略,即在该点位反手做多
  116. order_close_all() # 平仓
  117. order_volume(symbol=context.mainContract, volume=10, side=OrderSide_Buy,
  118. order_type=OrderType_Market, position_effect=PositionEffect_Open) # 做多
  119. print("空头持仓,当日最低价低于观察买入价后超过反转买入价: 反手做多")
  120. context.open_position_price = bars[0].close
  121. if context.now.hour == 14 and context.now.minute == 59:
  122. order_close_all()
  123. print('全部平仓')
  124. if __name__ == '__main__':
  125. run(strategy_id='strategy_id',
  126. filename='main.py',
  127. mode=MODE_BACKTEST,
  128. token='token_id',
  129. backtest_start_time='2019-10-1 15:00:00',
  130. backtest_end_time='2020-04-16 15:00:00',
  131. backtest_initial_cash=1000000,
  132. backtest_commission_ratio=0.0001,
  133. 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%以内,远远跑赢大盘指数。

注:此策略只用于学习、交流、演示,不构成任何投资建议。

0 篇笔记