🚀 AI 一键生成 ptrade 策略代码

PTrade 交易实战:订单状态监控与“部成待撤”异常处理逻辑

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

问题描述

如何判断和处理“部成待撤”状态的订单?

解决方案

在PTrade量化交易平台中,“部成待撤”(Partially Filled, Pending Cancel)是一种中间状态,表示订单已经部分成交,且策略或用户已经发起了撤单请求,但柜台或交易所尚未最终确认撤单结果。

以下是关于如何判断和处理该状态的详细说明及代码示例。

1. 状态定义与判断方法

根据PTrade API文档的数据字典,“部成待撤”对应的订单状态码为 '4'

  • 含义:订单已成交一部分数量,剩余部分正在撤单过程中。
  • 判断方式:通过 get_orders() 获取订单对象,检查其 status 属性是否等于 '4'

2. 处理逻辑建议

由于“部成待撤”是一个过渡状态,通常不需要(也无法)对其再次发起撤单操作。处理策略通常如下:

  1. 等待状态流转:该状态通常很快会变为“部撤”(状态码 '5',即撤单成功)或“已成”(状态码 '8',即撤单失败,剩余部分全部成交)。
  2. 风控锁死:在状态未流转为最终状态(如部撤、已成)之前,不要对该标的进行新的下单操作,以免造成资金占用计算错误或重复下单。
  3. 超时处理(仅限实盘):如果在实盘中该状态持续时间过长(如超过1分钟),可能涉及柜台异常,建议通过日志报警人工介入。

3. 代码实现

以下策略代码展示了如何在 handle_data 中轮询订单,识别“部成待撤”的订单,并进行相应的逻辑处理(如打印日志、暂停对该标的的后续操作)。

def initialize(context):
    # 初始化股票池
    g.security = '600570.SS'
    set_universe(g.security)

def handle_data(context, data):
    # 获取当日所有订单
    orders = get_orders()
    
    # 标记是否存在“部成待撤”的订单
    has_pending_cancel = False
    
    for _order in orders:
        # 状态码 '4' 代表 部成待撤
        if _order.status == '4':
            log.info("发现部成待撤订单,订单号: %s, 标的: %s" % (_order.order_id, _order.symbol))
            has_pending_cancel = True
            
            # 在此处可以添加逻辑,例如记录到全局变量,防止下一轮继续操作该标的
            # g.locked_securities.append(_order.symbol)
            
        # 状态码 '3' 代表 已报待撤 (尚未成交但正在撤单)
        elif _order.status == '3':
            log.info("发现已报待撤订单,订单号: %s" % _order.order_id)
    
    # 正常的交易逻辑
    if not has_pending_cancel:
        # 只有当没有正在撤单的中间状态时,才进行新的交易判断
        # 示例:简单的买入逻辑
        if get_position(g.security).amount == 0:
            order(g.security, 100)
    else:
        log.info("当前有订单处于撤单中间状态,暂停新开仓操作。")

4. 关键点总结

  • 状态码对照
    • '3': 已报待撤(完全未成交,正在撤)
    • '4': 部成待撤(部分成交,剩余正在撤)
    • '5': 部撤(最终状态,部分成交,剩余已撤销)
  • API兼容性:代码使用了 %s 格式化字符串,完全兼容 Python 3.5 及以上版本。
  • 实盘注意:在回测环境中,由于撮合是瞬间完成的,很难捕捉到 '4' 这种瞬时状态;该逻辑主要用于实盘交易中的状态防抖和风控。

Q&A

Q1: 为什么我的策略里捕捉不到状态 '4'?
A1: 在回测模式下,PTrade的撮合引擎处理速度极快,订单状态通常直接从“已报”跳变为“已成”或“已撤”,很难捕捉到“待撤”这种毫秒级的中间状态。该逻辑主要在实盘交易中有效。

Q2: 如果订单一直卡在“部成待撤”怎么办?
A2: 如果在实盘中该状态持续超过几秒钟甚至更久,通常意味着柜台或交易所回报延迟。此时再次调用 cancel_order 通常无效。建议在策略中设置超时告警,并联系券商或通过终端手动检查。

Q3: cancel_order 函数能撤销状态为 '4' 的订单吗?
A3: 不需要也不建议。状态为 '4' 说明系统已经接收到了撤单指令并正在处理中。重复调用 cancel_order 可能会导致API报错或被柜台视为频繁报撤单。