一個短線日內交易策略 ——R-Breaker

R-Breaker是一種短線日內交易策略,該策略已經在市場上存活了二十年之久,尤其當指數波動較大時,該策略表現越好,根據S&P至2011年底的統計,R-Break也多次名列前十,由於進入榜單的交易系統業績並不穩定,尤其是一年業績榜單,時常會發生變化,因此模型的穩定性和一致性其實比短期排名更加關鍵,雜誌給出了長期來看一致性最好的十大交易模型,其中就包括 R-Breaker 等模型,它們的業績不一定總是能排進前十名的榜單,但長期以來具有較高的一致性。

策略邏輯:日內突破與反轉會獲得盈利

策略內容:根據前一個交易日的收盤價、最高價和最低價數據通過一定方式計算出六個價位,從大到小依次爲:突破買入價、觀察賣出價、反轉賣出價、反轉買入、觀察買入價、突破賣出價。以此來形成當前交易日盤中交易的觸發條件。追蹤盤中價格走勢,實時判斷觸發條件。具體條件如下:突破:在空倉條件下,如果盤中價格超過突破買入價,則採取趨勢策略,即在該點位開倉做多。在空倉條件下,如果盤中價格跌破突破賣出價,則採取趨勢策略,即在該點位開倉做空。反轉:持多單,當日內最高價超過觀察賣出價後,盤中價格出現回落,且進一步跌破反轉賣出價構成的支撐線時,採取反轉策略,即在該點位反手做空。持空單,當日內最低價低於觀察買入價後,盤中價格出現反彈,且進一步超過反轉買入價構成的阻力線時,採取反轉策略,即在該點位反手做多。設定止損條件。當虧損達到設定值後,平倉。

資金管理:一次買入一手

風險控制:

源代碼

# coding=utf-8
from __future__ import print_function, absolute_import
import pandas as pd
from gm.api import *
from datetime import datetime
"""
R-Breaker是一種短線日內交易策略
根據前一個交易日的收盤價、最高價和最低價數據通過一定方式計算出六個價位,從大到小依次爲:
突破買入價、觀察賣出價、反轉賣出價、反轉買入、觀察買入價、突破賣出價。以此來形成當前交易
日盤中交易的觸發條件。
追蹤盤中價格走勢,實時判斷觸發條件。具體條件如下:
突破
在空倉條件下,如果盤中價格超過突破買入價,則採取趨勢策略,即在該點位開倉做多。
在空倉條件下,如果盤中價格跌破突破賣出價,則採取趨勢策略,即在該點位開倉做空。
反轉
持多單,當日內最高價超過觀察賣出價後,盤中價格出現回落,且進一步跌破反轉賣出價構成的支撐線時,採取反轉策略,即在該點位反手做空。
持空單,當日內最低價低於觀察買入價後,盤中價格出現反彈,且進一步超過反轉買入價構成的阻力線時,採取反轉策略,即在該點位反手做多。
設定止損條件。當虧損達到設定值後,平倉。
選用了SHFE的rb2010 在2019-10-1 15:00:00 到 2020-04-16 15:00:00 進行回測。
注意: 
1:爲回測方便,本策略使用了on_bar的一分鐘來計算,實盤中可能需要使用on_tick。
2:實盤中,如果在收盤的那一根bar或tick觸發交易信號,需要自行處理,實盤可能不會成交。
3:本策略使用在15點收盤時全平的方式來處理不持有隔夜單的情況,實際使用中15點是無法平倉的。
"""
# 策略中必須有init方法
def init(context):
    # 設置交易品種
    context.symbol = 'SHFE.rb'
    # 設置止損點數
    context.stopLossPrice = 50
    # 獲取當時的主力合約
    startDate = datetime.strptime(context.backtest_start_time, '%Y-%m-%d %H:%M:%S').date()
    continuous_contract = get_continuous_contracts(context.symbol, startDate, startDate)
    context.mainContract = continuous_contract[0]['symbol']
    # 訂閱行情
    subscribe(continuous_contract[0]['symbol'], frequency='60s', count=1)
    schedule(schedule_func=algo, date_rule='1d', time_rule='8:50:00')
