问题描述
算法交易中撤单和补单的时间规则是什么?
解决方案
在算法交易中,撤单和补单(简称“撤补”)是控制交易滑点、提高成交率的重要手段。在 ptrade 量化平台中,撤补操作不仅需要调用相应的 API,还必须严格遵守交易所的时间规则。
一、 撤单与补单的时间规则(基于A股市场机制)
在 ptrade 中执行撤单操作,本质上是向交易所发送撤单指令,因此必须符合沪深交易所的交易时间规定:
- 早盘集合竞价阶段:
- 09:15 - 09:20:可以接收申报,也可以接收撤单申报。此阶段可以进行撤补操作。
- 09:20 - 09:25:可以接收申报,但不接收撤单申报。此阶段调用撤单 API 会被交易所拒绝(废单)。
- 连续竞价阶段:
- 09:30 - 11:30 及 13:00 - 14:57:正常交易时间,随时可以进行撤单和补单操作。
- 尾盘集合竞价阶段(深市及科创板/创业板):
- 14:57 - 15:00:不接收撤单申报。此阶段无法撤单。
- 盘后固定价格交易阶段(科创板/创业板):
- 15:05 - 15:30:可以撤销未成交的盘后固定价格委托。ptrade 提供了专门的
after_trading_cancel_order接口用于盘后撤单。
- 15:05 - 15:30:可以撤销未成交的盘后固定价格委托。ptrade 提供了专门的
注意:在 ptrade 的回测环境中,每天结束时(15:00)系统会自动取消所有未完成的交易订单。
二、 ptrade 中实现撤补的核心 API
实现撤补逻辑通常需要以下三个步骤:
- 查询未成交订单:使用
get_open_orders(security)获取当前挂在盘口未完全成交的订单列表。 - 执行撤单:使用
cancel_order(order_id)对指定的未成交订单发起撤单请求。 - 重新补单:撤单成功后(可通过
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}")
四、 进阶建议
- 使用主推事件加速撤补:对于对速度要求极高的算法交易(如 Tick 级别),建议使用
on_order_response和on_trade_response事件来监听订单状态变化,而不是在handle_data中轮询get_open_orders,这样可以大幅降低撤补延迟。 - 防范重复下单:在执行补单前,务必确认撤单指令已经生效(订单状态变为 '5' 部撤 或 '6' 已撤),否则可能导致双重下单,超出资金或仓位限制。