🚀 AI 一键生成 joinquant 策略代码
立即体验

joinquant 平台如何订阅 Tick 数据并编写盘口高频交易策略?(附 Python 源码)

joinquant | 发布时间: 2026/7/31
以下内容由 EasyQuant 生成。

问题描述

请根据以下 SEO 主题生成完整页面内容:

Title: joinquant Tick 级高频交易:subscribe 订阅与 handle_tick 实战

Question: 请教如何在 joinquant 中订阅 Tick 数据并编写盘口高频交易策略?

解决方案

在 JoinQuant(聚宽)平台中,进行 Tick 级高频或盘口交易需要开启真实价格模式,并通过专用的 Tick 监听与订阅 API 实现。下面为您梳理核心步骤、关键 API 接口及完整的策略源码。

一、Tick 策略的核心流程

  1. 策略初始化 (initialize):设定基准、开启真实价格模式(set_option('use_real_price', True))并配置子账户类型(如期货账户 type='futures' 或股票账户)。
  2. 开盘前订阅 (before_trading_start / before_market_open):使用 subscribe(security, 'tick') 订阅目标标的的 Tick 事件。
  3. 事件驱动处理 (handle_tick):当订阅的标的产生新 Tick 时自动触发,在此函数内结合 get_current_tick 获取最新买卖盘口(买一至买五/卖一至卖五)并执行下单逻辑。
  4. 收盘后退订 (after_trading_end):使用 unsubscribe_all() 取消所有 Tick 订阅。

二、核心 API 说明

  • subscribe(security, frequency):订阅 Tick 事件,frequency 必须为 'tick'。模拟交易中最多可同时订阅 100 个标的。
  • unsubscribe_all():取消所有 Tick 事件订阅。
  • handle_tick(context, tick):Tick 事件触发时的回调函数,tick 参数为当前触发事件的 Tick 对象。
  • get_current_tick(security):获取指定标的的最新 Tick 数据对象,包含盘口买卖价量(如 a1_p, a1_v, b1_p, b1_v)及最新价 current 等字段。

三、完整策略源码示例(以商品期货为例)

# 运行频率建议设置为 tick,回测时间请选择包含 Tick 数据的区间
import jqdata

def initialize(context):
    # 1. 设定基准
    set_benchmark('000300.XSHG')
    # 2. 必须开启动态复权/真实价格模式
    set_option('use_real_price', True)
    
    # 获取初始资金并配置期货子账户
    init_cash = context.portfolio.starting_cash
    set_subportfolios([SubPortfolioConfig(cash=init_cash, type='futures')])
    
    # 定义交易标的(螺纹钢主力合约)
    g.security = 'RB1909.XSGE'
    
    # 定时任务:开盘前与收盘后
    run_daily(before_market_open, time='08:30', reference_security='RB9999.XSGE')
    run_daily(after_market_close, time='15:30', reference_security='RB9999.XSGE')

def before_market_open(context):
    # 在开盘前订阅 Tick 事件
    subscribe(g.security, 'tick')
    log.info("已成功订阅 Tick: %s" % g.security)

def handle_tick(context, tick):
    """
    每当有新的 Tick 产生时触发此函数
    """
    security = g.security
    # 获取最新的盘口 Tick 快照
    tick_data = get_current_tick(security)
    if tick_data is None:
        return
    
    # 读取卖一价与买一价
    ask_price_1 = tick_data.a1_p  # 卖一价
    bid_price_1 = tick_data.b1_p  # 买一价
    ask_volume_1 = tick_data.a1_v # 卖一量
    bid_volume_1 = tick_data.b1_v # 买一量
    
    # 获取当前多头持仓
    position_long = context.subportfolios[0].long_positions.get(security, None)
    long_amount = position_long.total_amount if position_long else 0
    
    # 简易高频逻辑示例:当买一量远大于卖一量(买盘强劲)且无持仓时开多仓
    if long_amount == 0 and bid_volume_1 > ask_volume_1 * 3:
        # 以市价单开一手多单
        order(security, 1, side='long', pindex=0)
        log.info("买盘强劲,开多单一手。买一量: %s, 卖一量: %s" % (bid_volume_1, ask_volume_1))
        
    # 止盈/平仓逻辑:有持仓且盘口反转(卖一量大于买一量)时平仓
    elif long_amount > 0 and ask_volume_1 > bid_volume_1 * 2:
        # 平多单
        order(security, -1, side='long', pindex=0)
        log.info("卖压增加,平多单一手。")

def after_market_close(context):
    # 盘后取消订阅,释放资源
    unsubscribe_all()
    log.info("已取消所有 Tick 订阅")

四、注意事项

  1. 运行频率:新建回测或模拟盘时,必须将运行频率设置为 tick 级别。
  2. 不能与 handle_data 混用:在 Tick 频率策略中,handle_dataevery_bar 定时函数不会被触发,策略逻辑应全部写在 handle_tick 中。
  3. 未交易时段处理:若非交易时段或当前时刻未产生 Tick,get_current_tick 可能返回 None,务必做好空值判断。