R-Breaker策略(难度:初级)

Table of Contents

策略简介

R-Breaker是一种短线日内交易策略,该策略已经在市场上存活了二十年之久,尤其当指数波动较大时,该策略表现越好,根据S&P至2011年底的统计,R-Break也多次名列前十,由于进入榜单的交易系统业绩并不稳定,尤其是一年业绩榜单,时常会发生变化,因此模型的稳定性和一致性其实比短期排名更加关键,杂志给出了长期来看一致性最好的十大交易模型,其中就包括 R-Breaker 等模型,它们的业绩不一定总是能排进前十名的榜单,但长期以来具有较高的一致性。

前十大S&P 交易系统排名
排名交易系统名称 年收益率 %
1 FT Classic 107.30%
2 TSL_SP_1.0Z 76.90%
3 TSL_CEL_SP1 74.50%
4 Keystone 54.10%
5 Impetus SP 50.50%
6 Big Blue 2 49.60%
7 Strategic 500 45.50%
8 STC SP Daytrader 42.00%
9 R-Breaker 37.10%
10 %C Daybreaker 36.30%

资料来源:https://blog.csdn.net/The_Time_Runner/article/details/88762963

策略的基本原理

  1. 根据前一个交易日的收盘价、最高价和最低价数据通过一定方式计算出六个价位,从大到小依次为:突破买入价、观察卖出价、反转卖出价、反转买入、观察买入价、突破卖出价。以此来形成当前交易日盘中交易的触发条件。(策略源码在文章最后)

    def get_index_line(klines):
        '''计算指标线'''
        high = klines.high.iloc[-2]  # 前一日的最高价
        low = klines.low.iloc[-2]  # 前一日的最低价
        close = klines.close.iloc[-2]  # 前一日的收盘价
        pivot = (high + low + close) / 3  # 枢轴点
        bBreak = high + 2 * (pivot - low)  # 突破买入价
        sSetup = pivot + (high - low)  # 观察卖出价
        sEnter = 2 * pivot - low  # 反转卖出价
        bEnter = 2 * pivot - high  # 反转买入价
        bSetup = pivot - (high - low)  # 观察买入价
        sBreak = low - 2 * (high - pivot)  # 突破卖出价
        print("已计算新标志线, 枢轴点: %f, 突破买入价: %f, 观察卖出价: %f, 反转卖出价: %f, 反转买入价: %f, 观察买入价: %f, 突破卖出价: %f"
                    % (pivot, bBreak, sSetup, sEnter, bEnter, bSetup, sBreak))
        return pivot, bBreak, sSetup, sEnter, bEnter, bSetup, sBreak
  2. 追踪盘中价格走势,实时判断触发条件。具体条件如下:
    1. 突破
      • 在空仓条件下,如果盘中价格超过突破买入价,则采取趋势策略,即在该点位开仓做多。
      • 在空仓条件下,如果盘中价格跌破突破卖出价,则采取趋势策略,即在该点位开仓做空。
    2. 反转
      • 持多单,当日内最高价超过观察卖出价后,盘中价格出现回落,且进一步跌破反转卖出价构成的支撑线时,采取反转策略,即在该点位反手做空。
      • 持空单,当日内最低价低于观察买入价后,盘中价格出现反弹,且进一步超过反转买入价构成的阻力线时,采取反转策略,即在该点位反手做多。

  3. 设定止损条件。当亏损达到设定值后,平仓。
  4. 设定是否隔夜留仓。

代码实现逻辑

实现步骤

只要新产生一条日线,即可判断为新交易日的开始,则重新计算七条指标线;

if api.is_changing(klines.iloc[-1], "datetime"):  # 产生新k线,则重新计算7条指标线
        pivot, bBreak, sSetup, sEnter, bEnter, bSetup, sBreak = get_index_line(klines)

根据策略的交易规则,依据当前的持仓信息以及行情最新价突破信息进行加减仓操作;

如果设置了非隔夜留仓,在策略进行过程中判断当前时间是否临近交易日结束,即当前行情时间已到达设定的平仓时间,若是则平仓;

if api.is_changing(quote, "datetime"):
        now = datetime.strptime(quote.datetime, "%Y-%m-%d %H:%M:%S.%f")
        if now.hour == CLOSE_HOUR and now.minute >= CLOSE_MINUTE:  # 到达平仓时间: 平仓
            print("临近本交易日收盘: 平仓")
            target_pos_value = 0  # 平仓
            pivot = bBreak = sSetup = sEnter = bEnter = bSetup = sBreak = float("nan")  # 修改各指标线的值, 避免平仓后再次触发

设置止损点,每次调仓后记录调仓时的行情价,当调仓价与当前行情价之差大于止损点则平仓止损。

STOP_LOSS_PRICE = 10  # 止损点(价格)
target_pos_value = position.pos_long - position.pos_short  # 净目标净持仓数
open_position_price = position.open_price_long if target_pos_value > 0 else position.open_price_short  # 开仓价

# 开仓价与当前行情价之差大于止损点则止损
if (target_pos_value > 0 and open_position_price - quote.last_price >= STOP_LOSS_PRICE) or (target_pos_value < 0 and quote.last_price - open_position_price >= STOP_LOSS_PRICE):
    target_pos_value = 0  # 平仓

策略代码实现工具

免费期货模拟、实盘天勤量化软件:https://www.shinnytech.com/tianqin/

回测

回测初始设置

初始账户资金:100万

回测日期:2018.11.14 —— 2018.12.25

策略参数:平仓时间:14:50 ;止损点:35

多、空头开仓手数:20手

合约:INE.sc1905

是否隔夜留仓:隔夜不留仓: 在每日收盘前,对所持合约进行平仓

回测时盘口行情quote的更新频率:和K线分钟线的更新频率一致

