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

ptrade量化平台中撤单和补单的时间规则是什么?如何实现撤补逻辑?

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

问题描述

撤补操作问题

算法交易中撤单和补单的时间规则是什么?

解决方案

在算法交易中,撤单和补单(简称“撤补”)是控制交易滑点、提高成交率的重要手段。在 ptrade 量化平台中,撤补操作不仅需要调用相应的 API,还必须严格遵守交易所的时间规则。

一、 撤单与补单的时间规则(基于A股市场机制)

在 ptrade 中执行撤单操作,本质上是向交易所发送撤单指令,因此必须符合沪深交易所的交易时间规定:

  1. 早盘集合竞价阶段
    • 09:15 - 09:20:可以接收申报,也可以接收撤单申报。此阶段可以进行撤补操作。
    • 09:20 - 09:25:可以接收申报,但不接收撤单申报。此阶段调用撤单 API 会被交易所拒绝(废单)。
  2. 连续竞价阶段
    • 09:30 - 11:3013:00 - 14:57:正常交易时间,随时可以进行撤单和补单操作。
  3. 尾盘集合竞价阶段(深市及科创板/创业板)
    • 14:57 - 15:00不接收撤单申报。此阶段无法撤单。
  4. 盘后固定价格交易阶段(科创板/创业板)
    • 15:05 - 15:30:可以撤销未成交的盘后固定价格委托。ptrade 提供了专门的 after_trading_cancel_order 接口用于盘后撤单。

注意:在 ptrade 的回测环境中,每天结束时(15:00)系统会自动取消所有未完成的交易订单。

二、 ptrade 中实现撤补的核心 API

实现撤补逻辑通常需要以下三个步骤:

  1. 查询未成交订单:使用 get_open_orders(security) 获取当前挂在盘口未完全成交的订单列表。
  2. 执行撤单:使用 cancel_order(order_id) 对指定的未成交订单发起撤单请求。
  3. 重新补单:撤单成功后(可通过 get_order 或主推事件确认状态),使用 order()order_target() 按照新的价格(如最新市价)重新下单。

三、 撤补逻辑代码示例

以下是一个在 ptrade 中实现简单超时撤补逻辑的示例。策略每分钟检查一次,如果发现有未成交的订单,则将其撤销,并以当前最新价重新补单。

def initialize(context):
    g.security = '600570.SS'
    set_universe(g.security)
    # 记录需要补单的数量
    g.reorder_amount = 0

def handle_data(context, data):
    # 1. 处理上一周期的撤单补单逻辑
    if g.reorder_amount != 0:
        # 获取最新价作为补单价格
        current_price = data[g.security]['close']
        log.info(f"执行补单,标的:{g.security},数量:{g.reorder_amount},价格:{current_price}")
        order(g.security, g.reorder_amount, limit_price=current_price)
        g.reorder_amount = 0 # 重置补单数量

    # 2. 检查当前未成交订单并执行撤单
    open_orders = get_open_orders(g.security)
    for open_order in open_orders:
        # 如果订单状态为待报、已报、部成等未完成状态
        if open_order.status in ['1', '2', '7']:
            log.info(f"发现未成交订单 {open_order.id},准备撤单。")
            cancel_order(open_order.id)
            # 计算需要补单的数量(原委托数量 - 已成交数量)
            # 注意:买入为正,卖出为负
            unfilled_amount = open_order.amount - open_order.filled
            g.reorder_amount += unfilled_amount

    # 3. 正常的策略下单逻辑 (示例:如果空仓则买入100股)
    if get_position(g.security).amount == 0 and len(open_orders) == 0 and g.reorder_amount == 0:
        current_price = data[g.security]['close']
        # 故意挂一个低价单,模拟无法成交的情况
        order(g.security, 100, limit_price=current_price * 0.95)
        log.info(f"发起初始委托,价格:{current_price * 0.95}")

四、 进阶建议

  1. 使用主推事件加速撤补:对于对速度要求极高的算法交易(如 Tick 级别),建议使用 on_order_responseon_trade_response 事件来监听订单状态变化,而不是在 handle_data 中轮询 get_open_orders,这样可以大幅降低撤补延迟。
  2. 防范重复下单:在执行补单前,务必确认撤单指令已经生效(订单状态变为 '5' 部撤 或 '6' 已撤),否则可能导致双重下单,超出资金或仓位限制。