告别付费行情软件:利用 QMT 免费“白嫖”全市场 Tick 级数据 (附 Python 代码)
前言:作为一名量化开发者,我每年最心疼的支出不是服务器费用,而是数据源费用。Wind 终端一年几万,Tushare 积分也要钱,稍微好点的 Tick 数据源动辄上千。但其实,很多散户手里就握着一把“金钥匙”却不自知——那就是券商免费提供的 QMT。今天,我将教你如何把 QMT 变成一个免费、稳定、实时的行情数据中心。
为什么 QMT 的数据最“香”?
在数据获取这条路上,我们通常有三个选择:
- 爬虫:容易被封 IP,数据不稳定,且有法律风险。
- 第三方 API (Tushare/JoinQuant):好用但要钱,免费版有各种限制(如延迟、限流)。
- 券商 QMT/PTrade:完全免费,速度极快(内网专线),且包含最珍贵的 Tick 级切片数据。
很多券商为了推广量化交易,是花了重金向交易所购买 Level-2 行情的。只要你开通了 QMT 权限(通常门槛在 50万-100万资金量),这些数据对你就是免费开放的。不用它,简直是暴殄天物。
核心原理:订阅-推送模式
QMT 获取数据的逻辑和传统的 request-response 不太一样。它采用的是订阅 (Subscribe) 模式:
- 你告诉 QMT:“我要订阅茅台的 Tick 数据”。
- QMT 客户端会在后台与券商服务器建立长连接。
- 一旦有新成交,QMT 会自动把数据推送到你的本地回调函数里。
这种模式的延迟通常在 毫秒级,非常适合做日内高频策略或盘口分析。
实战演示:搭建本地行情录制器
下面我们将用 Python 编写一个简单的脚本,利用 QMT (MiniQMT) 实时订阅全市场(或指定股票)的 Tick 数据,并保存为 CSV。
1. 环境准备
确保你已经登录了 QMT 客户端(极简模式),并记住了 mini_qmt_path(安装路径)。
from xtquant import xtdata import pandas as pd import time import datetime # 设定股票列表 (示例:茅台、宁德时代) stock_list =['600519.SH','300750.SZ']2. 核心代码:数据订阅与回调
defon_data(datas):""" 这是回调函数,当有新行情推送时会自动触发 """for stock_code in datas: data = datas[stock_code]# 打印实时数据 (你可以改为存入数据库)print(f"[{datetime.datetime.now()}] {stock_code} "f"价格:{data['lastPrice']} 成交量:{data['volume']} "f"买一:{data['bidPrice'][0]} 卖一:{data['askPrice'][0]}")# 简单存个 CSV 做演示# df = pd.DataFrame([data])# df.to_csv(f'./data/{stock_code}.csv', mode='a', header=False)# 1. 订阅全推数据 (全推模式下,不需要指定具体股票,但这需要券商权限)# 如果没有全推权限,只能逐个订阅for stock in stock_list: xtdata.subscribe_quote(stock, period='1m', count=-1)# 订阅 1分钟 K线 xtdata.subscribe_quote(stock, period='tick', count=-1)# 订阅 Tick# 2. 绑定回调函数# 注意:MiniQMT 的数据推送是基于 socket 的,这里直接用 xtdata 的高级接口更简单# 如果需要更高性能,可以使用 xtdata.get_market_data_ex 配合定时轮询print("🚀 数据监听已启动,按 Ctrl+C 停止...")# 3. 阻塞主线程,防止脚本退出whileTrue:# 模拟每 3 秒主动拉取一次最新 Tick (轮询模式,适合存数据) tick_data = xtdata.get_full_tick(stock_list)for stock in stock_list:if stock in tick_data: info = tick_data[stock]print(f"📊 轮询: {stock} 最新价: {info['lastPrice']}") time.sleep(3)3. 进阶技巧:历史数据下载
除了实时数据,QMT 也是下载历史数据的神器。它的下载速度极快,且不限制流量。
defdownload_history():print("开始下载历史数据...")# 下载最近 100 天的 1分钟 K线 xtdata.download_history_data('600519.SH', period='1m', start_time='20240101', end_time='20241231')# 读取并转为 DataFrame data = xtdata.get_market_data( field_list=[], stock_list=['600519.SH'], period='1m', start_time='20240101', end_time='20241231') df = pd.DataFrame(data['600519.SH']).T print(df.head()) df.to_csv('maotai_1m.csv')if __name__ =="__main__": download_history()避坑指南:免费的午餐也有刺
虽然 QMT 数据很香,但在实战中我有 2 个血泪教训:
第一,数据缺失问题。
QMT 的历史数据下载是基于 P2P 或券商缓存的,有时候会遇到某一天数据缺失的情况(比如全是 NaN)。
- 解决方案:下载后务必做一次
dropna()检查,如果缺失严重,尝试换个时间段重新下载,或者手动去客户端里点一下“补充数据”。
第二,客户端必须常驻。xtdata 库的所有功能都依赖于 QMT 客户端的运行。如果你把客户端关了,Python 脚本就会立刻报错。
- 建议:在服务器上跑的时候,不要为了省资源关掉 GUI 界面。
结语
在这个数据即资产的时代,善用手中的工具,就是最大的降本增效。
通过 QMT,我们不仅省下了购买数据的费用,更拥有了一套自主可控的实时行情系统。
把省下来的钱,去买两本书,或者请自己喝杯咖啡,它不香吗?