回测结果

R-Breaker策略回测结果
合约代码 合约品种 收益率 风险度 最大回撤 年化夏普率
INE.sc1905 原油 37.32% 0.00% 2.78% 6.1229

上表回测结果中累计收益走势图

天勤内策略源码:

非隔夜留仓(收盘前平仓):

# !/usr/bin/env python
#  -*- coding: utf-8 -*-
__author__ = 'limin'

'''
R-Breaker策略(非隔夜留仓: 在每日收盘前,对所持合约进行平仓)
参考: https://www.shinnytech.com/blog/r-breaker
注: 该示例策略仅用于功能示范, 实盘时请根据自己的策略/经验进行修改
'''

from datetime import datetime
from tqsdk import TqApi, TargetPosTask

SYMBOL = "SHFE.au1912"  # 合约代码
CLOSE_HOUR, CLOSE_MINUTE = 14, 50  # 平仓时间
STOP_LOSS_PRICE = 10  # 止损点(价格)

api = TqApi()
print("策略开始运行")


def get_index_line(klines):
    '''计算指标线'''
    high = klines.high.iloc[-2]  # 前一日的最高价
    low = klines.low.iloc[-2]  # 前一日的最低价
    close = klines.close.iloc[-2]  # 前一日的收盘价
    pivot = (high + low + close) / 3  # 枢轴点
    bBreak = high + 2 * (pivot - low)  # 突破买入价
    sSetup = pivot + (high - low)  # 观察卖出价
    sEnter = 2 * pivot - low  # 反转卖出价
    bEnter = 2 * pivot - high  # 反转买入价
    bSetup = pivot - (high - low)  # 观察买入价
    sBreak = low - 2 * (high - pivot)  # 突破卖出价
    print("已计算新标志线, 枢轴点: %f, 突破买入价: %f, 观察卖出价: %f, 反转卖出价: %f, 反转买入价: %f, 观察买入价: %f, 突破卖出价: %f"
                % (pivot, bBreak, sSetup, sEnter, bEnter, bSetup, sBreak))
    return pivot, bBreak, sSetup, sEnter, bEnter, bSetup, sBreak


quote = api.get_quote(SYMBOL)
klines = api.get_kline_serial(SYMBOL, 24 * 60 * 60)  # 86400: 使用日线
position = api.get_position(SYMBOL)
target_pos = TargetPosTask(api, SYMBOL)
target_pos_value = position.pos_long - position.pos_short  # 净目标净持仓数
open_position_price = position.open_price_long if target_pos_value > 0 else position.open_price_short  # 开仓价
pivot, bBreak, sSetup, sEnter, bEnter, bSetup, sBreak = get_index_line(klines)  # 七条标准线

while True:
    target_pos.set_target_volume(target_pos_value)
    api.wait_update()
    if api.is_changing(klines.iloc[-1], "datetime"):  # 产生新k线,则重新计算7条指标线
        pivot, bBreak, sSetup, sEnter, bEnter, bSetup, sBreak = get_index_line(klines)

    if api.is_changing(quote, "datetime"):
        now = datetime.strptime(quote.datetime, "%Y-%m-%d %H:%M:%S.%f")
        if now.hour == CLOSE_HOUR and now.minute >= CLOSE_MINUTE:  # 到达平仓时间: 平仓
            print("临近本交易日收盘: 平仓")
            target_pos_value = 0  # 平仓
            pivot = bBreak = sSetup = sEnter = bEnter = bSetup = sBreak = float("nan")  # 修改各指标线的值, 避免平仓后再次触发

    '''交易规则'''
    if api.is_changing(quote, "last_price"):
        print("最新价: %f" % quote.last_price)

        # 开仓价与当前行情价之差大于止损点则止损
        if (target_pos_value > 0 and open_position_price - quote.last_price >= STOP_LOSS_PRICE) or \
                (target_pos_value < 0 and quote.last_price - open_position_price >= STOP_LOSS_PRICE):
            target_pos_value = 0  # 平仓

        # 反转:
        if target_pos_value > 0:  # 多头持仓
            if quote.highest > sSetup and quote.last_price < sEnter:
                # 多头持仓,当日内最高价超过观察卖出价后,
                # 盘中价格出现回落,且进一步跌破反转卖出价构成的支撑线时,
                # 采取反转策略,即在该点位反手做空
                print("多头持仓,当日内最高价超过观察卖出价后跌破反转卖出价: 反手做空")
                target_pos_value = -3  # 做空
                open_position_price = quote.last_price
        elif target_pos_value < 0:  # 空头持仓
            if quote.lowest < bSetup and quote.last_price > bEnter:
                # 空头持仓,当日内最低价低于观察买入价后,
                # 盘中价格出现反弹,且进一步超过反转买入价构成的阻力线时,
                # 采取反转策略,即在该点位反手做多
                print("空头持仓,当日最低价低于观察买入价后超过反转买入价: 反手做多")
                target_pos_value = 3  # 做多
                open_position_price = quote.last_price

        # 突破:
        elif target_pos_value == 0:  # 空仓条件
            if quote.last_price > bBreak:
                # 在空仓的情况下,如果盘中价格超过突破买入价,
                # 则采取趋势策略,即在该点位开仓做多
                print("空仓,盘中价格超过突破买入价: 开仓做多")
                target_pos_value = 3  # 做多
                open_position_price = quote.last_price
            elif quote.last_price < sBreak:
                # 在空仓的情况下,如果盘中价格跌破突破卖出价,
                # 则采取趋势策略,即在该点位开仓做空
                print("空仓,盘中价格跌破突破卖出价: 开仓做空")
                target_pos_value = -3  # 做空
                open_position_price = quote.last_price

点击查看天勤量化程序