3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在使用联储证券 QMT(通过 Python 原生连接 miniqmt)时,盘中出现 subscribe_whole_quote 行情推送中断是一个比较常见的问题。底层通信确实是基于 RPC(Remote Procedure Call)的。
subscribe_whole_quote 会推送全市场的数据,盘中行情剧烈波动时,瞬间的数据吞吐量极大。如果 Python 端的 callback 回调函数处理逻辑过重(如进行了复杂的计算、写文件或数据库操作),会导致底层接收队列阻塞,最终触发 RPC 缓冲区溢出或超时断开。要解决这个问题,最有效的方法是在 Python 代码中实现心跳检测(Watchdog)机制。基本思路是:记录最后一次收到行情数据的时间,如果超过一定时间(例如 10 秒)没有收到任何数据,则认为连接已断开,主动执行退订并重新订阅。
import time
import threading
from xtquant import xtdata
class QuoteManager:
def __init__(self):
self.last_receive_time = time.time()
self.sub_id = None
self.is_running = True
self.timeout_threshold = 10 # 10秒未收到数据认为断线
def on_quote_callback(self, data):
# 1. 更新最后接收时间
self.last_receive_time = time.time()
# 2. 处理行情数据(注意:回调函数内一定要轻量,不要做耗时操作!)
# 如果有复杂逻辑,建议放入队列(queue),由其他线程异步处理
# print("收到行情:", data)
def subscribe(self):
print("开始订阅全市场行情...")
# 假设订阅全市场沪深A股
self.sub_id = xtdata.subscribe_whole_quote(['SH', 'SZ'], callback=self.on_quote_callback)
self.last_receive_time = time.time()
def unsubscribe(self):
if self.sub_id is not None:
print("取消订阅...")
xtdata.unsubscribe_quote(self.sub_id)
self.sub_id = None
def watchdog_loop(self):
while self.is_running:
time.sleep(3)
# 检查当前时间与最后接收时间的差值
if time.time() - self.last_receive_time > self.timeout_threshold:
print(f"警告:超过 {self.timeout_threshold} 秒未收到行情,触发自愈重连机制!")
self.unsubscribe()
time.sleep(1) # 稍微等待底层释放资源
self.subscribe()
def start(self):
self.subscribe()
# 启动看门狗线程
self.watchdog_thread = threading.Thread(target=self.watchdog_loop, daemon=True)
self.watchdog_thread.start()
def stop(self):
self.is_running = False
self.unsubscribe()
# 使用示例
if __name__ == '__main__':
manager = QuoteManager()
manager.start()
try:
# 保持主线程运行
while True:
time.sleep(1)
except KeyboardInterrupt:
manager.stop()
callback 中进行耗时的 IO 操作(如写数据库、复杂计算)。建议将收到的数据直接 put 到 queue.Queue 中,由另外的消费者线程去处理。subscribe_quote 传入具体的股票列表,而不是使用 subscribe_whole_quote。这能极大降低底层 RPC 的压力,显著减少断线概率。