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

ptrade 平台如何通过 tick_data 获取买一和卖一的十档逐笔委托队列?

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

问题描述

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

Title: ptrade Tick 级交易:解析 tick_data 数据字典中的十档买卖队列

Question: ptrade中tick_data函数接收的data字典里,怎么取到买一和卖一的逐笔队列?

解决方案

在 ptrade 量化交易平台中,进行 Tick 级别交易 时,可以通过 tick_data(context, data) 事件函数获取高频的盘口数据。若您开通了 Level 2 行情,买卖档位(bid_grpoffer_grp)的第一档中会包含详细的**委托队列(逐笔队列)**信息。

以下是关于如何在 tick_datadata 字典中提取买一和卖一逐笔委托队列的详细解析与代码实现。


一、 tick_data 数据字典结构解析

tick_data(context, data) 中,data 参数是一个字典:

  • Key: 订阅的标的代码(如 '600570.SS'
  • Value: 包含 tick(当前 tick 数据)、order(最近一条逐笔委托)和 transcation(最近一条逐笔成交)的字典。

其中,data[security]['tick'] 是一个 DataFrame,其包含的 bid_grp(买档)和 offer_grp(卖档)是字典类型。在 Level 2 行情下,其结构如下:

  • bid_grp (买档): {1: [价格, 委托量, 委托笔数, 委托队列], 2: [价格, 委托量, 委托笔数], ...}
  • offer_grp (卖档): {1: [价格, 委托量, 委托笔数, 委托队列], 2: [价格, 委托量, 委托笔数], ...}

注意:只有第一档(买一 1 / 卖一 1的列表里,第 4 个元素(索引为 3)才包含委托队列字典(格式为 {位置: 委托量},例如 {1: 33200, 2: 104800, 3: 1000})。


二、 如何提取买一和卖一的逐笔队列?

由于 data[security]['tick'] 返回的是 DataFrame,在实际提取时,需要注意数据格式的转换(通常需要使用 eval() 或直接读取字典)。

核心提取逻辑:

  1. 获取 tick 数据:tick_df = data[security]['tick']
  2. 提取买一档位信息:bid_one = eval(tick_df['bid_grp'][0])[1] (或直接通过 tick_df['bid_grp'].iloc[0][1],具体取决于平台返回的序列化状态)
  3. 提取买一队列:bid_queue = bid_one[3] (第 4 个元素)
  4. 提取卖一队列:offer_queue = eval(tick_df['offer_grp'][0])[1][3]

三、 完整 Python 策略示例

以下是一个完整的 ptrade 策略代码,展示了如何在 tick_data 中实时获取并打印买一、卖一的逐笔委托队列:

def initialize(context):
    # 设置操作的股票池
    g.security = '600570.SS'  # 恒生电子
    set_universe(g.security)
    
    # 开启相关参数(确保接收 L2 数据)
    set_parameters(tick_data_no_l2="0") 

def tick_data(context, data):
    security = g.security
    if security not in data:
        return
        
    try:
        # 1. 获取 tick 数据的 DataFrame
        tick_info = data[security]['tick']
        
        # 2. 提取买档和卖档字典
        # 注意:在 ptrade 中,DataFrame 里的 dict 字段可能需要 eval 解析
        bid_grp = eval(tick_info['bid_grp'][0]) if isinstance(tick_info['bid_grp'][0], str) else tick_info['bid_grp'][0]
        offer_grp = eval(tick_info['offer_grp'][0]) if isinstance(tick_info['offer_grp'][0], str) else tick_info['offer_grp'][0]
        
        # 3. 提取买一和卖一数据列表
        # 格式为: [价格, 委托量, 委托笔数, 委托队列]
        bid_one = bid_grp.get(1)
        offer_one = offer_grp.get(1)
        
        if bid_one and len(bid_one) > 3:
            bid_price = bid_one[0]       # 买一价
            bid_volume = bid_one[1]      # 买一总委托量
            bid_queue = bid_one[3]       # 买一逐笔委托队列 (dict)
            log.info(f"【买一】价格: {bid_price}, 总量: {bid_volume}, 队列前5笔: {list(bid_queue.items())[:5]}")
            
        if offer_one and len(offer_one) > 3:
            offer_price = offer_one[0]   # 卖一价
            offer_volume = offer_one[1]  # 卖一总委托量
            offer_queue = offer_one[3]   # 卖一逐笔委托队列 (dict)
            log.info(f"【卖一】价格: {offer_price}, 总量: {offer_volume}, 队列前5笔: {list(offer_queue.items())[:5]}")
            
    except Exception as e:
        log.error(f"提取 L2 委托队列出现异常: {e}")

def handle_data(context, data):
    # tick 级别策略中,handle_data 可保持为空
    pass

四、 注意事项

  1. Level 2 行情权限:逐笔委托队列(买一/卖一列表中的第 4 个元素)必须在开通并接入 Level 2 实时行情 的环境下才会有数据,普通 Level 1 行情下该位置为空字典 {}None
  2. 性能优化tick_data 每 3 秒触发一次,处理 L2 逐笔数据时,尽量避免复杂的循环计算,以防引起主线程卡顿。建议使用 set_parameters(tick_data_no_l2="1") 来按需关闭不需要的 L2 逐笔推送以提升性能。