Skip to content

撤单:先查单号再撤

这是工程记录。只演示怎么拿到委托号、怎么发撤。不写追价、不写买卖条件。不构成投资建议,不代操盘。

手册: cancelcancel-order

对照

QMTPTrade
查单get_trade_detail_data(..., 'ORDER') / get_last_order_idget_orders() / get_order(id)
cancel(orderId, accountId, accountType, C)cancel_order(order_id 或 Order)
返回bool,只表示「发出了撤」None
已成撤不掉,先看状态同上

cancel 返回 True 不等于柜台已经撤完。再查一次委托状态。

QMT:未成的单才撤

python
#coding:gbk
def init(C):
    C.acc = '你的资金账号'
    C.acct_type = 'STOCK'

def handlebar(C):
    if not C.is_last_bar():
        return
    orders = get_trade_detail_data(C.acc, C.acct_type, 'ORDER') or []
    for o in orders:
        oid = getattr(o, 'm_strOrderSysID', '') or getattr(o, 'm_strOrderID', '')
        status = str(getattr(o, 'm_nOrderStatus', ''))
        traded = int(getattr(o, 'm_nVolumeTraded', 0) or 0)
        total = int(getattr(o, 'm_nVolumeTotalOriginal', 0) or 0)
        print('order', oid, 'status', status, 'traded', traded, '/', total)
        if not oid:
            continue
        if traded >= total and total > 0:
            continue
        print('cancel', oid, cancel(oid, C.acc, C.acct_type, C))

账号类型要和开户一致:STOCK / CREDIT / FUTURE。填错就是 False。

PTrade:用 get_orders 取 id

python
def handle_data(context, data):
    bag = get_orders() or {}
    for oid, o in bag.items():
        log.info('id=%s sid=%s status=%s filled=%s', oid, getattr(o, 'sid', ''),
                 getattr(o, 'status', ''), getattr(o, 'filled', None))
        st = str(getattr(o, 'status', '')).lower()
        if 'fill' in st or 'cancel' in st or 'reject' in st:
            continue
        cancel_order(oid)
        log.info('after cancel %s', get_order(oid))

只演示「查到未完成 → 撤」。要不要撤、撤哪一笔,自己对账,不要写成追价循环。

  1. 编辑器里点运行,常常没有真实委托号,cancel 无意义。
  2. QMT 委托号用 m_strOrderSysID,和成交里是同一个字段。版本不同先 dir(obj)
  3. PTrade 回测日终会自动取消未完成单,和实盘不一样。
  4. 已经部成、已成、已拒的单再撤,柜台会拒,先过滤状态。

相关:API 查询 · 热门问题 · 关注 / 知识星球

完整讨论和附件在 知识星球 Kimi量化研究所