3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
on_trade_response(成交主推回调函数)来处理订单成交后的逻辑。然而,部分开发者发现该函数在某些情况下会神秘失效。这实际上与 Ptrade 底层对 entrust_no(委托编号)的处理机制有关。\n\n### 1. Bug 的核心原因:entrust_no 跨日重复\n\n* 什么是 entrust_no?\n entrust_no 是营业部柜台生成的下单编号(例如 100001)。在同一个交易日内,这个编号是绝对唯一且不重复的。\n* Ptrade 的回调机制缺陷\n Ptrade 的底层引擎在触发 on_trade_response 时,会记录并依赖这个 entrust_no。如果系统检测到某个 entrust_no 已经触发过成交回调,为了防止重复推送,它可能会忽略后续相同编号的推送。\n* 触发 Bug 的场景\n entrust_no 仅在单日内唯一,第二天柜台的编号会重置。如果你的 Ptrade 策略跨日连续运行(没有重启),且第二天的某个订单碰巧分配到了与昨天(或之前某天)相同的 entrust_no,Ptrade 引擎会误认为这是一笔“已经处理过的旧订单”,从而拒绝触发 on_trade_response。\n\n### 2. 解决方案与规避建议\n\n既然这是一个底层机制导致的“天坑”,在官方修复此 Bug 之前,量化开发者可以通过以下几种方式进行规避:\n\n#### 方案一:每日定时重启策略(最推荐)\n这是最简单且最彻底的规避方法。由于 Bug 的触发前提是“策略跨日连续运行导致内存中缓存了历史的 entrust_no”,只要每天盘前重启策略,引擎的缓存就会被清空。\n* 操作建议:在券商服务器或本地客户端中,设置每日盘后或盘前(如 8:30)自动重启 Ptrade 客户端及策略。\n* 注意:重启时请配合 pickle 模块做好全局变量 g 的持久化保存,以免丢失持仓或状态数据。\n\n#### 方案二:降级使用主动轮询机制 (get_trades)\n如果你的策略不能重启,或者对毫秒级延迟要求不是极高,可以放弃使用主推回调,改用主动查询。\n* 实现方式:在 handle_data 或 run_interval 中,定时调用 get_trades() 接口获取当日成交记录。\n* 代码示例:\npython\ndef run_interval_func(context):\n trades = get_trades()\n if trades:\n # 遍历并处理未处理的成交记录\n pass\n\n\n#### 方案三:依赖 order_id 而非 entrust_no\n在 Ptrade 中,order_id 是由 Ptrade 引擎生成的 UUID(如 e71d1684c8a74b4ca00b3326c9eb8614),它是全局唯一的,永远不会重复。\n* 虽然主推回调可能不触发,但你可以通过 get_orders() 或 get_open_orders() 轮询订单状态,通过比对 order_id 的 status 字段(如状态变为 '8' 已成)来判断订单是否成交。\n\n### 总结\nPtrade 的 on_trade_response 跨日失效是一个典型的状态缓存未清理导致的 Bug。在编写实盘策略时,强烈建议养成每日重启交易环境的习惯,这不仅能规避 entrust_no 重复的问题,还能有效释放内存,保持策略运行的稳定性。