from datetime import datetime,timedelta
STRATEGY_NAME = "STRATEGY_1"
def initialize(context):
"""初始化"""
context.ins = context.get_conf_param("instruments") # 从传入参数中获取需要交易的合约
print(context.ins)
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.flag = 1 # 用于获取今开
context.count = 0 # 交易次数记录
bar1d_df = data.history(context.ins, ["high","low",'close'], 1, "1d")
context.high = bar1d_df.iloc[0]['high'] # 昨高
context.low = bar1d_df.iloc[0]['low'] # 昨低
def handle_data(context, data):
"""Bar行情推送"""
# 获取当天开盘价
if context.flag == 1:
open_price = data.history(context.ins, ["open"], 1, "1m")
context.flag = context.flag + 1
context.today_open = open_price.iloc[-1]['open']
cur_date = data.current_dt
cur_hm = cur_date.strftime('%H:%M')
# 部分品种夜盘收盘时间不一样,此时间表示指定的尾盘平仓时间往后偏移30分钟,这段时间内不能开新仓,只能平仓。给30分钟是为了足够的冗余
closetime_nightshift = (datetime.strptime(context.closetime_night,'%H:%M') + timedelta(minutes = 30)).strftime('%H:%M')
# 分别获取多头持和空头持仓
position_long = context.get_position(context.ins, Direction.LONG)
position_short = context.get_position(context.ins, Direction.SHORT)
# 获取当前价格
price = data.current(context.ins, "close")
# 尾盘平仓
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=0) #输出关键日志
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=0) #输出关键日志
#尾盘不开新仓,直接返回
return
#止损逻辑
# 多头持仓,最新价小于开盘价 平多
if position_long.current_qty != 0 and price < context.today_open:
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=0)
# 空头持仓,最新价大于开盘价 平空
elif position_short.current_qty != 0 and price > context.today_open:
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=0)
# 建仓逻辑
# 当前的最新价大于前一天的最高价且没有持仓 开多
if (position_long.current_qty == 0) and (price > context.high) and (context.count<=1):
rv = context.buy_open(context.ins, context.order_num, price, order_type=OrderType.MARKET)
msg = "{} 开多 for {} 最新价={} 下单函数返回={}".format(str(data.current_dt),context.ins,str(price),str(rv))
context.count += 1 #只开仓一次的判断
context.write_log(msg, stdout=0)
# 当前最新价小于前一天的最低价且没有持仓 开空
elif (position_short.current_qty == 0) and (price < context.low) and (context.count<=1):
rv = context.sell_open(context.ins, context.order_num, price, order_type=OrderType.MARKET)
msg = "{} 开空 for {} 最新价={} 下单函数返回={}".format(str(data.current_dt),context.ins,str(price),str(rv))
context.count += 1
context.write_log(msg, stdout=0)
def handle_order(context, order):
"""委托回报推送"""
msg = "handle_order data:{}".format(order.log_str())
context.write_log(msg, stdout=0)
def handle_trade(context, trade):
"""成交回报推送"""
msg = "handle_trade data:{}".format(trade.log_str())
context.write_log(msg, stdout=0)
# 分别获取最新的多头持仓和空头持仓
position_long = context.get_position(trade.symbol, Direction.LONG)
position_short = context.get_position(trade.symbol, Direction.SHORT)
msg = "当前多头持仓:{} 当前空头持仓:{}".format(str(position_long),str(position_short))
context.write_log(msg, stdout=0)
instruments = "RB2110.SHF"
#需要交易者传入的参数
strategy_setting = [{
"instruments": instruments,
"order_num": 2,
"closetime_day": "14:58",
"closetime_night": "22:58"
}]
start_date = "2021-02-01"
end_date = "2021-03-01"
md = M.hfbacktest.v1(start_date=start_date,
end_date=end_date,
instruments=[instruments],
capital_base=20000,
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=0.0,
disable_cache=0,
show_debug_info=0,
strategy_setting=strategy_setting,
slippage_type=SlippageType.FIXED,#滑点固定模式
slippage_value=1.0,#买卖双向各1个滑点
m_deps=np.random.rand() # 模块依赖,值相同的话会命中缓存
)