复制链接
克隆策略

策略名称

均线突破策略(Tick级别)

策略逻辑

本策略是基于tick数据的高频日内交易策略。策略每tick触发一次,根据tick数据合并成分钟K线数据,然后计算分钟K线的20均线值,若当前tick价格上穿均线,则买开;反之,则卖开。每日交易次数小于2次,14:30分后不再建仓,尾盘阶段平掉所有仓位。

In [2]:
# 本代码由可视化策略环境自动生成 2023年3月6日 14:50
# 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
from bigtrader.utils import NumPyDeque
from biglearning.api import M
from bigtrader.constant import *

# 交易引擎:初始化函数,只执行一次
def m1_initialize_bigquant_run(context):
    """初始化函数"""
    context.symbol = context.instruments
    context.order_num = 1 # 下单手数
    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
)
/home/aiuser/.local/lib/python3.8/site-packages/numpy/core/getlimits.py:500: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.
  setattr(self, word, getattr(machar, word).flat[0])
/home/aiuser/.local/lib/python3.8/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.
  return self._float_to_str(self.smallest_subnormal)
/home/aiuser/.local/lib/python3.8/site-packages/numpy/core/getlimits.py:500: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.
  setattr(self, word, getattr(machar, word).flat[0])
/home/aiuser/.local/lib/python3.8/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.
  return self._float_to_str(self.smallest_subnormal)
[2023-05-23 10:34:16.567816] INFO moduleinvoker: hfbacktest.v2 开始运行..
[2023-05-23 10:34:16.698418] INFO hfbacktest: hfbacktest2 V2.0.0
[2023-05-23 10:34:16.700694] INFO hfbacktest: pytradersdk v1.0.0 2023-05-19
[2023-05-23 10:34:16.801063] INFO moduleinvoker: cached.v2 开始运行..
[2023-05-23 10:34:17.136139] INFO moduleinvoker: cached.v2 运行完成[0.335043s].
[2023-05-23 10:34:17.283128] INFO moduleinvoker: cached.v2 开始运行..
[2023-05-23 10:34:17.454463] INFO moduleinvoker: cached.v2 运行完成[0.171275s].
[2023-05-23 10:34:17.597115] INFO moduleinvoker: cached.v2 开始运行..
[2023-05-23 10:34:40.620732] INFO moduleinvoker: cached.v2 运行完成[23.023548s].
[2023-05-23 10:34:49.979618] INFO hfbacktest: read history data done, call run backtest(future,tick,100000,2020-01-01~2020-04-01) ...
[2023-05-23 10:36:56.641061] INFO hfbacktest: backtest done, raw_perf_ds:DataSource(10d7cf2cda0b40dc9101971bd17952c8T)
/usr/local/python3/lib/python3.8/site-packages/pandas/compat/_optional.py:116: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
  if distutils.version.LooseVersion(version) < minimum_version:
/usr/local/python3/lib/python3.8/site-packages/setuptools/_distutils/version.py:346: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
  other = LooseVersion(other)
/usr/local/python3/lib/python3.8/site-packages/tables/array.py:241: DeprecationWarning: `np.object` is a deprecated alias for the builtin `object`. To silence this warning, use `object` by itself. Doing this will not modify any behavior and is safe. 
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  (oid, self.atom, self.shape, self._v_chunkshape) = self._open_array()
/usr/local/python3/lib/python3.8/site-packages/tables/atom.py:1224: DeprecationWarning: tostring() is deprecated. Use tobytes() instead.
  return pickle.loads(array.tostring())
/var/app/enabled/fai/settings.py:22: ResourceWarning: unclosed <socket.socket fd=77, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('10.160.156.187', 51168), raddr=('10.102.176.195', 8000)>
ResourceWarning: Enable tracemalloc to get the object allocation traceback
/var/app/enabled/fai/lib/logsclient.py:37: DeprecationWarning: Importing DisplayHandle from IPython.core.display is deprecated since IPython 7.14, please import from IPython display
[2023-05-23 10:36:59.218969] INFO: bigcharts.impl.render:render.py:407:render_chart Data is None, skip loading it to chart.
  • 收益率-8.36%
  • 年化收益率-30.1%
  • 基准收益率-11.49%
  • 阿尔法-0.33
  • 贝塔-0.01
  • 夏普比率-3.32
  • 胜率0.47
  • 盈亏比0.82
  • 收益波动率11.89%
  • 最大回撤8.61%
成交时间 合约代码 合约名称 买/卖 开/平 数量 成交价 交易金额 交易佣金 平仓盈亏
Loading... (need help?)
日期 合约代码 合约名称 持仓均价 收盘价 数量 持仓保证金 浮动盈亏 平仓盈亏
Loading... (need help?)
时间 级别 内容
Loading... (need help?)
[2023-05-23 10:36:59.851208] INFO moduleinvoker: hfbacktest.v2 运行完成[163.28347s].
INFO:moduleinvoker:hfbacktest.v2 运行完成[163.28347s].
[2023-05-23 10:36:59.857189] INFO moduleinvoker: hftrade.v2 运行完成[163.322106s].
INFO:moduleinvoker:hftrade.v2 运行完成[163.322106s].
In [ ]: