🚀 AI 一键生成 ptrade 策略代码

PTrade 策略风控:如何使用 get_open_orders 批量管理未成交订单?

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

问题描述

如何获取我当前所有还没成交的挂单,并把它们全部撤销?

解决方案

在PTrade中,要获取当前所有未成交的挂单并将其全部撤销,主要涉及两个API函数:

  1. get_open_orders(): 获取当前所有未完成(未成交、部成待撤等状态)的订单。
  2. cancel_order(order_param): 对指定的订单进行撤单操作。

实现逻辑

  1. 调用 get_open_orders() 获取一个包含所有未完成订单对象的列表。
  2. 遍历这个列表。
  3. 对列表中的每一个订单对象调用 cancel_order()

代码示例

以下是一个完整的策略示例代码。为了演示效果,我在 initialize 中设置了股票池,并定义了一个 cancel_all_open_orders 函数,你可以在 handle_data 或其他逻辑中调用它。

def initialize(context):
    # 初始化设置
    g.security = '600570.SS'
    set_universe(g.security)
    
    # 为了演示,这里设置一个定时任务,每天14:50执行撤单操作
    # 实际使用时,你可以根据自己的策略逻辑在任何地方调用撤单函数
    run_daily(context, cancel_all_open_orders, time='14:50')

def handle_data(context, data):
    # 示例:每个交易时刻尝试下单(为了产生挂单供测试撤单使用)
    # 实际策略中请根据你的逻辑下单
    # 下一个价格很低的买单,确保它不会立即成交,从而产生挂单
    current_price = data[g.security]['close']
    if current_price > 0:
        order(g.security, 100, limit_price=current_price * 0.9)

def cancel_all_open_orders(context):
    """
    自定义函数:获取所有未完成订单并撤销
    """
    # 1. 获取当前所有未完成的订单
    # 不传参数默认获取所有标的的未完成订单
    open_orders = get_open_orders()
    
    if not open_orders:
        log.info("当前没有未完成的挂单。")
        return

    log.info("检测到 %s 个未完成订单,开始执行撤单..." % len(open_orders))

    # 2. 遍历订单列表并逐个撤销
    for _order in open_orders:
        # 记录日志
        log.info("正在撤销订单 -> 订单号: %s, 标的: %s, 数量: %s" % (_order.order_id, _order.symbol, _order.amount))
        
        # 3. 执行撤单
        # cancel_order 既可以接收 order_id 字符串,也可以接收 Order 对象
        cancel_order(_order)

代码详解

  1. get_open_orders():

    • 该函数返回一个列表,列表中的每个元素都是一个 Order 对象。
    • 如果不传入 security 参数,它会返回账户下所有标的的未完成订单。
    • 如果只想撤销特定股票的订单,可以传入参数,例如 get_open_orders(security='600570.SS')
  2. 循环与撤单:

    • 使用 for 循环遍历 open_orders 列表。
    • cancel_order(_order):直接将订单对象传入即可完成撤单。也可以传入 _order.order_id
  3. 注意事项:

    • Python 版本兼容性: PTrade 环境通常基于 Python 3,但为了兼容性(特别是旧版 Python 3.5),代码中使用了 % 格式化字符串(如 "%s" % var),而不是 f-string。
    • 交易与回测: 该逻辑在回测和实盘交易中均适用。在实盘交易中,撤单指令发送到柜台可能有一点延迟,但在策略层面调用后即视为已发出撤单请求。
    • 撤单失败: 如果订单在撤单指令发出前刚好成交,撤单可能会失败(或提示无法撤单),这是正常现象。

Q&A

Q: get_open_ordersget_orders 有什么区别?
A: get_open_orders 只返回未完成(如未报、待报、已报、部成)的订单,即“挂单”。而 get_orders 返回当日所有状态的订单,包括已成交、已撤销和废单。撤单逻辑中应使用 get_open_orders

Q: 如果我只想撤销买单,保留卖单怎么办?
A: 你可以在遍历 open_orders 时判断订单的方向。Order 对象有一个 amount 属性,买入是正数,卖出是负数

for _order in get_open_orders():
    if _order.amount > 0: # 仅撤销买单
        cancel_order(_order)

Q: 撤单操作是同步的吗?
A: cancel_order 函数本身是异步发出的指令。调用后,订单状态不会立即变为“已撤”,而是先变为“已报待撤”。你需要等待交易所确认后,订单状态才会更新为“已撤”。