你可能已经花了不少时间研究量化策略,在回测软件里跑出了漂亮的资金曲线,但一说到实盘自动化交易就卡住了——手动下单既慢又容易受情绪干扰,还经常错过最佳执行价格。我当初也在这个环节纠结了很久,最后选择了QMT和Ptrade这两套券商级工具,把选股、下单、风控全部交给程序自动完成。这篇内容就是把整个落地过程拆开来讲,从权限开通、客户端部署、策略代码,到自动打新、数据下载和实盘风控,适合那些已经掌握Python基础、想跳过重复劳动直接搭建自动化交易系统的朋友参考。
QMT和Ptrade都属于券商提供的程序化交易终端,不是自己从头写一套交易系统,而是站在券商已经建好的通道上做策略开发。对于个人量化交易者来说,这是目前性价比最高的一条路:不需要自己处理柜台接口、持仓同步、交易报告这些麻烦事,只需要把精力集中在策略本身。
1. 先搞清楚QMT和Ptrade的真实定位:不是所有“量化工具”都能直接下单
很多人一听“量化交易”,第一反应是自己写代码对接交易所,或者用一个能画K线的软件跑回测。但真正到了实盘环节,你得面对一个现实问题:你的程序需要通过某种合规的通道把委托单发到券商柜台,然后由柜台报给交易所。QMT和Ptrade解决的就是这个“最后一公里”的问题。
1.1 QMT和Ptrade的身份差异:券商定制的程序化终端
QMT是迅投开发的一整套量化交易客户端,很多券商直接拿来作为自己的量化终端,比如国金证券的版本就叫“国金QMT”。它既有图形界面用来盯盘和手工交易,也提供了miniQMT这种给开发者用的Python接口,通过xtquant库就能在外部IDE里写策略、取行情、下单。
Ptrade则是恒生电子推出的量化策略交易平台,同样被多家券商采用。它的特点是策略编写、回测、模拟交易、实盘交易都在同一个Web界面上完成,学习成本比QMT低一截,而且内置了不少现成的功能模块,比如自动打新、网格交易、定投策略等。
这两套工具解决的核心问题是一样的:把“策略想法”变成“实际委托单”。区别在于QMT更偏“客户端+本地Python环境”,灵活性高;Ptrade更偏“托管环境+Web操作”,稳定性和易用性更好。
1.2 为什么我劝你优先用券商工具而不是自己写交易系统
自己从头写一套自动化交易系统听起来很酷,但实际要解决的技术问题远超预期。你需要处理券商柜台协议的对接、断线重连、委托状态同步、持仓与资金的对账、撤单失败后的补偿逻辑,还要搞一个能扛住盘中高并发查询的数据库。这些工作量的总和,足以让一个初级开发忙活大半年,而且每一条都潜藏着资金风险。
QMT和Ptrade把这些底层细节全部封装好了。你只需要关注三件事:策略逻辑怎么写、行情数据从哪来、下单接口怎么调。券商已经帮你解决了合规报备、交易通道、账户体系这些最麻烦的部分。
1.3 一个反直觉的事实:很多“量化交易课程”教的代码根本跑不了实盘
市面上很多量化课程的代码停留在“使用第三方库读取历史数据,然后用循环计算买卖信号”的阶段。这类代码用来理解原理没问题,但直接拿去做实盘自动化会非常尴尬:没有实时行情推送、没有账户资金查询、没有委托回报处理,自然也没有办法自动下单。
真正的实盘自动化代码,至少要包含三层:数据层负责拿实时行情,策略层负责算信号,执行层负责把信号变成委托并跟踪委托状态。QMT和Ptrade的接口设计恰好就是按照这个思路来的,这也是我推荐从这两套工具入门的原因。
2. 开通权限、安装客户端:第一个绕不过去的门槛
QMT和Ptrade不是下载就能用的软件,需要券商的柜台系统先给你开通程序化交易权限。这一步看起来简单,实际上很多人在这个环节就卡住了。
2.1 资金门槛与权限申请的真实情况
不同券商对QMT和Ptrade的资金门槛要求不一样,有的要求证券账户资产达到一定金额,有的只要申请就能开通。我见过的最低门槛是几万元,高的可能要几十万。
申请流程一般是:先联系你的客户经理,说明想开通量化交易权限(QMT或Ptrade),然后按要求签署程序化交易相关的协议。部分券商还需要填写策略说明和风控承诺书。这里有个实用经验:如果你的客户经理对量化不太了解,可以直接问“贵司支持迅投QMT还是恒生Ptrade,我想申请miniQMT或Ptrade的实盘权限”,这句话一出来,对方就知道你是内行。
2.2 客户端下载安装与环境变量配置
拿到权限后,券商会发给你客户端下载链接。QMT一般是一个Windows安装包,安装完登录后,你会看到一个类似行情软件的界面。不过做量化的人通常不会直接在QMT的图形界面里写策略,而是用miniQMT模式:在外部Python环境里安装xtquant包,然后通过Python代码连接QMT客户端。
我第一次装的时候遇到一个典型问题:Python代码能跑,但一直报连接超时——因为QMT客户端没有登录,或者没有开启“允许外部程序接入”的选项。这个选项藏在QMT客户端的系统设置里,需要登录后手动勾选。不同券商的版本位置略有差异,但基本都在“交易设置”或“系统设置”一类的地方。
Ptrade的安装则要简单得多,它通常是Web版,券商开通权限后直接给你一个网址和账号密码,浏览器登录就能写策略和交易,不需要本地安装任何客户端。
2.3 国金QMT的Python下载失败与自动登录问题排查
搜索热词里有两个高频问题:“国金qmt python下载失败”和“国金证券qmt自动登录方式”。这两个我正好都踩过坑。
Python下载失败的原因,我排查下来主要有四个:
- 网络源问题:xtquant包从PyPI或券商自己的源下载,网络不稳定时容易中断。解决办法是切换国内镜像源。
- Python版本不匹配:xtquant对Python版本有要求,某些券商版本只支持3.7到3.10,装了Python 3.11以上就会失败。
- 杀毒软件拦截:QMT的客户端和xtquant包会被部分杀毒软件误报,下载过程中直接被隔离。
- 安装路径权限不足:把Python装在了需要管理员权限的目录下,pip安装时报错。
我自己最终的解决方式是用Anaconda单独创建一个Python 3.8的虚拟环境,然后从券商官方文档里给的备用链接直接下载whl文件,再本地安装。这样绕开了网络问题,版本也完全可控。
自动登录这件事,QMT的官方客户端通常会有一个“自动登录”勾选项,但实际用处有限,尤其是跨夜重启后仍然需要手动确认。我后来用了一个更接地气的方案:写一个Windows计划任务,每天开盘前定时启动QMT客户端,配合客户端的参数实现自动登录。不同券商的QMT版本支持的启动参数不太一样,但大致思路是启动时带上账号和配置路径。个别版本还支持通过ini文件或注册表记忆登录状态,部分券商甚至提供了类似auto_login的专用工具或接口,具体以你所在券商客户端的实际功能为准。
3. 写策略前必须搞懂的底层概念:数据、信号与执行
很多人在这一节容易犯一个错:直接把回测代码复制过来改几下就去实盘。回测和实盘之间的差距,比大部分人想象的大得多。为了避免实盘翻车,下面三个概念必须搞清楚。
3.1 订阅行情:轮询还是事件驱动
在QMT和Ptrade里获取行情,主要有两种方式:主动拉取和订阅推送。
主动拉取就是你调一个接口去查当前价格,比如代码里写一个while循环每秒钟取一次最新价。这种方式简单,但有两个问题:一是行情有延迟,二是高频轮询会占用大量CPU,在“大QMT单线程”的限制下容易阻塞后续任务。
订阅推送则是告诉系统“我要关注这几只股票”,然后系统每来一笔新行情就主动回调你的函数。这种方式响应快、节省资源,是实盘自动化推荐的做法。Ptrade的策略框架里就有handle_data函数,每个数据切片周期自动调用;QMT的xtquant也提供了类似subscribe机制。
3.2 交易接口的核心操作:委托、撤单与持仓
一套自动化交易系统,本质上是在循环处理几类操作:按信号买入、按信号卖出、检查委托是否成交、没成交就决定是继续等还是撤单重发、随时查询当前持仓和可用资金。
QMT的xtquant中,主要接口包括:下单接口、撤单接口、查询持仓接口、查询资金接口。Ptrade则提供了order、order_target等封装好的函数。无论哪个API,你要掌握的核心逻辑是一样的:每次下单后,系统会返回一个委托编号,你必须用这个编号去跟踪后续的委托状态,判断是“已成”“部成”还是“已撤”。很多初学者的策略在回测里跑得很好,一上实盘就乱,就是因为没有处理这个状态跟踪的循环。
3.3 回测与实盘的“模型偏移”
这是一个容易被忽略但极其致命的问题。回测中,你用的是历史的完整K线数据,信号出现的那一刻你就假设能立即成交;但实际上,实盘行情是逐笔推进的,信号出现时你看到的收盘价可能已经和真实可成交价有偏差,尤其是小盘股和高波动行情里。
即使你的策略逻辑完全正确,实盘表现也会和回测有差距,这部分偏差就叫“模型偏移”。避免它的一个实用建议是:回测时不要用收盘价撮合,至少用下一根K线的开盘价,并且把手续费、滑点都按保守值设置。我在跑双均线策略时,回测年化看着很不错,实盘第一个月收益直接少了一半,原因就是滑点和冲击成本没算够。
3.4 大QMT单线程到底什么意思
搜索热词里出现的“大qmt单线程”,指的是QMT的某些策略引擎在同一时刻只执行一个Python任务,如果你的策略主流程里有一个耗时的阻塞操作(比如同步下载大量历史数据),后面的行情回调就被卡住了。
解决思路其实不难:把耗时任务放到子线程里跑,主线程保持轻量化;下载历史数据这类事尽量在收盘后做,盘中只处理实时行情和交易信号。
4. 第一个自动化交易策略:双均线系统的完整拆解
选择双均线交叉作为第一个策略,不是因为它能稳定赚钱,而是它足够简单,能让你把“数据→信号→执行”这条链跑通。只要链跑通了,后面换任何策略都只是替换“信号生成”那一段代码。
4.1 Python策略代码的结构与写法
下面是一个基于QMT miniQMT的极简示例,用来演示完整的策略框架,不是在教你把全部资金按这个跑实盘。核心思路是订阅日线行情,当5日均线上穿20日均线时买入,下穿时卖出。
import xtquant.xtdata as xtdata import xtquant.xttrader as xttrader import pandas as pd # 参数区 code = "000001.SZ" asset_account_id = "你的资金账号" fast_window = 5 slow_window = 20 # 读取历史数据用于初始化均线 hist_data = xtdata.get_market_data_ex( field_list=["close"], stock_list=[code], period="1d", count=60 )[code] # 连接交易 session = xttrader.XtQuantTrader("你的QMT客户端路径", "session_id") session.start() session.connect() def on_bar(bar): # 每次来一根新K线,重新计算均线 hist_data.loc[bar["time"]] = bar["close"] ma_fast = hist_data["close"].rolling(fast_window).mean().iloc[-1] ma_slow = hist_data["close"].rolling(slow_window).mean().iloc[-1] prev_fast = hist_data["close"].rolling(fast_window).mean().iloc[-2] prev_slow = hist_data["close"].rolling(slow_window).mean().iloc[-2] # 多头交叉,买入 if prev_fast <= prev_slow and ma_fast > ma_slow: session.order_stock(asset_account_id, code, xttrader.STOCK_BUY, 100, xttrader.FIX_PRICE, 0) # 空头交叉,卖出 if prev_fast >= prev_slow and ma_fast < ma_slow: position = session.get_stock_positions(asset_account_id, code) if position and position[0].volume > 0: session.order_stock(asset_account_id, code, xttrader.STOCK_SELL, position[0].volume, xttrader.FIX_PRICE, 0) xtdata.subscribe_quote([code], "1d", callback=on_bar)代码里的order_stock和get_stock_positions参数在不同券商版本的xtquant里略有差异,你拿到官方文档后对着改参数名就行。核心逻辑就是策略框架的骨架,后面的策略再怎么复杂,也逃不开这个模式。
4.2 不要把主线程阻塞在下载数据上
极简代码里有一个隐患:在初始化阶段直接调用get_market_data_ex同步下载历史数据,如果这个函数耗时较长,会阻塞行情订阅。实操中应该在程序启动时先去下载历史数据,再启动行情订阅,或者把下载放到专门的线程里。
4.3 从“手动跑”到“自动跑”:安排任务与盯盘
程序写好后,总要有人在你睡觉的时候替你看盘,这就是自动化的价值。QMT客户端需要保持登录状态,Python策略脚本需要保持运行。我的做法是写一个启动脚本,同时拉起QMT客户端和策略进程,再加一个看门狗脚本定时检查策略进程是否还活着,如果意外退出就自动重启。这个“看门狗”的思路同样适用于Ptrade这类托管平台之外的自建服务场景。
4.4 因子数据下载:量化研究的弹药库
搜索热词里有“qmt 如何下载因子数据”,这里一起说清楚。QMT的xtdata模块提供了历史行情下载功能,包括日线、分钟线、财务数据等。你可以按股票代码批量下载,也可以全市场扫描。
因子数据分三类,下载方式和用途完全不同:
| 因子类型 | 来源 | 典型数据 | 获取方式 |
|---|---|---|---|
| 行情因子 | QMT行情接口 | 价格、成交量、振幅 | xtdata直接下载 |
| 基本面因子 | 券商数据服务 | 财报、估值、股东结构 | QMT财务数据库或第三方 |
| 另类因子 | 外部数据源 | 舆情、资金流、龙虎榜 | 数据API或网络爬虫 |
下载因子数据最常见的问题,不是不会调接口,而是数据量太大导致下载超时。一次下载全市场几千只股票五年的分钟线,数据量轻松到几十GB,这不仅是时间问题,还占磁盘空间。实用建议是:把数据按“日线全量、分钟线近三个月、事件类因子滚动更新”的方式分层存储,避免一次性把所有历史数据都拉下来。
5. Ptrade自动打新:真正的“躺赚”功能可能比你的策略还稳
在很多个人量化策略的收益还没跑出来之前,自动打新反而是真正能稳定贡献超额收益的部分。A股打新的逻辑大部分时候是”申购就可以,中签才缴款“,风险可控,收益率虽然一直在下降,但作为自动化交易系统里的一个模块依然很有存在价值。
5.1 Ptrade自动打新的原理与设置
Ptrade之所以在量化圈子里受欢迎,一个很大的原因是它内置了自动打新功能。你不需要自己写复杂的申购代码,只需要在Ptrade的策略管理页面里配置好“新股新债自动申购”的开关,系统会在每个交易日的申购时间段自动为你的持仓市值对应的额度发起申购。
操作路径一般是:登录Ptrade → 进入“策略”或“自动化”模块 → 找到“打新设置”或“新股申购” → 打开自动申购开关,选择参与申购的市场,保存。
5.2 中签后的资金准备与缴款提醒
自动打新最大的隐藏风险是中签后忘记缴款。新股中签后,券商一般会短信通知,你需要在T+2日16:00前保证账户里有足够的资金。自动化系统可以帮你申购,但资金转入了还是要你自己安排。
好一点的方案是在Ptrade里额外写一个小监控策略:每天检查账户可用资金,如果发现中签缴款日资金不足,就推送一条告警到微信或短信。这就用到了自动化系统里“事件提醒”这个模块,和交易本身一样重要。
5.3 为什么我把打新放在”入门友好“的位置
对于刚接触量化交易的人来说,自动打新几乎是零风险的自动化实践:它涉及的代码少、资金占用小、收益与策略能力无关,可以让你快速熟悉“系统自动做事”的感觉,同时积累一套日志和监控经验。在这些经验成熟之前,不建议直接上高杠杆的日内策略。
6. 实盘人生必备:资金管理、断线重连与日志告警
搭建好策略代码只是开始,真正决定你能在这个市场活多久的,是风控和运维能力。这一部分可能不像写策略那么有成就感,但每一个细节都可能在关键时刻救你一命。
6.1 仓位管理:自动化系统的“安全气囊”
我见过不少自动化交易翻车案例,本质上都不是策略逻辑的问题,而是仓位没有管理好。一个很朴素但有效的原则是:单只股票的仓位不超过总资金的10%,单日最大回撤达到一定比例就停止开新仓。
在QMT和Ptrade里,这些规则都可以在策略启动时写死。比如买入前检查“当前持仓市值占总资金比例是否超过上限”,如果超过就跳过本次买入信号。这行代码看起来不起眼,但在策略连续触发买入信号的行情里,它就是你和爆仓之间的隔离墙。
6.2 断线重连、代码异常与日志留痕
自动化系统跑在真实交易时段,网络抖动、客户端崩溃、接口超时都是必然会发生的事,只是时间问题。你需要在系统设计时就把这些异常当作正常流程处理。
import time import logging logging.basicConfig(filename="trade.log", level=logging.INFO) while True: try: session = create_xt_trader() # 伪代码 session.start() logging.info("策略启动成功") while True: time.sleep(5) session.check_connection() # 伪代码 except Exception as e: logging.error(f"连接断开: {e}") time.sleep(10) continue伪代码里体现的思想比代码本身重要:外层循环负责断线后自动重连,内层循环负责交易时段内的状态检查,日志负责把每一次异常和操作记录下来。有了这些,出了问题才有据可查,而不是对着黑屏发呆。
6.3 盘后自动化:复盘与数据更新
实盘自动化只是前半段,盘后的数据整理同样值得自动化。每天收盘后,我建议让程序自动做三件事:下载当天的行情数据并追加到本地数据库;把策略模拟盘的持仓和实盘持仓做一次对比,检查是否一致;把当天的收益曲线、回撤值、交易记录生成一份摘要报告。
把这三件事用定时任务跑起来,你每天早上打开电脑就能看到一份清晰的交易日报,而不是手动打开客户端一个个查。
7. 常见问题排查链路:从“策略没跑”到“持仓不对”
最后这一节,把新手最容易遇到的技术问题按排查思路列出来,也许能帮你少走半年的弯路。
7.1 客户端连接正常的排查顺序
如果QMT客户端已经登录,但Python代码连不上,按下面的顺序排查:
- 确认QMT客户端的“允许外部程序接入”开关已打开。
- 确认Python环境和xtquant包的位数、版本与客户端一致。
- 确认session_id没有与其他正在运行的进程冲突。
- 确认不是公司网络限制了本地回环地址。
我遇到过一例很隐蔽的问题:电脑上装了两个Python环境,pip默认装到了A环境,但VSCode里选择的解释器是B环境,最后代码一直提示找不到xtquant模块。这个问题排查了很久,所以建议一开始用专门的虚拟环境装好依赖,并且固定下来。
7.2 委托报错的常见原因
委托下单报错是另一种高频问题,原因主要集中在:账号未开通对应市场的交易权限、可用资金不足、委托价格超过涨跌停范围、持仓不足却发起了卖出委托。
排除这些以后,如果还报错,就要看委托类型参数是否正确。限价单的price字段不能填0,市价单的price填0在某些接口里可以,但某些券商接口里必须传一个特殊枚举值。
7.3 持仓对不上账:先查同步,再查对账
自动化系统最怕的是程序认为买到了,但实际没成交;或者程序认为卖了,但委托还在挂着。这类问题的根源几乎都是没有跟踪委托状态。
正确做法是:每次委托成功后,要定期拉取当日委托列表或持仓列表,和本地记录做对比。如果发现持仓不一致,先撤掉所有未完成委托,再以券商柜台数据为准重新同步。宁可少交易一次,也不能带着错误仓位过夜。
结尾:跑实盘的这几个月,我最大的体会
以前我总以为量化交易的核心是策略、是模型、是数学公式。真正把QMT跑起来、第一次让程序自动下单的时候,我才反应过来:对普通人来说,量化交易最大的门槛根本不是策略本身,而是“把想法变成稳定运行的系统”这件事。策略灵感的产生只要几分钟,但把它变成一套白天自动盯盘、晚上自动复盘、异常自动告警的交易系统,需要的是工程能力和耐心。
如果你正在准备入坑,我的建议是先从一个最简单的自动打新或双均线跑通全流程,别急着上复杂模型。一套系统跑得稳、跑得久,比跑得激进重要得多。等你把日志、监控、断线重连这些“不性感”的细节都做扎实了,再去尝试更高频、更复杂的策略也不迟。