🚀 AI 一键生成 ptrade 策略代码

PTrade `tick_data` 数据结构实战:如何提取并使用逐笔委托与成交信息?

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

问题描述

在处理tick数据时,如何获取并解析其中的逐笔委托和逐笔成交明细?

解决方案

在PTrade量化交易平台中,处理Tick级别的逐笔委托(Order)和逐笔成交(Transaction)数据主要有两种方式:

  1. 通过 tick_data 回调函数被动接收:这是处理高频策略最常用的方式,系统每隔3秒(或更短,取决于频率设置)推送一次数据。
  2. 通过主动查询接口获取:使用 get_individual_entrustget_individual_transaction 函数主动拉取数据。

注意:获取逐笔数据通常需要开通 Level-2 行情权限,否则对应字段可能返回 None 或空数据。

以下是具体的实现代码和解析。

策略代码示例

def initialize(context):
    # 初始化策略
    # 设置我们要操作的股票池,这里以恒生电子为例
    g.security = '600570.SS'
    set_universe(g.security)
    
    # 开启Tick级别数据接收(通常在实盘或Tick回测模式下自动生效)
    # 注意:确保账户有Level-2权限
    
    # 设置日志打印频率,避免日志过多
    g.log_counter = 0

def tick_data(context, data):
    """
    Tick数据回调函数,每隔一定时间(如3秒)触发一次
    data结构:
    {
        '股票代码': {
            'order': DataFrame/None (最近一条逐笔委托),
            'tick': DataFrame (当前快照),
            'transcation': DataFrame/None (最近一条逐笔成交, 注意API文档中key可能拼写为transcation)
        }
    }
    """
    security = g.security
    
    # 1. 获取该股票的数据包
    if security not in data:
        return
        
    stock_data = data[security]
    
    # ------------------------------------------------------
    # 解析逐笔委托 (Order)
    # ------------------------------------------------------
    # 注意:如果没有L2权限或该时刻无委托,可能为None
    order_df = stock_data.get('order')
    
    if order_df is not None and len(order_df) > 0:
        # 由于是DataFrame,通常取第一行(最近的一笔)
        latest_order = order_df.iloc[0]
        
        # 提取字段
        order_time = latest_order['business_time']      # 时间戳
        order_price = latest_order['hq_px']             # 委托价格
        order_vol = latest_order['business_amount']     # 委托数量
        order_dir = latest_order['business_direction']  # 委托方向 (0-卖, 1-买, 2-借入, 3-出借)
        order_kind = latest_order['trans_kind']         # 委托类别 (1-市价, 2-限价, 3-本方最优)
        
        # 简单的逻辑示例:打印大额买单
        if order_dir == 1 and order_vol > 10000: # 假设大于100手算大单
            log.info("[逐笔委托] 监测到大额买单: 时间=%s, 价格=%.2f, 数量=%d" % (order_time, order_price, order_vol))

    # ------------------------------------------------------
    # 解析逐笔成交 (Transaction)
    # ------------------------------------------------------
    # 注意:API文档中该Key有时拼写为 'transcation',需根据实际返回字典键值获取
    trans_df = stock_data.get('transcation') 
    
    if trans_df is not None and len(trans_df) > 0:
        latest_trans = trans_df.iloc[0]
        
        # 提取字段
        trans_time = latest_trans['business_time']      # 时间戳
        trans_price = latest_trans['hq_px']             # 成交价格
        trans_vol = latest_trans['business_amount']     # 成交数量
        trans_dir = latest_trans['business_direction']  # 成交方向 (0-卖, 1-买)
        trans_idx = latest_trans['trade_index']         # 成交编号
        
        # 简单的逻辑示例:打印主动买入成交
        if trans_dir == 1:
             # 限制日志打印频率
            g.log_counter += 1
            if g.log_counter % 10 == 0:
                log.info("[逐笔成交] 主动买入: 时间=%s, 价格=%.2f, 数量=%d" % (trans_time, trans_price, trans_vol))

def handle_data(context, data):
    # 分钟/日线级别的逻辑(如果需要)
    # 也可以在这里使用主动查询接口获取当日累积的逐笔数据
    
    # 示例:主动查询逐笔成交(获取最近50条)
    # 注意:is_dict=True 可以提高返回速度,返回字典格式
    if is_trade(): # 仅在交易模式下有效
        transactions = get_individual_transaction(stocks=[g.security], data_count=10, is_dict=True)
        if transactions:
            # 处理主动查询到的数据
            pass

关键点解析

1. tick_data 中的数据结构

tick_data(context, data) 函数中,data 参数是一个字典。对于每一只股票,它包含三个主要键值:

  • tick: 当前的行情快照(盘口、最新价等)。
  • order: 最近一条逐笔委托数据。
  • transcation: 最近一条逐笔成交数据(请注意: PTrade文档及实际返回中,这个Key通常拼写为 transcation 而非 transaction,编写代码时需特别留意,或者先打印 data[security].keys() 确认)。

2. 字段含义

  • 逐笔委托 (order) 常用字段:
    • hq_px: 委托价格。
    • business_amount: 委托数量。
    • business_direction: 0-卖, 1-买。
    • trans_kind: 1-市价, 2-限价, 3-本方最优。
  • 逐笔成交 (transcation) 常用字段:
    • hq_px: 成交价格。
    • business_amount: 成交数量。
    • business_direction: 0-卖(内盘/主动卖), 1-买(外盘/主动买)。
    • buy_no / sell_no: 买方/卖方委托单号(可用于追踪大单拆单)。

3. 主动查询接口

除了在 tick_data 中被动接收,你也可以在 handle_data 或其他地方主动调用:

  • get_individual_entrust(stocks=..., is_dict=True): 获取逐笔委托。
  • get_individual_transaction(stocks=..., is_dict=True): 获取逐笔成交。
  • 建议设置 is_dict=True,这样返回的是字典格式,解析速度比 DataFrame 快,更适合高频场景。

Q&A

Q1: 为什么我在回测中 tick_data 里取不到 ordertranscation 数据?
A: 这通常有两个原因:

  1. 你选择的回测频率不是 "Tick级别"。只有在Tick级别回测或实盘交易中,tick_data 函数才会被调用。
  2. 你的账号或回测环境没有开通 Level-2 行情权限。逐笔数据属于 L2 高级行情,普通行情只包含快照(Snapshot)。

Q2: tick_data 推送的数据是全量的吗?
A: 不一定。tick_data 的触发频率通常是每3秒一次(或根据券商配置)。在 data 参数中返回的 ordertranscation 通常是最近一条该切片时间内的数据。如果市场交易非常活跃,3秒内发生了成百上千笔交易,单纯依靠 tick_data 的推送可能会漏掉中间的明细。如果需要极其精确的全量逐笔分析,建议结合 get_individual_transaction 主动查询,或者确认券商端的推送机制是否支持全量推送。

Q3: 如何判断逐笔成交是主动买入还是主动卖出?
A: 查看 transcation 数据中的 business_direction 字段。

  • 1: 代表买(Buy),即外盘,通常理解为主动买入(买方以卖一价或更高价格成交)。
  • 0: 代表卖(Sell),即内盘,通常理解为主动卖出(卖方以买一价或更低价格成交)。