委托回报与状态管理
本章介绍 QMT 内置 Python 的委托回报机制和订单状态管理。
委托回报回调
order_callback
当委托状态发生变化时触发:
def order_callback(ContextInfo, order_info):
"""委托状态变化回调"""
print(f'委托回报: {order_info.m_strStockCode}')
print(f' 方向: {"买入" if order_info.m_nOrderType == 1 else "卖出"}')
print(f' 数量: {order_info.m_nVolume}')
print(f' 价格: {order_info.m_dPrice}')
print(f' 状态: {order_info.m_nOrderStatus}')
print(f' 委托号: {order_info.m_strOrderSysID}')
deal_callback
当委托成交时触发:
def deal_callback(ContextInfo, deal_info):
"""成交通知回调"""
print(f'成交回报: {deal_info.m_strStockCode}')
print(f' 方向: {"买入" if deal_info.m_nOrderType == 1 else "卖出"}')
print(f' 成交数量: {deal_info.m_nVolume}')
print(f' 成交价格: {deal_info.m_dPrice}')
print(f' 成交编号: {deal_info.m_strTradeID}')
订单状态详解
状态流转
委托提交 → 已确认 → 部分成交 → 全部成交
→ 已撤销
→ 部分成交 + 部分撤销
状态码对照表
| 状态码 | 常量名 | 说明 |
|---|---|---|
| 50 | ORDER_SUBMITTED | 委托已提交 |
| 55 | ORDER_CONFIRMED | 委托已确认 |
| 56 | ORDER_PARTIALLY_FILLED | 部分成交 |
| 57 | ORDER_FILLED | 全部成交 |
| 58 | ORDER_CANCELLED | 已撤销 |
| 59 | ORDER_PARTIALLY_CANCELLED | 部分撤销 |
状态判断
def order_callback(ContextInfo, order_info):
status = order_info.m_nOrderStatus
if status == 57:
print(f'订单全部成交: {order_info.m_strStockCode}')
# 更新持仓记录
update_position(ContextInfo, order_info)
elif status == 56:
print(f'订单部分成交: {order_info.m_strStockCode}')
# 记录部分成交
record_partial_fill(ContextInfo, order_info)
elif status == 58:
print(f'订单已撤销: {order_info.m_strStockCode}')
# 清理未成交记录
cleanup_pending_order(ContextInfo, order_info)
订单信息对象
order_info 字段
| 字段 | 类型 | 说明 |
|---|---|---|
m_strStockCode |
str | 品种代码 |
m_nOrderType |
int | 委托类型(1=买, 2=卖) |
m_nVolume |
int | 委托数量 |
m_dPrice |
float | 委托价格 |
m_nOrderStatus |
int | 委托状态 |
m_strOrderSysID |
str | 委托编号 |
m_nTradedVolume |
int | 已成交数量 |
m_dTradedAmount |
float | 已成交金额 |
deal_info 字段
| 字段 | 类型 | 说明 |
|---|---|---|
m_strStockCode |
str | 品种代码 |
m_nOrderType |
int | 委托类型 |
m_nVolume |
int | 成交数量 |
m_dPrice |
float | 成交价格 |
m_strTradeID |
str | 成交编号 |
m_strOrderSysID |
str | 关联委托编号 |
订单管理策略
订单跟踪
def init(ContextInfo):
# 订单跟踪字典
ContextInfo.pending_orders = {} # order_id -> order_info
ContextInfo.filled_orders = [] # 已完成订单列表
def handlebar(ContextInfo):
if not ContextInfo.is_last_bar():
return
# 检查超时未成交订单
check_pending_orders(ContextInfo)
def order_callback(ContextInfo, order_info):
order_id = order_info.m_strOrderSysID
if order_info.m_nOrderStatus in [57, 58, 59]:
# 订单结束(全部成交/已撤/部分撤)
if order_id in ContextInfo.pending_orders:
del ContextInfo.pending_orders[order_id]
ContextInfo.filled_orders.append(order_info)
else:
# 更新订单状态
ContextInfo.pending_orders[order_id] = order_info
def check_pending_orders(ContextInfo):
"""检查超时未成交订单"""
from datetime import datetime, timedelta
now = datetime.now()
for order_id, order in list(ContextInfo.pending_orders.items()):
# 超时 5 分钟未成交则撤单
if hasattr(order, 'submit_time'):
elapsed = now - order.submit_time
if elapsed > timedelta(minutes=5):
ContextInfo.cancel(order_id, ContextInfo)
print(f'超时撤单: {order_id}')
防止重复下单
def safe_order(ContextInfo, stock, volume, price, order_type=1):
"""安全下单,防止重复"""
# 检查是否已有该品种的未成交订单
for order_id, order in ContextInfo.pending_orders.items():
if order.m_strStockCode == stock:
print(f'{stock} 已有未成交订单,跳过')
return None
# 下单
order_id = ContextInfo.order_volume(
stockcode=stock,
volume=volume,
priceType=11,
price=price,
orderType=order_type,
ContextInfo=ContextInfo,
)
if order_id:
ContextInfo.pending_orders[order_id] = {
'm_strStockCode': stock,
'submit_time': datetime.now(),
}
return order_id
错误处理
常见委托错误
def order_callback(ContextInfo, order_info):
status = order_info.m_nOrderStatus
if status == 50 and order_info.m_strErrorInfo:
# 委托被拒绝
print(f'委托被拒绝: {order_info.m_strErrorInfo}')
handle_rejection(ContextInfo, order_info)
def handle_rejection(ContextInfo, order_info):
"""处理委托被拒绝"""
error = order_info.m_strErrorInfo
if '资金不足' in error:
print('错误:资金不足,请减少委托数量')
elif '权限' in error:
print('错误:交易权限不足')
elif '涨跌停' in error:
print('错误:触及涨跌停限制')
else:
print(f'未知错误: {error}')
技巧
在模拟环境中充分测试委托回报处理逻辑,确保各种状态都能正确处理后再用于实盘。