QMT和通达信这两个词放在一起,很多刚开始接触量化交易的人会愣一下:这不是两个软件吗?一个是我天天看盘用的行情终端,一个是券商给的交易客户端,它们能怎么配合?实际上,我身边不少做程序化交易的朋友,日常工作流就是“通达信选股,QMT下单”——用通达信丰富的公式生态把盘面信号筛出来,再把信号自动送给QMT完成委托,整个过程不用人盯盘、不用手动敲单。这篇文章就把这条链路拆开讲透,从公式怎么写、预警怎么接、数据怎么传、QMT怎么下单,到中间会踩的坑,一次性给你捋明白。
如果你已经能写一点通达信指标,又想把自己的选股思路做成真正能自动交易的策略,这篇文章就是给你准备的。如果你完全没有量化基础,但只要看得懂K线和均线,跟着步骤走也能搭出一套能跑的自动化框架。
1. 先把方案想清楚:为什么预警归通达信,交易归QMT
1.1 两个软件的天生定位刚好互补
通达信在国内股民里的普及率不用多说,它的公式系统积累了几十年,网络上随便一搜就是各种指标、选股公式、条件预警,生态成熟得可怕。我写策略的时候,很多灵感就是先从通达信的指标社区里看到的,比如“主力追踪分时指标源码”“主力增仓指标”这类资金流思路,放在通达信里改一改,很快就能验证。
但通达信的短板也明显:它本质上是一个行情和分析软件,虽然带一点交易功能,但主要面向人工操作。你想让它按条件自动下单、自动撤单、批量报单,非常别扭。
QMT则是券商提供的量化交易终端,内置Python和VBA接口,能直接连接柜台报单,速度和稳定性都远胜于模拟手工点击。但QMT的公式选股生态远没有通达信丰富,很多指标得自己拿Python重新实现一遍。
所以最务实的做法就是“分工协作”:通达信负责信号发现,QMT负责交易执行。两边都是各自领域的成熟工具,你不需要重新发明轮子。
1.2 这条链路实际又三个环节
我习惯把“从预警到交易的自动化”拆成三个环节来看:
- 信号发现:通达信这边跑公式,在盘中或盘后筛选出符合你条件的股票,生成预警列表。
- 信号传递:用某种方式把选股结果从通达信交给QMT,不能靠人肉抄,得有文件、数据库或接口通道。
- 交易执行:QMT拿到信号后,完成查持仓、查资金、下单、回报确认等一系列动作。
这三个环节里,大家最容易忽略的是中间的“信号传递”。很多人早早写好了通达信公式,也开通了QMT权限,结果卡在不会把两者连起来,于是又回到手动下单。其实通道方案很多,后面第四章会详细展开。
1.3 为什么不用纯QMT或者纯通达信
你可能会想,QMT自带Python,我直接在里面把指标写了不就行了?说实话,如果你擅长写Python,这么做没毛病。但问题是:通达信里一个十来行的选股公式,换成Python实现可能要上百行,而且行情数据源、复权处理、盘中刷新全都要自己折腾。反过来,纯通达信自动化下单基本不现实,它的交易接口和合规限制都摆在那里。
还有一个现实因素:很多人选股思路最初就是在通达信里跑着的,已经验证过一段时间,直接迁移回测逻辑,容易引入偏差。与其推倒重来,不如在现有通达信框架上做加法,把交易环节外接到QMT。这也是我认为适合大多数普通投资者的路线。
2. 环境准备:先把两个软件的“底座”装稳
2.1 QMT环境依赖到底要装什么
“qmt安装环境依赖”是我见过问得最多的问题。实际上,QMT客户端一般自带一套定制版Python环境,安装后主要需要确认几个东西:
- 登录QMT终端,进入交易界面,确认账号能正常登录。
- 打开QMT的“模型交易”或“程序化交易”面板,通常会生成一个 Python 工作目录,里面有券商提供的
xtquant包。 - 用你自己机器上的Python调试时,需要安装
xtquant。我遇到过的情况是,不同券商给的包版本略有差异,最好以你券商文档的包为准。
很多报错,比如“qmt终端 client is null”,十有八九不是包没装好,而是QMT客户端没有登录,或者登录态过期。你写了代码打算连接终端拿账户数据,连上的时候才发现会话是空的,就会报这个错。
2.2 通达信端要打通的数据出口
通达信这边,要先确认几个基础条件:
- 盘中能用“条件预警”功能。在菜单“功能”里找到“预警系统”,把你要监控的公式加进去。
- 数据下载要完整。如果做盘后选股,建议先执行一遍盘后数据下载,避免因为部分数据缺失导致选股结果不准。
- 如果盘中要高频刷新,要注意连接数限制。装上几个券商行情服务器之后,通达信默认的连接数其实不算大,网上常有人问“怎么样让通达信20路同时运行”,其实就是多开几个实例或用 connevct.cfg 调整连接参数。我的经验是:在同一台机器上开多个通达信实例,内存占用会很夸张,最好控制在两三个以内,或者用云服务器分担。
需要提醒的是,通达信的通讯协议是封闭的,网上流传的解析方法大多依赖本地文件格式,而不是抓网络数据包。我更推荐走“通达信本地数据”这条路线,后面会细讲。
2.3 通道选择:同机部署还是双机部署
QMT和通达信都主要运行在Windows上,所以最简单的方案是同一台Windows电脑上同时跑两个软件。同机部署的好处是文件共享、数据库连接都方便,坏处是容易受系统休眠、Windows更新之类的影响。
也有朋友用双机方案:一台机器专门跑通达信看盘,另一台跑QMT,中间通过网络共享文件夹或数据库同步信号。这样更稳,但要多维护一台机器,日常成本更高。我自己是先用同机方案把链路跑通,再决定要不要拆开,先求功能后求稳健。
3. 通达信侧:把预警信号做成“可被别人读懂”的格式
3.1 一个能用的选股指标示例
我先给一个非常简单的选股公式,风格上参考网上流传的“三步点金通达信源码”那种思路:条件不复杂,但组合起来能代表一类常见战法。
{三步点金示例:均线多头+放量阳线} MA5:=MA(CLOSE,5); MA10:=MA(CLOSE,10); MA20:=MA(CLOSE,20); 放量:=VOL > REF(VOL,1) * 2; 阳线:=CLOSE > OPEN; 突破:=CROSS(CLOSE,MA20) OR (CLOSE > MA20 AND REF(CLOSE,1) <= REF(MA20,1)); 选股: 放量 AND 阳线 AND MA5 > MA10 AND MA10 > MA20 AND 突破;在通达信里,打开公式管理器(快捷键一般在功能菜单里,版本不同入口略有差异),新建一个“条件选股公式”,把这串代码粘进去,编译通过后就能用了。
这里我想多说一句:公式的编写重点是逻辑清晰,不是炫技。你未来要把信号传给QMT,代码里最好只保留真正用得上的条件,别塞太多装饰性语句,不然排查问题的时候自己都容易看晕。
3.2 预警和自动选股的设置
公式建好之后,有两种用法:
- 盘中预警:打开条件预警设置,把刚才的选股公式加进监控列表,通达信会在盘中满足条件时弹窗提示。这个适合看盘用,但弹窗对程序化不友好,因为信号不会自动生成文件。
- 自动选股:在“功能”菜单里找到“公式选股”或“自动选股”,运行选股公式,把结果加入自定义板块。选股结果可以随后手动导出。
如果你只是偶尔选股,手动导出就够了。但要实现全自动,就要让选股结果被程序读取。最稳妥的做法是:设定自动选股在固定时间运行,结果输出到自定义板块,再用外部工具读取通达信板块文件。这个方法比盯着预警弹窗要可靠得多。
3.3 把选股结果输出成程序能读的格式
通达信本身没有直接提供“选股结果自动写txt”的开关,所以实战中大家会用几种变通办法。
第一种最简单:自动选股后,把自定义板块里的股票手动用“数据导出”存成TXT或Excel。这个适合半自动场景,每天盘后跑一次,然后把文件丢给QMT次日执行。
第二种是解析板块文件:通达信的自定义板块信息会保存在本地,一般是blocknew或类似命名的cfg文件,格式比较固定。你可以用Python解析这个文件,拿到最新的板块成分股代码,再写入数据库。这样只要通达信自动选股完成了,Python侧就能感知到变化。
第三种是把通达信本地数据直接拿给外部程序用,现在也有人做“通达信 股票软件 本地数据 mcp”,用类似MCP的方式把行情数据暴露给其他AI工具或脚本。这类方案适合不想自己解析复杂格式的人,但依赖第三方实现,要留意数据格式和软件版本匹配问题。
我自己常用的路径是:通达信自动选股 → 自定义板块 → Python读板块cfg文件 → 生成统一信号表。整个过程十分钟能跑完,而且不依赖外部服务,稳。
3.4 一些指标思路:主力追踪和主力增仓是怎么写出来的
网上最常被搜的指标就是“主力追踪分时指标源码”和“通达信主力增仓指标”。这类指标本质上都在做同一件事:通过量价关系去推测主力行为。比如“主力增仓”,常见写法是用大单成交金额占总成交金额的比例,或者用主动买盘和主动卖盘的差值近似判断资金流入。
{主力增仓示例} 主力增仓:= 大单净量 > 0 AND CLOSE > OPEN;不过我要泼一点冷水:这类指标作为盘面参考可以,但千万不要把“主力增仓”当成一定会涨的信号。它是资金流向的近似估计,不等于真实席位数据。做自动化的时候,我更建议把它当成一个“过滤条件”,配合其他策略逻辑综合使用。
4. 中间桥梁:把预警结果实时“递”给QMT
4.1 方案A:文件监控方式(最推荐入门)
文件通道是门槛最低、也最容易调试的方案。思路是:通达信或你的Python脚本把选股结果写入一个TXT文件,QMT侧的Python脚本监控这个文件,发现内容变化就读取新信号。
比如你每天盘后把选股结果写到D:\signals\today.txt,每行一只股票代码:
600519 000001 300750那QMT侧的Python可以用一个循环去监控文件变化。给你一个最朴素的示例,不需要额外安装复杂库:
import os import time signal_file = r"D:\signals\today.txt" last_mtime = 0 while True: try: mtime = os.path.getmtime(signal_file) if mtime != last_mtime: with open(signal_file, "r", encoding="utf-8") as f: lines = [line.strip() for line in f if line.strip()] print("检测到新信号:", lines) # 在这里调用QMT下单逻辑 last_mtime = mtime except FileNotFoundError: print("信号文件不存在,等待生成...") time.sleep(5)这段代码的优点是逻辑直白,你只需要理解“时间戳变化”这个概念:每次文件被重新保存,修改时间就会更新,程序就知道有新信号了。
有朋友会问:“文本文档怎么运行代码?”其实很简单,把上面的代码保存为monitor.py,在命令行里执行python monitor.py就行,不需要什么特殊IDE。
4.2 方案B:本地数据库方式(更适合盘中频繁推送)
如果信号量很大,或者你要做盘中的实时监控,文本文件可能会出现写入冲突、并发读取的问题。更稳妥的方式是让通达信侧脚本把信号写入本地数据库,比如SQLite,QMT侧直接查数据库新增记录。
SQLite的好处是单文件、零配置,Python内置支持,非常适合这种“两台程序共享数据”的场景。比如通达信侧每小时写入一批选股结果,QMT侧用增量查询读取“还没有处理过的股票代码”,处理完后更新标记,这样就不会重复下单。
数据库通道的排查成本比文件通道高一些,因为涉及连接、事务、锁,但换来的是更高的可靠性。如果你发现文件方式偶尔丢信号,建议尽早切到SQLite。
4.3 编码、代码格式和时间戳的坑
在搭建通道的时候,最容易踩的三个坑:
- 编码问题:通达信导出的文件可能是GBK编码,而Python默认用UTF-8读会乱码。读取时最好用
encoding="gbk",或者统一转成UTF-8。 - 证券代码映射:通达信里显示的“600519”可能不带交易所前缀,但QMT报单通常需要完整的证券代码格式,比如
600519.SH、000001.SZ。这个映射必须在前置逻辑里处理好,不能让错误代码进入下单环节。 - 时间戳和去重:文件或数据库里的信号要带时间戳,QMT侧要通过时间戳判断“这个信号是新的还是旧的”。否则你重启一次程序,它可能把历史信号全部重新下单一遍,那会出大问题。
5. QMT侧:把信号变成真实委托
5.1 QMT的Python接口结构
QMT这边的编程入口通常叫xtquant,里面最核心的是交易类。我没法在这里写出和你的券商完全一致的文档,但一般套路是固定的:
from xtquant import xttrader from xtquant.xttrader import XtQuantTrader from xtquant.xttype import StockAccount # 连接QMT终端 path = r"d:\qmt\userdata_mini" # 目录以你实际安装位置为准 session_id = 123 trader = XtQuantTrader(path, session_id) trader.start() trader.connect() # 用资金账号登录 account = StockAccount("你的资金账号") trader.subscribe(account) # 查询资产 asset = trader.query_stock_asset(account) print(asset)这里要注意,QMT的策略代码并不是独立运行的“服务脚本”,它依赖QMT客户端已经登录。你在调试时,终端必须保持登录状态,不能把客户端关掉。这也是很多人报client is null的原因之一:客户端没开,或者会话掉线。
5.2 从“收到信号”到“完成下单”的状态机
真正写交易逻辑时,我建议不要急着把“读信号”和“下委托”塞在一起,而是拆成一个简单的状态流程:
- 接收信号:从文件或数据库读到新的股票代码。
- 持仓检查:查一下这只股票是否已经持有,避免重复加仓。
- 资金检查:查一下可用资金是否足够下指定数量。
- 价格判断:如果是市价单,直接下单;如果是限价单,要确保价格合理。
- 下单并记录:调用下单函数,把请求记录下来。
- 回报确认:异步等待回报回调,确认委托状态。
下单的关键代码大概长这样:
# 以限价单买入100股为例 order_id = trader.order_stock(account, stock_code, xtconstant.STOCK_BUY, 100, xtconstant.FIX_PRICE, price) print(f"委托已提交: {order_id}")这里“下单”只是提交委托,并不意味着成交。QMT的回调机制会告诉你委托状态的变化,比如“已成”“部成”“已撤”等。为了稳妥,你应该把回报处理写进回调函数,并做好日志。
5.3 风险控制:防止“程序比你更疯”
自动化交易最怕的不是信号不准,而是程序在异常时疯狂下单。比如网络卡了一下,信号被读取了两遍,就可能出现双倍仓位。所以我的风控三板斧是:
- 硬性限制:程序里写死单日最大下单次数、单只股票最大买入金额,超过就停止。
- 去重逻辑:基于信号ID或者日期做去重,同一信号不重复处理。
- 手动熔断:在界面上留一个“总开关”,盘中如果发现异常,一键关闭自动交易。
对于刚开始做自动化的人,我强烈建议先在模拟盘跑两个星期,把各种边界情况跑一遍,再上真实小资金。这个过程接触过“自动化测试”“接口自动化”的朋友应该很有共鸣,本质上就是给交易系统做回归测试,把可能炸的雷提前排掉。
6. 常见问题与排查技巧实录
6.1 一张问题排查速查表
| 现象 | 可能原因 | 排查步骤 |
|---|---|---|
| 通达信预警弹窗了,但程序没收到信号 | 选股结果没有导出到文件或板块 | 先确认“自动选股”结果是否写入自定义板块;确认文件路径和程序监控路径一致 |
| Python读文件中文乱码 | 文件编码是GBK | 读取时指定encoding="gbk",或让上游统一导成UTF-8 |
| QMT提示 client is null | QMT终端未登录/会话过期 | 打开QMT客户端并登录交易账户,保持进程在后台运行 |
| 程序跑起来后重复下单 | 缺少去重逻辑 | 给信号加唯一ID,或记录已处理信号的清单 |
| 股票代码报错 | 代码没有带交易所后缀 | 把通达信代码转为QMT格式,如600519.SH、000001.SZ |
| 盘中数据刷新延迟 | 通达信连接数不够 | 检查两侧连接配置,必要时调整 connect.cfg 或减少多开实例 |
| Windows休眠后程序不工作 | 系统自动睡眠,脚本停摆 | 关闭自动睡眠;或在机器上配置计划任务定时唤醒 |
| 下单成功但没成交 | 限价单价格偏离盘口 | 查看委托回报,改用对手价或市价单 |
6.2 我踩过的几个典型坑
先说通达信多开的事。有人问“让通达信20路同时运行”怎么弄,我试过开四五个实例,结果内存直接爆了。后来发现真的没必要——大多数人只是同时监控几个板块,一个实例里把预警股票池加满就够。真有那么多信号要处理,先想想是不是策略条件设得太宽。
再说QMT这边。之前调试时经常出现“代码能连接终端,但报单回报迟迟不到”的情况,最后发现是我跑了多个QMT会话,回调逻辑被重复订阅。每次调试完一定要把旧会话释放掉,否则回调会串。
还有一次,信号文件在盘中从几十行变成上万行,程序卡在读取阶段。原因是上游脚本把历史数据全量写进了同一个文件。后来我在生成信号文件时严格限制“只保留当天新增信号”,并且监控逻辑里加了文件大小校验,这个问题就再没出现过。
6.3 自动化跑起来之后,还需要人工盯什么
程序替你下单了,不代表你可以完全不管。我每天例行检查的事情不多,但都很关键:
- 看日志:程序每天输出一份日志,重点扫一眼有没有异常报错。
- 对账单:盘中看一次成交回报,确认委托没有挂在那边一直不成交。
- 风向标:如果当天某只股票停牌或者临时停牌,程序很可能卡在“查不到价格”的情况,需要人工处理。
- 留有余量:资金账户里不要放满,给程序留一点缓冲,避免遇到异常时无法补仓或调整。
在这个环节,我身边不少做了很久的朋友也坚持“日复盘”。自动化省下来的时间,其实应该花在复盘和策略迭代上,而不是真的去做甩手掌柜。
做这套自动化链路,我最深的体感是:真正难的从来不是写代码,而是把边界条件都处理干净。线上跑的策略,大部分时间都在对付各种“意外”:文件没生成、编码变了、账号掉线、股票停牌、重复信号……如果你把这些情况都提前想好,每个环节都有日志、有兜底,这个自动化系统才算真正立住了。
最后分享一个小技巧:刚开始联调时,别直接让QMT按信号自动下单。你先让程序把“准备下的单”写成日志,连续模拟运行几天,确认输出完全符合预期,再放开真实下单。这多花的一周时间,能帮你省掉后面大量的补救成本。