
这个标题看着像搜索引擎里爬出来的问题但我拿到手反而觉得更值得聊聊。我这些年接过的行情接口少说也有七八种从最开始拿AkShare拉日线做回测到后来用券商QMT做实盘行情中间踩过的坑和绕开的路比接口文档本身能写出来的东西多得多。这篇文章不打算只给一个标准答案而是把主流的接入路径全部整理出来说清楚每条路适合谁、怎么接、坑在哪以及我实际用下来的一些判断。1. 接入前先想清楚不同行情来源的定位和边界很多人一上来就问哪个接口最全这其实是个伪命题。行情接口这个事没有绝对的最全只有最适合你当前场景的方案。核心要先搞清楚一件事你要的行情是拿来干嘛的是回测研究、实盘盯盘、还是程序化交易这三个场景对数据的要求完全不一样。先说免费开源类的数据源典型代表是AkShare和efinance。这类接口的特点是免费、无需注册、开箱即用通过爬取公开网页数据或者对接公开接口来实现行情获取。适合做学习研究、策略回测、个人数据分析数据频率一般到分钟级部分能拿到tick但延迟和稳定性都谈不上保障。我自己早期做策略验证时就用AkShare写个循环拉几百只股票的历史日线处理一下就能跑回测效率确实高。然后是半开放式的数据平台最典型的是Tushare Pro。需要注册获取token不同积分等级对应不同的接口权限和数据粒度。日线、分钟线、资金流向、财务数据覆盖面都很广数据质量相对稳定是个人量化爱好者最常用的方案之一。它的好处是有统一的数据结构和文档坏处是高频数据和部分L2数据需要更高积分或者付费。再往上是券商和量化交易平台提供的接口比如QMT、PTrade、掘金、聚宽、米筐这类。这类接口不只是行情还绑定了交易通道适合做实盘的程序化交易。行情数据一般包含完整的盘口、逐笔成交、资金流等延迟低稳定性有券商级别的保障但开通门槛也高通常要求资金量或者通过券商审核。最后是专业数据商像Wind、iFinD、聚源、恒生聚源、卡曼资管这类面向机构客户数据维度极全从基础行情到另类数据都有接口功能和响应速度都是顶级但费用也是顶级个人用户基本不用考虑。这个分层想清楚了选型就不会纠结。我的建议是做研究用免费开源做产品原型用Tushare做实盘用券商或量化平台API机构场景直接找数据商谈。下面我逐一展开讲怎么接。2. 免费数据源实操演示用AkShare把行情拉到本地如果你刚从零开始想最快速度看到一批股票的真实行情数据AkShare是最省事的路径。它是一个纯Python的开源库封装了大量公开数据源接口风格统一基本可以用一句话取数。2.1 安装与第一个取数请求环境准备很简单Python 3.7以上pip直接装pip install akshare装好后拉一只股票的日线行情代码非常直观import akshare as ak # 获取贵州茅台的历史行情前复权 df ak.stock_zh_a_hist(symbol600519, perioddaily, start_date20230101, end_date20241231, adjustqfq) print(df.head()) print(df.tail())这段代码里adjustqfq是前复权如果做回测建议统一用前复权因为后复权价格会偏离真实成交价而前复权更贴近当前市场的价格视角。如果做除权除息相关的分析可以用拿不复权原始数据。AkShare能拿的不只是日线。分钟线、实时行情、盘口五档、资金流向、龙虎榜、北向资金甚至期货、期权、外汇、加密货币它都有一堆接口。我经常用ak.stock_zh_a_spot_em()拿全市场实时快照大概几千只股票一秒内能返回做盘面扫描非常顺手。2.2 批量拉取与本地存储实际项目中很少只拉一只票更多是要维护一个自选股池的历史数据。这里有个效率坑千万不要在循环里一个一个地调接口AkShare的接口不是为高频批量调用设计的几十只股票顺序拉可能就要等好几分钟而且容易被数据源限流。我的做法是加缓存和并发控制。历史数据用本地文件缓存每天只增量更新。比如用Parquet格式存储读取快、压缩率高import akshare as ak import pandas as pd from pathlib import Path def update_daily_data(symbol: str, data_dir: str ./data): Path(data_dir).mkdir(exist_okTrue) file_path Path(data_dir) / f{symbol}.parquet # 读取本地已有数据 if file_path.exists(): old_df pd.read_parquet(file_path) start_date (pd.Timestamp(old_df[日期].max()) pd.Timedelta(days1)).strftime(%Y%m%d) else: old_df None start_date 20000101 # 只拉增量 new_df ak.stock_zh_a_hist(symbolsymbol, perioddaily, start_datestart_date, end_date20500101, adjustqfq) if old_df is not None and not new_df.empty: df pd.concat([old_df, new_df]).drop_duplicates(subset日期, keeplast) else: df new_df df.to_parquet(file_path, indexFalse) return df这段代码里我刻意把end_date写成了20500101是为了省去每次手动改日期的麻烦接口会自己截断到最新交易日。2.3 AkShare的已知缺陷要提前知道用了两年我总结AkShare主要几个问题无官方SLA接口随时可能失效。它本质是爬虫聚合数据源网页改版、加验证码、封IP都会导致接口突然报错。我遇到过最夸张的一次某数据源改版后AkShare停更了三天我的增量任务直接空跑。实时数据有延迟。股票快照数据大概有几秒到十几秒的延迟做日内高频肯定不行但做分钟级监控够用。字段稳定性一般。不同接口的字段名风格差异很大有的返回中文列名有的是英文有的还会因为数据源改版悄悄变字段。所以建议在存储层做一层字段标准化不要直接把原始返回存进数据库。3. 个人量化的标准方案Tushare Pro的接入与进阶如果你的数据需求超过了AkShare能稳定提供的范围比如需要完整的财务数据、指数成分股权重、板块资金流或者希望有更稳定的接口体验Tushare Pro是国内个人量化圈事实上的标准选择。3.1 注册、token与积分机制Tushare Pro用token鉴权注册后在个人主页拿到tokenPython里这样初始化import tushare as ts ts.set_token(你的token) pro ts.pro_api()这里必须说清楚积分机制Tushare Pro不是完全免费的积分决定了你能调用哪些接口、每分钟能调多少次。初始注册积分很少很多核心接口要2000积分以上才能调。积分可以通过社区贡献、分享、付费等方式获得。我的经验是如果只是拿日线数据和基础财务数据初始积分基本够用一旦需要分钟线、L2资金流这类接口就得认真考虑积分策略了。3.2 核心接口与数据结构Tushare的接口设计比较统一核心是传入参数、返回DataFrame。常用的几个# 日线行情 df pro.daily(trade_date20241201) # 某一交易日全市场日线 # 个股周线/月线 df pro.weekly(ts_code600519.SH, start_date20230101, end_date20241231) # 实时快照需要积分 df pro.stk_mins(ts_code600519.SH, freq1min, start_date20241201 09:30:00, end_date20241201 15:00:00)注意Tushare的股票代码格式是600519.SH、000001.SZ带了交易所后缀和AkShare的纯数字代码不一样写代码时要做代码格式的适配。另外Tushare日线是不复权数据复权因子单独用pro.adj_factor()拿需要自己计算复权价。这在刚开始会觉得麻烦但其实更灵活你想算前复权还是后复权都可以自己控制而不是被接口写死。3.3 调用频率限制与优雅重试Tushare Pro按积分高低有严格的频率限制基础积分通常是每分钟几十次调用。如果写循环批量拉取很容易触发限频接口返回类似抱歉您每分钟最多访问该接口X次的错误。我的处理方案是封装一个带重试和限速的请求函数import time import pandas as pd from functools import wraps def ts_request_with_retry(func, max_retries5, base_sleep2.0): wraps(func) def wrapper(*args, **kwargs): for attempt in range(max_retries): try: return func(*args, **kwargs) except Exception as e: if 每分钟最多访问 in str(e): sleep_time base_sleep * (attempt 1) print(f触发限频{sleep_time}秒后重试...) time.sleep(sleep_time) elif attempt max_retries - 1: raise e else: time.sleep(base_sleep) return pd.DataFrame() return wrapper这个封装用了指数退避的思路每次重试的等待时间递增既不会把自己封死也不会因为等待太久拖慢任务。4. 实盘场景怎么接券商终端与量化平台API的选择如果目标是实盘交易免费接口和Tushare都不够用因为行情和交易必须走合法合规的通道。这一层我推荐两条路券商自带的量化终端QMT/PTrade和第三方量化平台掘金、聚宽、米筐。4.1 QMT和PTrade实盘的最短路径QMTQuant Multi-Trading System和PTrade是目前国内券商主推的两套量化交易终端本质是券商提供的行情交易一体化客户端支持Python策略编写和运行。我重点说QMT因为它对行情的支持更完整。QMT的接入流程大概是找券商开通量化交易权限一般要求资金量达到一定门槛不同券商标准不一样常见的从几万到几十万不等下载QMT客户端用资金账号登录在客户端里编写Python策略或者通过xtquant库在外部连接QMT的行情接口用起来是这样的外部连接模式from xtquant import xtdata # 连接行情服务器 xtdata.connect() # 获取复权因子 xtdata.download_history_data(600519.SH, period1d, start_time20230101) # 获取历史行情 data xtdata.get_market_data_ex([], [600519.SH], period1d, start_time20230101, end_time20241231)QMT最大的优势是行情数据与交易通道同源不需要自己维护行情服务器也不存在行情和交易数据不一致的问题而且能拿到Level-2逐笔和十档盘口数据如果券商开通了这个权限。但QMT有几个我特别想吐槽的坑API文档质量参差不齐。有些版本的文档明显是从旧版复制来的函数签名对不上报错信息也含糊。我踩过最典型的一个坑是download_history_data必须要在get_market_data_ex之前调用否则返回空数据但文档里没写清楚这个顺序要求。数据本地缓存机制。QMT会把下载过的数据缓存在本地如果数据更新异常缓存可能脏掉需要手动清理缓存目录才会重新拉取。运行环境要求。官方客户端只支持Windows服务器部署需要考虑Windows Server环境。我见过有人非要在Linux上跑绕了一大圈最后还是得在Windows虚拟机里跑QMT。4.2 掘金、聚宽、米筐平台化的接入体验第三方量化平台的思路是把你需要的行情、回测、交易、风控都封装成统一API。以掘金为例它的接入方式是装一个客户端Python通过SDK连接本地或远程的终端from gm.api import * # 初始化 set_token(你的token) # 订阅实时行情 subscribe(symbolsSHSE.600519,SZSE.000001, frequency1d, count1) # 回调处理 def on_bar(context, bars): for bar in bars: print(bar.symbol, bar.close)这类平台的好处是封装做得比较好文档和社区完善初学者上手快坏处是平台本身的稳定性依赖第三方公司而且策略代码和平台API深度绑定将来想迁移到其他平台或者自研系统改动成本不小。4.3 实盘场景接入的核心考量行情、交易、费用的三角关系选择实盘行情通道时我建议用一个三角框架来评估行情质量、交易通道、资金门槛。方案行情质量交易通道资金门槛适合人群QMT高支持L2内置券商直连中高有实盘交易需求、需要L2数据PTrade中高内置券商直连中高偏好成熟托管环境的用户掘金/聚宽/米筐中等部分L2通过合作券商接入低个人量化、投研一体Tushare券商交易API中需另接交易API低需要灵活架构的开发者这里有个关键认知行情通道和交易通道不一定要是同一个。很多人以为实盘就必须用券商的行情其实不是。我的做法是行情用QMT稳定、快、L2回测用AkShare或Tushare历史数据更方便两者各司其职。但如果你追求极低延迟的套利策略那还是尽量让行情和交易同源减少消息流转的中间层。5. 行情数据落地的工程细节增量更新、字段对齐与存储选型接口本身只是起点真正决定一个行情系统好不好用的是数据落地层的设计。这块如果你没提前规划好后面会越改越痛苦。5.1 增量更新策略别每天全量拉很多人刚开始写数据任务是每天全量拉一次比如清空表然后重新拉1000只股票的日线。这个做法在小数据量时没问题但数据量一大处理和存储成本都上去了而且容易在拉取过程中出错导致数据不全。更好的方案是增量更新日线/分钟线记录每只股票本地数据的最大日期或时间戳下次只拉这个时间点之后的数据。前面AkShare的示例代码就是这个思路。快照数据按日期分区写入每天一个分区保留最近N天的热数据历史数据归档到冷存储。Tick/逐笔数据按小时或按天分区写入时做好去重因为这类数据偶尔会因为重连导致重复推送。5.2 字段标准化统一命名是命根子不同数据源的字段命名差异很大比如日期字段AkShare叫日期Tushare叫trade_dateQMT叫time。如果不做标准化你的策略代码一旦切换数据源全部要重写。我维护一个统一的行情Schema大致是这样标准字段含义AkShare映射Tushare映射QMT映射symbol股票代码带后缀需转换ts_code带后缀代码datetime时间戳日期/时间trade_date/timetimeopen开盘价开盘openopenhigh最高价最高highhighlow最低价最低lowlowclose收盘价收盘closeclosevolume成交量成交量volvolumeamount成交额成交额amountamount在采集层加一个转换函数把各源数据统一成这个Schema再入库下游所有模块只认这一套标准字段。这个习惯帮我省了太多事强烈建议一开始就做好。5.3 存储选型从CSV到数据库/数据湖不同阶段用不同的存储方案个人研究阶段CSV/Parquet文件足够简单直接读取快不需要额外服务。建议用Parquet而非CSV体积小一个数量级读速也快很多。策略回测阶段SQLite或者DuckDB足够单机查询方便支持SQL分析。实盘/团队协作阶段用PostgreSQL或者ClickHouse。行情数据写多读少、追加为主ClickHouse的压缩比和查询性能非常适合但运维成本也高一个人没必要硬上。海量Tick数据考虑对象存储分区表结构或者专业时序数据库如InfluxDB。我个人的路径是从CSV升级到DuckDB再升级到PostgreSQL每次升级都是因为前一个方案的痛点足够明显了才动。不要一上来就搞分布式行情数据量大但还没大到个人电脑处理不了的程度别为了技术炫耀而引入复杂度。6. 限频、重连和脏数据实盘中那些不容易注意但必须处理的点最后这部分我专门聊聊实盘过程中一定会遇到、但文档不会告诉你的问题。6.1 限频不只是Tushare才有QMT也会限免费接口限频大家有心理准备但很多人不知道QMT这类券商终端同样有限频机制。尤其当你用get_market_data_ex批量订阅几百只股票时如果请求频率过高客户端会直接拒绝服务或者延迟响应。我的经验是批量请求时做一次请求合并不要循环里粒度太细地调接口。比如获取100只股票1分钟K线用get_market_data_ex一次性传100只股票代码而不是在循环里一只只调。6.2 交易日历你自己维护一份别依赖任何单一数据源交易日的判断直接影响增量更新能不能正确执行。有的节假日调休周末补班但股市不开盘这种时候如果你用今天是不是周末来判断是否更新就会出错。我建议独立维护一份交易日历表可以人工更新也可以用数据源接口自动生成。Tushare的pro.trade_cal()可以拿到完整的交易日历但注意它也可能因为节假日安排调整而有变化最好每年查验一次。6.3 脏数据的识别与清洗行情数据的脏数据问题比很多人想象中严重。我遇到过的典型情况零值/空值停牌股票在部分接口里成交量、成交额为0或者为NaN但价格字段可能保留停牌前价格。策略里要明确停牌股的处理方式。异常价格跳动比如某只股票数据里突然出现一根跌了90%的K线其实可能是数据源昨天的错误数据覆盖了。我会在入库前做一个简单的异常检测价格变动超过30%就告警人工确认。复权因子不一致同一只股票A接口的复权因子和B接口可能因为除权除息时间不同产生微差长期累积会导致回测结果对不上。尽量全链路用同一个数据源或者统一复权因子的更新逻辑。6.4 K线闭合的时序问题这个坑特别隐蔽。日内实时K线是动态变化的最后一根1分钟K线在下一秒来临前是未闭合的它的收盘价、成交量都还在变。如果策略在盘中做实时计算一定要区分当前正在形成的K线和已经闭合的历史K线。我在代码里的习惯是实时订阅回调里拿到的bar是窗口结束前一刻的快照如果策略对准确性敏感就设置一个延迟确认比如等3秒再处理新闭合的K线确认它不再变化。这在分钟级策略里影响不大但在秒级或tick级策略里可能导致信号错误。7. 接入方案的分层总结看到这里你会发现股票行情接口的接入并不是选一个接口就完事更像是一套分层方案研究层AkShare、Tushare Pro解决历史数据和基础数据需求实时层QMT、掘金等平台API解决盘中实时行情需求交易层券商量化终端解决合法合规的交易通道需求存储层本地文件到数据库的演进解决数据落地和快速读取需求每一层选什么工具取决于你的真实场景和阶段。做研究时不需要L2数据做实盘时不能依赖爬虫接口程序化交易必须走券商合规通道。这个认知比任何一段代码都有价值。我最深的个人体会是不要迷信最全这个说法行情接口没有一个方案能包打天下。AkShare再方便也只是免费层QMT再强也只面向特定券商客户。把需求拆清楚把每一层选对工具比满世界找万能接口靠谱得多。如果读完你还不确定从哪开始那就先装一个AkShare拉一只股票的数据存成本地文件跑通一次通宵更新任务。这套流程跑顺了你会发现其他接口的接入也只是换一层API的事。