🚀 AI 一键生成 joinquant 策略代码

JoinQuant Tick 级数据高级应用:如何分析买卖五档订单簿数据?

joinquant | 发布时间: 2025/12/16
以下内容由 EasyQuant 生成。

问题描述

如何获取实时买卖五档的挂单价格和数量,并计算订单不平衡指标?

解决方案

在聚宽(JoinQuant)平台中,获取实时买卖五档挂单数据主要通过 Tick 级频率的回测或模拟交易来实现。

核心步骤说明

  1. 获取方式
    • Tick 策略中,使用 handle_tick(context, tick) 函数,tick 对象包含了当前的五档盘口数据。
    • 分钟/日频策略中,可以使用 get_current_tick(security) 获取当前的快照数据。
  2. 数据字段
    • 买盘量:b1_v ~ b5_v,买盘价:b1_p ~ b5_p
    • 卖盘量:a1_v ~ a5_v,卖盘价:a1_p ~ a5_p
  3. 订单不平衡指标 (OII) 计算
    • OII (Order Imbalance Indicator) 是衡量买卖压力的常用指标。
    • 公式:$OII = \frac{\sum \text{BidVolume} - \sum \text{AskVolume}}{\sum \text{BidVolume} + \sum \text{AskVolume}}$
    • 取值范围为 [-1, 1],越接近 1 代表买压越强,越接近 -1 代表卖压越强。

策略代码实现

以下是一个完整的 Tick 级策略示例,展示了如何提取五档数据、计算 OII 指标,并根据指标进行简单的交易判断。

# -*- coding: utf-8 -*-
import jqdata

def initialize(context):
    # 设定基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    
    # 设置要操作的标的(以平安银行为例)
    g.security = '000001.XSHE'
    
    # 设定OII阈值,用于触发交易
    g.buy_threshold = 0.6   # 买压显著
    g.sell_threshold = -0.6 # 卖压显著

    # 必须在初始化或开盘前订阅 Tick 数据
    # 注意:Tick 回测需要在回测界面选择“Tick”频率
    run_daily(before_market_open, time='09:00')

def before_market_open(context):
    # 订阅标的的 tick 事件
    subscribe(g.security, 'tick')

# Tick 数据更新时调用(仅在 Tick 回测/模拟中生效)
def handle_tick(context, tick):
    security = tick.code
    
    # 1. 获取五档买卖量
    # 买一到买五的量
    bid_volumes = [tick.b1_v, tick.b2_v, tick.b3_v, tick.b4_v, tick.b5_v]
    # 卖一到卖五的量
    ask_volumes = [tick.a1_v, tick.a2_v, tick.a3_v, tick.a4_v, tick.a5_v]
    
    # 2. 计算总买量和总卖量
    total_bid_vol = sum(bid_volumes)
    total_ask_vol = sum(ask_volumes)
    
    # 3. 计算订单不平衡指标 (OII)
    # 防止分母为0
    if total_bid_vol + total_ask_vol > 0:
        oii = (total_bid_vol - total_ask_vol) / (total_bid_vol + total_ask_vol)
    else:
        oii = 0
        
    # 打印日志方便观察
    # log.info("时间: %s, OII: %.4f, 总买量: %d, 总卖量: %d" % (tick.datetime, oii, total_bid_vol, total_ask_vol))
    
    # 4. 简单的交易逻辑示例
    position = context.portfolio.positions[security]
    
    # 如果 OII > 0.6,说明买盘强劲,尝试买入
    if oii > g.buy_threshold and position.total_amount == 0:
        log.info("买压显著 (OII=%.2f),执行买入" % oii)
        order_value(security, context.portfolio.available_cash)
        
    # 如果 OII < -0.6,说明卖盘强劲,尝试卖出
    elif oii < g.sell_threshold and position.closeable_amount > 0:
        log.info("卖压显著 (OII=%.2f),执行卖出" % oii)
        order_target(security, 0)

def after_trading_end(context):
    # 收盘后取消订阅
    unsubscribe_all()

代码解析

  1. subscribe(g.security, 'tick'):
    这是 Tick 策略的关键。必须显式订阅标的,handle_tick 函数才会被触发。
  2. tick 对象属性:
    • tick.b1_vtick.b5_v: 代表买一到买五的手数(注意单位是股还是手,聚宽股票 Tick 数据通常单位为股)。
    • tick.a1_vtick.a5_v: 代表卖一到卖五的手数。
    • tick.current: 当前最新价。
  3. OII 计算逻辑:
    代码中将五档的买量求和与卖量求和,然后计算差值比例。这是一个最基础的微观结构指标,常用于短线高频策略。
  4. 注意事项:
    • 此代码需要在回测配置中选择 “Tick” 频率。
    • 如果是在分钟策略中使用,不能使用 handle_tick,而应该在 handle_data 中调用 get_current_tick(security) 来获取快照对象,属性访问方式相同。

Q&A

Q: 为什么我在 handle_data 中无法获取 tick 参数?
A: handle_data 是按分钟或按天运行的,不接收 tick 参数。如果在分钟策略中需要 Tick 数据,请使用 jqdata.get_current_tick(security) 函数获取当前的 Tick 快照对象。

Q: OII 指标除了计算五档总量,还有其他计算方式吗?
A: 有的。进阶的 OII 计算可以引入距离权重。例如,给买一/卖一更高的权重,给买五/卖五较低的权重(如 $W_i = 1/i$),因为一档的价格最容易成交,对短期价格影响最大。

Q: 聚宽的 Tick 数据包含期货吗?
A: 包含。聚宽支持股票、期货、场内基金和指数的 Tick 数据。对于期货,Tick 对象通常只提供买一和卖一(b1_v, a1_v),而不像股票那样提供完整的五档数据(取决于交易所披露的深度)。