3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 QMT 平台中,get_trade_detail_data 接口默认会返回指定账号当天的所有委托明细。API 底层并没有直接提供 limit(限制条数)或 start_time/end_time(限制时间)的参数。
你遇到的“下午越来越慢”的问题,根本原因通常不是 get_trade_detail_data 获取数据慢,而是对 1000 多条历史委托(包括已成、已撤、废单)进行了无意义的遍历,并且频繁调用 can_cancel_order 导致了极大的性能开销。
为了实现高效的“超时 N 秒自动撤单”,你可以采用以下几种优化方案:
既然接口返回的是一个列表,且通常是按时间顺序追加的,你可以直接在 Python 层面截取最后 100 条数据进行遍历,避免遍历早上的历史订单。
order_list = get_trade_detail_data(ContextInfo.accid, 'STOCK', 'order')
# 只取最后 100 条委托
recent_orders = order_list[-100:]
绝大多数历史委托已经是“已成(56)”、“已撤(54)”或“废单(57)”,对它们调用 can_cancel_order 是毫无意义且耗时的。你应该在循环的第一步,直接过滤掉这些状态,只处理“未报(48)”、“待报(49)”、“已报(50)”和“部成(55)”的活跃订单。
对于高频/大量订单的策略,最专业的做法是不依赖全量查询,而是在下单时将订单号和时间记录在全局字典中,成交或撤单后将其剔除。这样你每次只需要遍历几个真正未成交的订单。
下面结合了状态过滤和时间比对的优化代码,能将十几秒的耗时降低到毫秒级:
import time
import datetime
def init(ContextInfo):
ContextInfo.accid = '你的资金账号'
ContextInfo.timeout_seconds = 60 # 设置超时时间 N = 60秒
def handlebar(ContextInfo):
# 1. 获取当天所有委托
order_list = get_trade_detail_data(ContextInfo.accid, 'STOCK', 'order')
# 2. 优化:如果订单量极大,可先切片取最近 200 条
if len(order_list) > 200:
order_list = order_list[-200:]
current_time = datetime.datetime.now()
for order in order_list:
# 3. 核心优化:只处理活跃状态的订单
# 48:未报, 49:待报, 50:已报, 51:已报待撤, 52:部成待撤, 53:部撤, 55:部成
# 如果是 54(已撤), 56(已成), 57(废单),直接跳过,极大地节省时间
if order.m_nOrderStatus in [54, 56, 57, 86, 255]:
continue
# 4. 解析订单时间 (m_strInsertTime 格式通常为 'HH:MM:SS')
try:
# 拼接当天的日期和订单时间
today_str = current_time.strftime('%Y-%m-%d')
order_time_str = f"{today_str} {order.m_strInsertTime}"
order_time = datetime.datetime.strptime(order_time_str, '%Y-%m-%d %H:%M:%S')
# 计算时间差
time_diff = (current_time - order_time).total_seconds()
# 5. 判断是否超时 N 秒
if time_diff > ContextInfo.timeout_seconds:
# 6. 确认可撤后执行撤单
if can_cancel_order(order.m_strOrderSysID, ContextInfo.accid, 'STOCK'):
cancel(order.m_strOrderSysID, ContextInfo.accid, 'STOCK', ContextInfo)
print(f"订单 {order.m_strOrderSysID} 超时 {time_diff} 秒,已发送撤单指令")
except Exception as e:
print(f"解析订单时间出错: {e}")
[-100:] 切片。order.m_nOrderStatus 过滤掉已成、已撤的单子,这是解决你循环耗时十几秒的最关键一步。can_cancel_order 内部有通信开销,只有在状态和时间都满足条件时,才去调用它。