尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

QMT与聚宽策略对接实战:基于Redis的信号中转与xtquant下单

发布时间:2026/9/18 7:40:54

资讯中心
01
ARTICLE

QMT与聚宽策略对接实战:基于Redis的信号中转与xtquant下单

QMT与聚宽策略对接实战:基于Redis的信号中转与xtquant下单
搞量化的人多多少少都会遇到一个坎回测跑得好好的策略一上实盘就跟换了个脑子似的。更尴尬的是有些人习惯在聚宽上研究策略模型、因子、历史回测都挺顺手但真要落地实盘下单又绕不开QMT这种能把交易指令直接怼进券商柜台的工具。于是就有了这篇文章的起点QMT与聚宽策略代码对接实战核心是靠Redis做信号中转站用xtquant这个Python接口在QMT侧执行交易。这套东西解决的不只是“信号怎么从A传到B”的问题更是一整套异构系统之间的解耦、状态管理、异常兜底的工程问题。如果你是那种策略逻辑已经成型、想在聚宽和QMT之间搭一座“桥”的人或者你只是听别人说过xtquant但不知道怎么跟自己的策略接起来这篇文章应该能帮上忙。我会把整个对接思路、数据结构设计、代码骨架、以及我踩过的坑全写出来尽量让没有接触过这块的读者也能照着搭一套能跑的通路。1. 项目背景与整体架构1.1 为什么非要“曲线救国”聚宽和QMT各自的分工先说清楚聚宽和QMT到底各干各的什么活。聚宽JoinQuant本质是一个量化的研究、回测、模拟交易平台它的强项在于数据丰富、研究便捷、因子库和策略库都现成而且有网页端的Notebook环境适合快速验证思路。你在聚宽上写策略会感觉特别顺手因为很多数据处理函数、财务因子、行业分类、指数成分股这些都是封装好的。但问题是聚宽并不是一个“实盘交易终端”。它能够把策略研究做得很舒服但要实现真正的券商账户下单聚宽本身的能力是受限的。这里的“受限”不是说聚宽没有模拟盘或者没有接口而是对于有特定交易需求、需要直接操作自己账户、需要精细到撤单改单、需要特殊交易品种的人群来说QMT迅投QMT极速策略交易系统那种贴近柜台的方式更直接、更灵活。QMT是券商提供的一种行情和交易终端它把行情推送、交易通道、策略运行整合到一起。而且QMT开放了Python接口也就是我们常说的xtquant。xtquant可以让你的Python代码直接连接QMT客户端完成行情订阅、查询账户、下单、撤单、查看持仓、接收成交回报这些操作。可以说xtquant是QMT对量化玩家开放的一扇门。那为什么不能直接在聚宽上调用xtquant因为聚宽的策略运行环境在云端跟你本地的QMT终端不在同一个网络环境更不在同一个进程里。你既不能在聚宽里连上你本地的QMT也没法让QMT直接跑聚宽的代码。两边像是两座孤岛中间没有任何直通桥。所以要实盘落地通常就得分两半聚宽负责“想”策略计算QMT负责“做”交易执行中间得有一个“传话筒”把聚宽想好的信号递给QMT。1.2 为什么选Redis做“传话筒”而不是别的方案有人会问既然只是传信号能用文件吗能用数据库吗能直接发微信消息吗这些其实都有人试过但各有各的坑文件传参比如JSON文件逻辑最简单但跨机器、跨网络就很麻烦而且要注意文件锁、读写冲突、清理问题。如果聚宽在云端、QMT在本地文件方案基本没法用除非再引入同步盘那又是一套复杂度。MySQL/PostgreSQL能存能查但为了传几个信号起一个数据库服务稍微重了点而且高频轮询数据库的效率和延迟也不够理想。HTTP接口Flask/FastAPI起个服务这个靠谱适合有编程基础的人但你需要自己管服务、管网络、管鉴权。对于只想把策略落地的人来说写一堆Web服务代码反而是负担。Redis轻量快数据结构丰富字符串、哈希、列表、发布订阅都能用而且它天然就是个“中间层”。聚宽把信号写进RedisQMT从Redis读信号两边都只需要关心跟Redis的读写不需要关心对方在哪儿、用的什么语言。这种松耦合的方式正是对接异构系统时最省心的方案。所以我最终定了Redis。它足够简单同时又能处理“信号传递”这个场景。你要是在本机跑Redis装Windows版或者用Docker起一个都行你要是在多台机器之间传递只要配置好网络和访问密码Redis也能很轻松地搞定。1.3 整体流程从聚宽策略信号到QMT下单中间发生了什么为了方便理解我把整套流程画成一个流水线不用图我用文字描述聚宽策略在设定的时间点运行通过jqdata获取行情数据、因子数据按策略逻辑判断今天该买什么、卖什么、用多少仓位。聚宽计算出信号之后把信号包装成结构化的数据比如包含股票代码、操作方向、目标仓位、价格类型、策略标识、时间戳然后用Redis客户端把这段数据写入Redis指定key。QMT侧的本地Python程序基于xtquant启动它循环地、或者在收到Redis通知后去读取指定key的数据。QMT程序解析信号调用xtquant下单接口把信号翻译成真实的交易指令。交易指令提交后QMT程序监听成交回报把订单状态再写回Redis供聚宽侧或者人眼监控。这个流程说白了就是一个“生产者-消费者”模型。聚宽是生产者QMT程序是消费者Redis之间就是一个消息队列/信号邮箱。接下来我从架构、数据设计、代码实现一层层拆开讲。2. 环境准备把地基打牢2.1 QMT终端与xtquant的版本坑很多人第一次接触xtquant会懵因为下载到的QMT终端里不一定直接带xtquant。你需要确认你的QMT客户端是支持Python交易的版本一般在行情界面里会有“模型交易”之类的入口。同时你需要在QMT安装目录下找到类似bin.x64\Lib\site-packages\xtquant这样的路径里面放着xttrader.py、xtdata.py、xttype.py这些核心文件。我的建议是不要自己去造xtquant的轮子直接把QMT安装目录里的xtquant整个文件夹拷贝到你自己的Python项目里。比如你的项目路径是D:\quant_project\你就在这个目录下建一个xtquant文件夹把这个包塞进去。为什么要这样做因为QMT终端更新频率不低它自带的xtquant和客户端版本是匹配的你从网上随便pip安装某个版本的xtquant很容易出现客户端和接口版本对不上、连不上的情况。还有个小细节xtquant是基于Python 3.7/3.8左右的版本时代写出来的如果你本地用的是Python 3.10甚至3.12很可能会碰到一些兼容性报错比如某些依赖库装不上。实测下来用Python 3.8或者3.9跑xtquant是最稳的别在版本上硬刚。2.2 Redis安装本机跑还是Docker怎么选Redis的安装其实很无脑但很多人卡在Windows上因为Redis官方其实不太维护Windows原生版本。你有两条路Windows直接装去下载Microsoft维护的Redis for Windows版本或者用tporadowski/redis这个开源项目装完就能当服务跑。优点是省事缺点是版本老功能上够用但你要用的什么Stream、Lua脚本高级特性可能会受限。Docker跑Redis如果你电脑装了Docker Desktop跑一条命令docker run -d -p 6379:6379 --name redis -v redis-data:/data redis:7.0就能起一个干净、版本新的Redis。这种方式更贴近生产环境以后要加主从、加哨兵、加Redis Cluster都方便而且配置文件也容易挂载进来。个人建议如果你只是本机调试怎么跑都行如果你准备长期跑实盘建议直接Docker起一个固定版本的Redis把数据目录通过Volume挂载到宿主机方便备份恢复。别小看Redis的持久化虽然它是个缓存数据库但你的交易信号如果因为Redis重启丢了那晚上自动交易可能就静默罢工了。另外强烈推荐装一个可视化管理工具比如Another Redis Desktop Manager很多人也叫它RedisDesktopManager。写Redis、查Redis、看超时时间、删key这些操作有图形界面比命令行效率高很多。特别是排查问题的时候你能一眼看到当前的key长什么样值是什么有没有过期时间。2.3 Python依赖清单redis-py、pandas、jqdata这些不能缺对接程序用到的主要Python库如下redisPython的Redis客户端官方推荐这个库pip install redis即可。pandas聚宽信号处理过程中DataFrame是标配几乎绕不开。jqdata聚宽的Python数据库接口用来拉行情、财务数据。注意jqdata库在本地安装需要作者授权如果你是在聚宽云端写策略那就不用管这个库直接用聚宽平台封装的函数即可。xtquant从QMT目录拷贝过来的本地包用来连接QMT。schedule或APScheduler如果在本地做定时轮询或者定时任务可以选一个。依赖的真正常见坑是redis-py和Redis服务端版本不匹配。比如Redis服务端是5.xredis-py太新或者太旧都可能出现语法报错。好在redis-py兼容性还不错但如果你在代码里用了decode_responsesTrue一定要确认取出来的值是字符串而不是bytes不然序列化数据反序列化时容易出错。3. 核心设计Redis信号的数据结构与状态机3.1 Key的命名规范别用裸字符串更别把信号全塞一个Key很多第一次搞对接的人习惯用一个key比如signal:1然后把所有信号打包成一个JSON数组直接写进去。这在信号量少的时候没问题但一旦策略多了、股票多了、信号类型复杂了你就等着各种覆盖吧。我的设计思路是一个key对应一笔信号或一种信号类型key用层级命名冒号分隔。比如strategy:signal:list这是信号的列表key用Redis的List结构里面按顺序push信号数据。strategy:signal:{stock_code}如果你是根据股票维度处理信号可以给每只股票单独存一个key互相不干扰。strategy:order:{order_id}订单状态存放某个订单的实时状态包括委托价、委托量、成交价、成交量、状态等。strategy:account:xxx账户相关的持久化信息。另外一定要给key设置过期时间TTL。比如信号这个key我一般设24小时或者48小时过期以防止信号堆积。因为信号是时效性的如果当天没有处理掉第二天再读到昨天的信号就是灾难。3.2 信号值用什么序列化JSON还是pickle这是我自己踩过最惨的一次坑第一次写对接的时候图省事用pickle直接序列化聚宽传出来的DataFrame里面一堆浮点数、字符串、还有重复索引当时在本地测试一切正常。结果换到另一台电脑读Redis数据反序列化直接报错。原因很简单pickle是Python私有协议跨版本、跨机器、跨Python解释器都可能出问题。所以信号传递的序列化我最终全部改成JSON。有人会担心JSON序列化DataFrame太复杂其实没那么麻烦。聚宽计算完信号之后把DataFrame转换成list of dict挑出关键字段用json.dumps()序列化成一个字符串这个字符串作为Redis的信号value读出来之后再用json.loads()解析回dict。整个过程干净、可读、跨语言通用调试时你甚至能在Redis Desktop Manager里直接看到中文内容。3.3 状态机设计信号不只是“买”和“卖”信号如果只设计成“买”“卖”两个字那实盘肯定要出问题。因为一笔信号从产生到最终执行可能要经历“已发送”“已收到”“已下单”“部分成交”“全部成交”“已撤销”“失败”这几种状态。所以我给每个信号增加了一个状态字段并用状态机管理它的生命周期。我的状态流转是这样的PENDING信号已写入Redis等待QMT程序消费。RECEIVEDQMT程序读取到信号并已开始处理。ORDER_SUBMITTED已经调用xtquant提交了委托单。PARTIAL_FILLED部分成交还挂着单。FILLED全部成交信号完成。CANCELED被撤销了。FAILED下单失败可能是资金不足、停牌、涨跌停、接口异常等。为什么要维护这么多状态因为你在实盘里必须知道自己每一笔信号到底走到哪一步了。你总不能看到“卖出信号”发出去就放心睡觉吧万一xtquant下单失败信号丢在半路你第二天起来发现仓位没动那就不是少赚几个点的问题了是系统性风险。实际操作中我还会额外加一个version字段。因为聚宽策略可能会重复推送同一笔信号比如因为网络问题或者策略重复执行有了version消费者就可以做幂等处理——重复信号直接跳过避免重复下单。4. 聚宽侧信号生产策略代码怎么和Redis衔接4.1 从聚宽策略里取信号拼成结构化数据在聚宽侧你的策略代码大概率是一个initialize(context)加handle_data(context, data)的结构。信号计算的逻辑每个人不一样但最终你会发现无论策略多复杂给下游的输出始终是有限的几个字段。我一般会在聚宽侧定义这样一个统一的信号字典{ strategy_name: my_first_strategy, signal_id: 20250301140500_600519, timestamp: 2025-03-01 14:05:00, stock_code: 600519.XSHG, action: buy, # buy / sell / hold target_position: 0.2, # 目标仓位比例 order_type: limit, # limit / market limit_price: 1710.50, # 如果是限价单指定价格 version: 1 }这个字典是聚宽策略和QMT对接的“协议”两边都必须遵守同样的字段定义。建议用注释把这个协议写清楚不然过两个月你自己都会忘。4.2 聚宽推送信号到Redis的三种姿势在聚宽环境里写Redis推送主要有三种方式取决于你的策略怎么部署的第一种在聚宽Notebook里手动执行你可以在聚宽的研究环境里用一行jqdata拉数据然后用你的策略脚本算好信号再调用Redis客户端把信号推送到本地Redis。这种方式适合半自动的场景——人肉跑策略机器负责执行。第二种在聚宽的模拟交易里设置Webhook触发有些平台支持Webhook之类的机制或者你写一个定时任务从聚宽的数据API拉数据凑成信号。不过聚宽的云环境和本地Redis怎么打通是个需要动脑筋的事。比较实用的做法是聚宽侧只负责把信号结果推到一个公网可以访问的中间服务比如一个简单的HTTP API然后本地服务去拉取。但如果你不想引入太多中间层用Redis本身做公共中转也行——前提是你的Redis暴露给了聚宽可以访问的地址并且做好了密码保护和IP白名单。第三种在本地跑聚宽的Python环境如果你已经装了jqdata库并且本地Python环境也能登录聚宽的权限那你完全可以把聚宽策略搬到本地跑。这样聚宽策略和Redis就在同一台机器上推送信号再简单不过。这种方式的优点是调试方便实盘速度快缺点是需要自己维护数据获取、权限控制、定时调度。我用得最多的是第三种。因为本身QMT就在本地聚宽策略在本地跑信号直接就进了本地Redis延迟最低出问题也最快能定位。4.3 聚宽侧Redis推送代码示例这里给个简洁版的推送示例。假设你已经在本地搭好Redis安装好了redis这个Python库。import json import redis import datetime REDIS_HOST 127.0.0.1 REDIS_PORT 6379 REDIS_PASSWORD your_password r redis.Redis( hostREDIS_HOST, portREDIS_PORT, passwordREDIS_PASSWORD, decode_responsesTrue ) def push_signal(signal_dict: dict): key fstrategy:signal:{signal_dict[stock_code]} signal_json json.dumps(signal_dict, ensure_asciiFalse) r.rpush(key, signal_json) r.expire(key, 86400) print(f[{datetime.datetime.now()}] 信号已推送 - {key} - {signal_dict[stock_code]})rpush用的是列表的push操作这样同一个股票的多个信号会按照时间顺序排队下游消费的时候用lpop/blpop或者lindex读取即可数据结构天然是FIFO比较契合信号流的场景。4.4 防止信号重复推送Redis分布式锁的巧妙用法聚宽策略可能被重复触发比如定时任务重叠、手动误触、网络重试都可能导致同一个信号被推送两次。要防止这个问题除了在信号里携带version字段做幂等外还可以用Redis的SETNX命令实现一个简单的分布式锁。比如在推送信号前先尝试设置一个带过期时间的锁lock_key fstrategy:lock:{stock_code}:{signal_id} locked r.set(lock_key, 1, nxTrue, ex60) if not locked: # 说明这个信号已经推送过了 return # 执行推送逻辑 push_signal(signal_dict)这个锁的效果是同一只股票、同一信号ID在60秒内只能推送一次。实际中这个场景非常常见因为你不可能完全控制策略执行器只跑一次但只要加上这个锁就能很大程度上避免重复下单。5. QMT侧消费落地用xtquant把信号变成真实委托5.1 初始化xtquant连接QMT客户端处理client is nullQMT这边的核心是xtquant。你用xtquant之前首先要保证本地QMT客户端已经登录并且开启了极速交易模式。然后你的Python程序里需要创建一个XtQuantTrader实例并启动交易回调。很多新人第一次跑xtquant都会撞上一个神秘报错client is null。这个报错看起来像是网络问题、连接问题其实大多数情况下是因为QMT客户端没有正常启动极速交易或者你的xtquant版本和客户端版本不匹配。我在网上搜的时候看不少人说更新客户端就能解决但实测下来最稳妥的办法是确认QMT已经用正确的账号登录进入的是“极速交易”界面。在QMT的配置里找到类似“Python环境”的选项指定你的Python解释器路径。在代码里连接时传入正确的QMT路径这个路径就是QMT安装目录下的userdata_mini路径每个人的机器不一样。用session_id区分不同会话避免连接冲突。初始化代码大致长这样from xtquant import xttrader, xtconstant from xtquant.xttype import StockAccount # QMT安装目录的userdata路径一般形如 C:/Users/xxx/AppData/Roaming/迅投QMT/... qmt_userdata_path C:/qmt/userdata_mini session_id int(datetime.now().strftime(%Y%m%d%H%M%S)) trader xttrader.XtQuantTrader(qmt_userdata_path, session_id) trader.start() trader.connect() # 如果连接成功再创建资金账号 acc StockAccount(你的资金账号, STOCK)connect()调用之后并不是立即就连接好了有些情况下需要一个短暂等待。你可以循环检查trader.get_asset(acc)是否能返回有效的资产信息来确定连接是否成功。5.2 轮询Redis怎么避免漏信号和高频空转在QMT侧消费信号最简单的方案是循环轮询Redis。但是轮询有个矛盾轮询频率太高Redis压力大CPU跑满轮询频率太低信号响应不及时。我的做法是以1秒为间隔轮询Redis同时利用Redis的BLPOP阻塞读取。BLPOP是一个阻塞式弹出命令如果没有数据它会一直等着直到有数据或者超时。这样既不会空转也不会因为轮询间隔太长而错过信号。伪代码如下import json import redis import threading from xtquant import xttrader r redis.Redis(host127.0.0.1, port6379, passwordxxx, decode_responsesTrue) def consume_signal(): while True: # 从Redis列表中阻塞地取出一个信号超时30秒 result r.blpop(strategy:signal:list, timeout30) if result is None: continue key, signal_json result signal json.loads(signal_json) handle_signal(signal)这个方式有一个小问题如果你把同一个股票的多个信号按stock_code分别存了多个key那么不能简单BLPOP一个key。这时候你可以统一用一个信号queue key比如strategy:signal:list所有股票的信号都进同一个队列消费者取出来之后自己判断股票代码。如果你要按股票维度并发处理那就多起几个消费者线程每个线程负责一组股票代码。5.3 调用xtquant下单订单参数详解与下单代码示例拿到信号后下一步就是调用xtquant的order_stock下单。xtquant的下单接口和很多券商的Python API大同小异核心是这几个accountStockAccount对象里面是资金账号信息。stock_code股票代码注意是类似600519.SH这种格式需要从聚宽的600519.XSHG做一次格式转换。order_type下单类型比如xtconstant.STOCK_BUY或者xtconstant.STOCK_SELL。order_volume委托数量A股必须按100股整数倍科创板按200股整数倍起步超过200股可以1股递增。price_type定价方式xtconstant.FIX_PRICE表示限价单xtconstant.LATEST_PRICE表示最新价。price委托价格。strategy_name/order_remark备注信息方便追踪。一个非常容易踩的坑是数量换算。聚宽侧算出来的信号是目标仓位比例比如target_position0.2表示想买20%仓位但你到xtquant下单必须把它换算成具体的股数。换算逻辑是# 假设你已经获取了账户总资产 total_asset # 当前股价 price target_value total_asset * target_position target_volume int(target_value / (price * 100)) * 100这里我直接按手取整因为A股股票交易最低100股多出来的零头我通常会放弃防止超买。如果信号是加仓或者减仓你还需要结合当前持仓来计算实际委托量。下单示例def place_order(trader, account, signal): stock_code signal[stock_code].replace(XSHG, SH).replace(XSHE, SZ) action signal[action] if action buy: order_type xtconstant.STOCK_BUY elif action sell: order_type xtconstant.STOCK_SELL else: return None # 假设price已经根据最新价或者信号指定价获得 price signal.get(limit_price, 0) # 0表示市价? 实际要小心 volume signal[target_position] # 实际得换算 order_id trader.order_stock( account, stock_code, order_type, volume, xtconstant.FIX_PRICE, price, strategy_name, signal_remark ) return order_id5.4 成交回报与状态回写让聚宽侧知道到底成交没有下单之后不能拍屁股就走。你需要用xtquant的回调机制监听订单状态和成交回报。xtquant里你要继承一个类类似XtQuantTraderCallback然后实现on_order_status和on_trade_response方法。回调里面拿到订单状态之后我建议第一时间把状态写回Redis同时做一个本地日志记录。这样你在聚宽侧或者监控面板上就能实时看到订单的推进情况。写回Redis的时候就用到前面说的状态机设计。class MyCallback(xttrader.XtQuantTraderCallback): def on_order_status(self, order): # order里包含order_id, order_status, traded_volume等信息 status_dict { order_id: order.order_id, stock_code: order.stock_code, order_status: order.order_status, traded_volume: order.traded_volume, total_volume: order.total_volume, price: order.price, timestamp: datetime.now().strftime(%Y-%m-%d %H:%M:%S) } r.hset(strategy:order: str(order.order_id), mappingstatus_dict) def on_trade_response(self, trade): # 成交回报可以更新持仓、更新信号状态等 pass如果你把回调也跑起来了那整套闭环基本就完整了聚宽产生信号 - Redis中转 - QMT消费下单 - 回调回报 - 状态回写Redis。你甚至可以在聚宽侧写一个监控函数定期去看看strategy:order:*这些key看看哪些订单还卡在中间状态。6. 常见问题与排查技巧实录6.1 Redis连接常见问题Timeout、拒绝连接、密码认证失败connection refused多半是Redis没启动或者端口不对。用redis-cli -h 127.0.0.1 -p 6379 ping测一下有没有返回PONG。NOAUTH Authentication required没有输入密码。检查password参数或者看redis.windows.conf/redis.conf里requirepass配置。Timeout跨网络访问Redis常见检查防火墙和网络安全组或者确认Redis的bind配置是不是只绑定了localhost。内存被打爆信号key堆积太多又没有设置过期时间。解决办法是给信号key统一加expire同时定期用redis-cli info memory查看内存使用情况。6.2 xtquant常见问题排查把client is null这种神级报错展开讲讲。说实话这个报错出现的时候很容易让人心态爆炸因为表面上看起来是连接丢失其实可能的原因包括QMT客户端没登录或者登录过期。QMT端口的Python服务没有启动。xtquant包版本与QMT客户端版本不一致。你传入的userdata_mini路径不对连接时定位不到客户端。多开户多账号时资金账号选错。排查的时候先用最简单的方式打开QMT终端确认能看到交易界面再用trader.connect()后检查返回值如果connect()返回0说明连接成功返回非0就要逐步排查上述原因。还有一个小技巧别在同一个Python进程里重复创建多个XtQuantTrader实例这也会导致连接状态错乱。全局维护一个trader实例就可以了。6.3 策略信号有延迟怎么优化链路响应速度如果你发现一段信号从聚宽出来到QMT下单中间要隔上十几秒那第一反应应该是去看Redis的轮询间隔。如果你用的是一秒一次的轮询那么最坏情况延迟1秒属于正常如果你用的是while True sleep(5)那5秒延迟也在意料之中。如果想更快用BLPOP阻塞读取是更好的方案几乎可以做到信号一到就立刻消费。信号传输本身的耗时其实很低通常不到1毫秒。真正的大头是聚宽策略计算、本地下单接口的响应、券商柜台处理。所以如果整体链路延迟高建议在代码里给每个环节都打上时间戳从信号写入Redis到订单回报返回逐步定位是哪个环节慢。6.4 实盘中的隐性大坑行情权限、停牌、涨跌停、资金不足实盘和回测最大的不同是实盘里有各种“回测里不存在的意外”。比如信号说买入但股票当天停牌你是买不进去的。信号说卖出但股票跌停封死你即使挂了卖单也成交不了。信号计算的目标仓位折算成股数之后发现资金不够因为你还留着手续费没算。QMT凌晨维护你的实盘程序挂了信号没消费第二天早上醒来发现自己没交易。这些问题的通用解法是在QMT侧做一个交易前检查。下单前先查一下trader.query_stock_asset和trader.query_stock_positions确认股票是否能交易、有没有持仓、资金够不够然后再下单。另外信号消费失败要有告警至少得把失败日志写清楚不然盘中出了问题你只能干瞪眼。7. 最终实践心得对接QMT和聚宽这套体系我自己最大的感受是技术都不是最难的最难的是想清楚信号的生命周期。很多人在本地跑通了“聚宽出信号 - Redis读到 - QMT下单”这串流程就觉得完事了结果一上实盘不是漏单就是重复下单归根到底是状态管理没做好。把信号从出生到消亡的每一步都考虑进去每一笔委托都有迹可循成功率才会真正上来。另外一个建议是任何地方都要留日志。聚宽侧推送了信号要打日志Redis里写入了要能查得到QMT侧收到了要打日志下单返回的order_id要记录回调更新的状态也要记录。只有把数据链路完整记录下来了排查问题的时间才能从小时级压缩到分钟级。还有一点信号队列建议定期清理过期key该删就删别让Redis变成一个垃圾场不然等到它内存告警的时候你的策略已经默默地停止交易了。这套对接方案现在陪我跑了好几个月中间也经历过半夜惊醒、爬起来看订单状态的日子但把状态机、幂等机制、异常排查这几块补齐之后基本就稳了。希望这篇文章能给准备做聚宽和QMT对接的朋友省下几个星期的摸索时间。如果你也踩过client is null或者其他奇怪的坑欢迎在评论区互通有无毕竟量化这条路一个人闷头走太容易掉沟里。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。