# 本代码由可视化策略环境自动生成 2023年3月6日 14:50
# 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
from bigtrader.utils import NumPyDeque
from bigtrader.constant import *
# 交易引擎:初始化函数,只执行一次
def m1_initialize_bigquant_run(context):
"""初始化函数"""
context.symbol = context.instruments
context.order_num = 1 # 下单手数
context.set_universe(context.symbol) #设置需要处理的合约
context.ma_length = 20
context.closetime_day = '14:55' # 日内策略白盘平仓时间,一般14:58
context.closetime_night = '22:58' #日内策略夜盘平仓时间,一般22:58,注意有些商品夜盘收盘时间不一样
context.set_stock_t1(1) # 支持T0操作
from datetime import datetime,timedelta
# 交易引擎:每个单位时间开盘前调用一次。
def m1_before_trading_start_bigquant_run(context, data):
# 盘前处理,订阅行情等
context.subscribe(context.symbol) #注册合约
context.tick_num_count = 0 # tick数量记录
context.trade_count = 0 # 记录每日交易次数
context.tick_num = 60 * 2 # 期货1分钟 60秒 每妙2tick
context.bar_num = context.ma_length # 均线长度
context.tick_series = NumPyDeque(context.tick_num, dtype='object') # 最近120个tick组成的队列
context.bar_series = NumPyDeque(context.bar_num, dtype='object') # 20个分钟 K线 (包括OHLC)
context.bar_open_series = NumPyDeque(context.bar_num, dtype='int') # 20个分钟 K线 开盘价
context.bar_high_series = NumPyDeque(context.bar_num, dtype='int') # 20个分钟 K线 最高价
context.bar_low_series = NumPyDeque(context.bar_num, dtype='int') # 20个分钟 K线 最低价
context.bar_close_series = NumPyDeque(context.bar_num, dtype='int') # 20个分钟 K线 收盘价
# 根据tick数据计算分钟k线的OCHL
def calc_OCHL(ticks):
tmp_open = 0.5 * (ticks[0].ask_price1 + ticks[0].bid_price1)
tmp_close = 0.5 * (ticks[-1].ask_price1 + ticks[-1].bid_price1)
tmp_high = tmp_open
tmp_low = tmp_open
tmp_volume = ticks[-1].volume - ticks[0].volume
for tick in ticks[1:]:
mid_price = 0.5 * (tick.ask_price1 + tick.bid_price1)
if tmp_high < mid_price:
tmp_high = mid_price
if tmp_low > mid_price:
tmp_low = mid_price
return {'open' : tmp_open, 'close' : tmp_close, 'high' : tmp_high, 'low' : tmp_low, 'volume' : tmp_volume, 'time_int' : ticks[-1].time_int}
# 交易引擎:tick数据处理函数,每个tick执行一次
def m1_handle_tick_bigquant_run(context, tick):
"""主函数"""
context.tick_series.append(tick)
context.tick_num_count += 1 # 每遍历一个tick数据,计数+1
if context.tick_num_count % context.tick_num == 0: # 每过一分钟 就加一根bar
OCHL = calc_OCHL(context.tick_series) # 分钟K线
context.bar_series.append(OCHL) # 分钟K线的队列
context.bar_open_series.append(OCHL['open'])
context.bar_low_series.append(OCHL['low'])
context.bar_high_series.append(OCHL['high'])
context.bar_close_series.append(OCHL['close'])
# 不足20根k线时,直接返回,不用往下运行
if len(context.bar_series) < context.bar_num:
return
elif len(context.bar_series) == context.bar_num:
mean_close = context.bar_close_series.data().mean() # 分钟K线均值
position_long = context.get_position(tick.symbol, Direction.LONG) # 多头持仓
position_short = context.get_position(tick.symbol, Direction.SHORT) # 空头持仓
price = tick.last_price # 最新价
cur_hm = tick.datetime.strftime('%H:%M') # 当前时间
# 部分品种夜盘收盘时间不一样,此时间表示指定的尾盘平仓时间往后偏移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.avail_qty != 0):
context.sell_close(tick.symbol, position_long.avail_qty, price, order_type=OrderType.MARKET)
msg = "{} 尾盘平多 for {} 最新价={}".format(cur_hm,tick.symbol,str(price))
context.write_log(msg, stdout=0) #输出关键日志,stdout设置为0,不展示到页面,stdout设置为1,展示到页面
if (position_short.avail_qty != 0):
context.buy_close(tick.symbol, position_short.avail_qty, price, order_type=OrderType.MARKET)
msg = "{} 尾盘平空 for {} 最新价={}".format(cur_hm,tick.symbol,str(price))
context.write_log(msg, stdout=0) #输出关键日志
# 建仓逻辑
if price > mean_close and position_long.current_qty == 0 and context.trade_count <=2 and cur_hm<="14:30":
context.buy_open(tick.symbol, context.order_num, price, order_type=OrderType.MARKET)
msg = "{} 开多 for {} 最新价={}".format(cur_hm,tick.symbol,str(price))
context.trade_count += 1 # 开仓次数判断需要
context.write_log(msg, stdout=0) #输出关键日志
elif price < mean_close and position_short.current_qty == 0 and context.trade_count <=2 and cur_hm<="14:30":
context.sell_open(tick.symbol, context.order_num, price, order_type=OrderType.MARKET)
msg = "{} 开空 for {} 最新价={}".format(cur_hm,tick.symbol,str(price))
context.trade_count += 1 # 开仓次数判断需要
context.write_log(msg, stdout=0) #输出关键日志
# 交易引擎:bar数据处理函数,每个时间单位执行一次
def m1_handle_data_bigquant_run(context, data):
pass
# 交易引擎:成交回报处理函数,每个成交发生时执行一次
def m1_handle_trade_bigquant_run(context, trade):
"""成交回报推送"""
return
msg = "handle_trade data:{}".format(trade.log_str())
context.write_log(msg, stdout=1)
# 分别获取最新的多头持仓和空头持仓
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=1)
# 交易引擎:委托回报处理函数,每个委托变化时执行一次
def m1_handle_order_bigquant_run(context, order):
"""委托回报推送"""
return
msg = "handle_order data:{}".format(order.log_str())
context.write_log(msg, stdout=1)
# 交易引擎:盘后处理函数,每日盘后执行一次
def m1_after_trading_bigquant_run(context, data):
pass
instrument = 'AG2006.SHF'
m1 = M.hftrade.v2(
instruments=instrument,
start_date='2020-01-01',
end_date='2020-04-01',
initialize=m1_initialize_bigquant_run,
before_trading_start=m1_before_trading_start_bigquant_run,
handle_tick=m1_handle_tick_bigquant_run,
handle_data=m1_handle_data_bigquant_run,
handle_trade=m1_handle_trade_bigquant_run,
handle_order=m1_handle_order_bigquant_run,
after_trading=m1_after_trading_bigquant_run,
capital_base=100000,
frequency='tick',
price_type='真实价格',
product_type='期货',
before_start_days='10',
volume_limit=1,
order_price_field_buy='open',
order_price_field_sell='close',
benchmark='000300.HIX',
plot_charts=True,
disable_cache=False,
replay_bdb=False,
show_debug_info=False,
backtest_only=False
)