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