def algo(context):
    # 檢查主力和約,發生變化則更換訂閱
    contractInfo = get_continuous_contracts(context.symbol, context.now.date(), context.now.date())
    if context.mainContract != contractInfo[0]['symbol']:
        context.mainContract = contractInfo[0]['symbol']
        subscribe(context.mainContract, frequency='60s', count=1, unsubscribe_previous=True)
        return  # 這一根bar不判斷。
    # 獲取歷史數據
    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
    # 獲取現有持倉 返回的是一個list的各種合約的持倉對象 詳見
    # https://www.myquant.cn/docs/python/python_object_trade#Position%20-%20%E6%8C%81%E4%BB%93%E5%AF%B9%E8%B1%A1
    position_long = context.account().position(symbol=context.symbol, side=PositionSide_Long)
    position_short = context.account().position(symbol=context.symbol, side=PositionSide_Short)
    # 突破:
    if not position_long and not position_short:  # 空倉條件
        if bars[0].close > bBreak:
            # 在空倉的情況下,如果盤中價格超過突破買入價,
            # 則採取趨勢策略,即在該點位開倉做多
            print(context.now)
            print("空倉,盤中價格超過突破買入價: 開倉做多")
            order_volume(symbol=context.mainContract, volume=1, side=OrderSide_Buy,
                         order_type=OrderType_Market, position_effect=PositionEffect_Open)  # 做多
            context.open_position_price = bars[0].close
        elif bars[0].close < sBreak:
            # 在空倉的情況下,如果盤中價格跌破突破賣出價,
            # 則採取趨勢策略,即在該點位開倉做空
            print(context.now)
            print("空倉,盤中價格跌破突破賣出價: 開倉做空")
            order_volume(symbol=context.mainContract, volume=1, side=OrderSide_Sell,
                         order_type=OrderType_Market, position_effect=PositionEffect_Open)  # 做空
            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(context.now)
            print('止損')
            order_close_all()  # 平倉
        # 反轉:
        if position_long:  # 多頭持倉
            if  data.high.iloc[1] > sSetup and bars[0].close < sEnter:
                # 多頭持倉,當日內最高價超過觀察賣出價後,
                # 盤中價格出現回落,且進一步跌破反轉賣出價構成的支撐線時,
                # 採取反轉策略,即在該點位反手做空
                print(context.now)
                print("多頭持倉,當日內最高價超過觀察賣出價後跌破反轉賣出價: 反手做空")
                order_close_all()  # 平倉
                order_volume(symbol=context.mainContract, volume=1, side=OrderSide_Sell,
                             order_type=OrderType_Market, position_effect=PositionEffect_Open)  # 做空
                context.open_position_price = bars[0].close
        elif position_short:  # 空頭持倉
            if data.low.iloc[1] < bSetup and bars[0].close > bEnter:
                # 空頭持倉,當日內最低價低於觀察買入價後,
                # 盤中價格出現反彈,且進一步超過反轉買入價構成的阻力線時,
                # 採取反轉策略,即在該點位反手做多
                print(context.now)
                print("空頭持倉,當日最低價低於觀察買入價後超過反轉買入價: 反手做多")
                order_close_all()  # 平倉
                order_volume(symbol=context.mainContract, volume=1, side=OrderSide_Buy,
                             order_type=OrderType_Market, position_effect=PositionEffect_Open)  # 做多
                context.open_position_price = bars[0].close
    # 15點收盤全部平倉。
    if context.now.hour == 15:
        print(context.now)
        print('close all')
        order_close_all()
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')

最終回測結果:

聲明:本文觀點僅供交流與探討,不構成任何投資建議,否則後果自負!!!1 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章