R-Breaker是一种短线日内交易策略。根据前一个交易日的收盘价(C)、最高价(H)和最低价(L)数据通过一定方式计算出六个价位,从大到小依次为: 突破买入价、观察卖出价、反转卖出价、反转买入、观察买入价、突破卖出价。
中心价位P = (H + C + L)/3
突破买入价 = H + 2P -2L
观察卖出价 = P + H - L
反转卖出价 = 2P - L
反转买入价 = 2P - H
观察买入价 = P - (H - L)
突破卖出价 = L - 2(H - P)
空仓时:突破策略
空仓时,当盘中价格>突破买入价,则认为上涨的趋势还会继续,开仓做多;
空仓时,当盘中价格<突破卖出价,则认为下跌的趋势还会继续,开仓做空。
持仓时:反转策略
持多单时:当日内最高价>观察卖出价后,盘中价格回落,跌破反转卖出价构成的支撑线时,采取反转策略,即做空;
持空单时:当日内最低价<观察买入价后,盘中价格反弹,超过反转买入价构成的阻力线时,采取反转策略,即做多。
from datetime import datetime,timedelta
STRATEGY_NAME = "STRATEGY_1m_rbreak"
def initialize(context):
"""初始化"""
print("initialize")
context.symbol = instruments
context.ins = context.get_conf_param("instruments")#从传入参数中获取需要交易的合约
context.order_num = context.get_conf_param("order_num")#下单手数
context.set_universe(context.ins) #设置需要处理的合约
context.closetime_day = context.get_conf_param("closetime_day")#日内策略白盘平仓时间,一般14:58
context.closetime_night = context.get_conf_param("closetime_night")#日内策略夜盘平仓时间,一般22:58,注意有些商品夜盘收盘时间不一样
def before_trading(context, data):
"""盘前处理"""
context.subscribe(context.ins) #注册合约
context.max_high = 0 #当日最高价
context.max_low = 0 #当日最低价
hist = data.history(context.ins, ["high","low","open","close"], 1, "1d")
high = hist['high'].iloc[0] # 前一日的最高价
low = hist['low'].iloc[0] # 前一日的最低价
close = hist['close'].iloc[0] # 前一日的收盘价
pivot = (high + low + close) / 3 # 枢轴点
price_multi = 2 # 参数
context.bBreak = np.round(high + price_multi * (pivot - low), 2) # 突破买入价
context.sSetup = np.round(pivot + (high - low), 2) # 观察卖出价
context.sEnter = np.round(price_multi * pivot - low, 2) # 反转卖出价
context.bEnter = np.round(price_multi * pivot - high, 2) # 反转买入价
context.bSetup = np.round(pivot - (high - low), 2) # 观察买入价
context.sBreak = np.round(low - price_multi * (high - pivot), 2) # 突破卖出价
cur_date = data.current_dt
print(cur_date, context.bBreak, context.sSetup, context.sEnter,context.bEnter , context.bSetup,context.sBreak)
def handle_data(context, data):
"""Bar行情推送"""
cur_date = data.current_dt
cur_hm = cur_date.strftime('%H:%M')
#获取当日最高价和最低价
today_high = data.current(context.ins,'high')
today_low = data.current(context.ins,'low')
context.max_high = max(context.max_high,today_high)
context.max_low = max(context.max_high,today_low)
# 分别获取多头持仓,和空头持仓
position_long = context.get_position(context.ins, Direction.LONG)
position_short = context.get_position(context.ins, Direction.SHORT)
# 获取当前价格
price = data.current(context.ins, "close")
#部分品种夜盘收盘时间不一样,此时间表示指定的尾盘平仓时间往后偏移30分钟,这段时间内不能开新仓,只能平仓。给30分钟是为了足够的冗余
closetime_nightshift = (datetime.strptime(context.closetime_night,'%H:%M') + timedelta(minutes = 30)).strftime('%H:%M')
#尾盘平仓
if((cur_hm>=context.closetime_day and cur_hm<="15:00") or (cur_hm>=context.closetime_night and cur_hm<=closetime_nightshift)):
if(position_long.current_qty != 0):
rv = context.sell_close(context.ins, position_long.avail_qty, price, order_type=OrderType.MARKET)
msg = "{} 尾盘平多 for {} 最新价={} 下单函数返回={}".format(str(data.current_dt),context.ins,str(price),str(rv))
context.write_log(msg, stdout=1) #输出关键日志
if(position_short.current_qty != 0):
rv = context.buy_close(context.ins, position_short.avail_qty, price, order_type=OrderType.MARKET)
msg = "{} 尾盘平空 for {} 最新价={} 下单函数返回={}".format(str(data.current_dt),context.ins,str(price),str(rv))
context.write_log(msg, stdout=1) #输出关键日志
#尾盘不开新仓,直接返回
return
# 突破策略
if position_long.current_qty == 0 and position_short.current_qty == 0: # 空仓条件下
if price > context.bBreak:
# 在空仓的情况下,如果盘中价格超过突破买入价,则采取趋势策略,即在该点位开仓做多
rv = context.buy_open(context.ins, context.order_num, price, order_type=OrderType.MARKET)
msg = "buybuybuy{} 开多 for {} 最新价={} 下单函数返回={}".format(str(data.current_dt),context.ins,str(price),str(rv))
context.write_log(msg, stdout=1) #输出关键日志
context.open_position_price = price
elif price < context.sBreak:
# 在空仓的情况下,如果盘中价格跌破突破卖出价,则采取趋势策略,即在该点位开仓做空
rv = context.sell_open(context.ins, context.order_num, price, order_type=OrderType.MARKET)
msg = "sellsellsell{} 开空 for {} 最新价={} 下单函数返回={}".format(str(data.current_dt),context.ins,str(price),str(rv))
context.write_log(msg, stdout=1) #输出关键日志
context.open_position_price = price
# 设置止损条件
else:
# 反转策略:
if position_long.current_qty != 0: # 多仓条件下
if context.max_high > context.sSetup and price < context.sEnter:
# 多头持仓,当日内最高价超过观察卖出价后
# 盘中价格出现回落,且进一步跌破反转卖出价构成的支撑线时
# 采取反转策略,即在该点位反手做空
context.write_log('多头持仓,当日内最高价超过观察卖出价后跌破反转卖出价: 反手做空', stdout=1) #输出关键日志
rv = context.sell_close(context.ins, position_long.avail_qty, price, order_type=OrderType.MARKET)
msg = '平===多'*5+"{} 平多 for {} 最新价={} 下单函数返回={}".format(str(data.current_dt),context.ins,str(price),str(rv))
context.write_log(msg, stdout=1) #输出关键日志
rv = context.sell_open(context.ins, context.order_num, price, order_type=OrderType.MARKET)
context.open_position_price = price
msg = '开===空'*5 +"{} 开空 for {} 最新价={} 下单函数返回={}".format(str(data.current_dt),context.ins,str(price),str(rv))
context.write_log(msg, stdout=1) #输出关键日志
elif position_short.current_qty != 0: # 空头持仓
if context.max_low < context.bSetup and price > context.bEnter:
# 空头持仓,当日内最低价低于观察买入价后,
# 盘中价格出现反弹,且进一步超过反转买入价构成的阻力线时,
# 采取反转策略,即在该点位反手做多
context.write_log('空头持仓,当日最低价低于观察买入价后超过反转买入价: 反手做多', stdout=1) #输出关键日志
rv = context.buy_close(context.ins, position_short.avail_qty, price, order_type=OrderType.MARKET)
msg = "{} 平空 for {} 最新价={} 下单函数返回={}".format(str(data.current_dt),context.ins,str(price),str(rv))
context.write_log(msg, stdout=1) #输出关键日志
rv = context.buy_open(context.ins, context.order_num, price, order_type=OrderType.MARKET)
context.open_position_price = price
msg = "{} 开多 for {} 最新价={} 下单函数返回={}".format(str(data.current_dt),context.ins,str(price),str(rv))
context.write_log(msg, stdout=1) #输出关键日志
def handle_order(context, order):
"""委托回报推送"""
pass
def handle_trade(context, trade):
"""成交回报推送"""
pass
instruments = "RB2201.SHF"
#需要交易者传入的参数
strategy_setting = [
{
"instruments": instruments,
"order_num": 1,
"closetime_day": "14:58",
"closetime_night": "22:58"
}
]
start_date = "2021-08-01"
end_date = "2021-11-01"
md = M.hfbacktest.v1(start_date=start_date,
end_date=end_date,
instruments=[instruments], #只传入一个合约便于策略逻辑展示
capital_base=100000,
product_type=Product.FUTURE,
frequency=Frequency.MINUTE,
initialize=initialize,
before_trading_start=before_trading,
handle_data=handle_data,
handle_order=handle_order,
handle_trade=handle_trade,
plot_charts=True,
volume_limit=1.0,
disable_cache=0,
show_debug_info=1,
strategy_setting=strategy_setting,
slippage_type=SlippageType.FIXED,#滑点固定模式
slippage_value=1.0,#买卖双向各1个滑点
m_deps=np.random.rand())
[2021-11-25 16:29:14.399316] INFO: moduleinvoker: hfbacktest.v1 开始运行..
[2021-11-25 16:29:14.575307] INFO: hfbacktest: passed-in daily_data_ds:None
[2021-11-25 16:29:14.577998] INFO: hfbacktest: passed-in minute_data_ds:None
[2021-11-25 16:29:14.579501] INFO: hfbacktest: passed-in tick_data_ds:None
[2021-11-25 16:29:14.581016] INFO: hfbacktest: passed-in each_data_ds:None
[2021-11-25 16:29:14.582601] INFO: hfbacktest: passed-in dominant_data_ds:None
[2021-11-25 16:29:14.584173] INFO: hfbacktest: passed-in benchmark_data_ds:None
[2021-11-25 16:29:14.585742] INFO: hfbacktest: passed-in trading_calendar_ds:None
[2021-11-25 16:29:14.589782] INFO: hfbacktest: biglearning V1.3.2
[2021-11-25 16:29:14.591469] INFO: hfbacktest: bigtrader v1.7.9
[2021-11-25 16:29:14.988505] INFO: hfbacktest: strategy callbacks:{'on_init': , 'on_start': , 'handle_data': , 'handle_trade': , 'handle_order': }
[2021-11-25 16:29:15.003259] INFO: hfbacktest: begin reading history data, 2021-08-01 00:00:00~2021-11-01, disable_cache:0
[2021-11-25 16:29:15.004632] INFO: hfbacktest: reading benchmark data 2021-07-01 00:00:00~2021-11-01...
[2021-11-25 16:29:15.037513] INFO: moduleinvoker: cached.v2 开始运行..
[2021-11-25 16:29:15.925844] INFO: moduleinvoker: cached.v2 运行完成[0.877508s].
[2021-11-25 16:29:16.087076] INFO: hfbacktest: reading daily data 20200205~2021-11-01...
[2021-11-25 16:29:16.128101] INFO: moduleinvoker: cached.v2 开始运行..
[2021-11-25 16:29:16.433868] INFO: moduleinvoker: cached.v2 运行完成[0.305779s].
[2021-11-25 16:29:16.478455] INFO: hfbacktest: reading minute data 2021-07-30 20:55:00~2021-11-01...
[2021-11-25 16:29:16.499683] INFO: moduleinvoker: cached.v2 开始运行..
[2021-11-25 16:29:16.894192] INFO: moduleinvoker: cached.v2 运行完成[0.394527s].
[2021-11-25 16:29:18.087891] INFO: hfbacktest: cached_benchmark_ds:DataSource(de5a95e7a2164034b7835c2c950674abT)
[2021-11-25 16:29:18.089681] INFO: hfbacktest: cached_daily_ds:DataSource(aa51ad9e3a2745118aca9ed1850f788dT)
[2021-11-25 16:29:18.097243] INFO: hfbacktest: cached_minute_ds:DataSource(225222d47e354269b6ac90ff7fd2f5a0T)
[2021-11-25 16:29:18.099010] INFO: hfbacktest: cached_tick_ds:None
[2021-11-25 16:29:18.100240] INFO: hfbacktest: cached_each_ds:None
[2021-11-25 16:29:18.101423] INFO: hfbacktest: dominant_data_ds:None
[2021-11-25 16:29:18.102559] INFO: hfbacktest: read history data done, call run_backtest()
[2021-11-25 16:29:58.286291] INFO: hfbacktest: backtest done, raw_perf_ds:DataSource(5555f71885104716bc70da64c5d48067T)
[2021-11-25 16:29:58.949996] INFO: moduleinvoker: hfbacktest.v1 运行完成[44.551295s].