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

免费金融数据接口Python接入全攻略:股票期货外汇数字货币全覆盖

发布时间:2026/9/25 10:08:48

资讯中心
01
ARTICLE

免费金融数据接口Python接入全攻略:股票期货外汇数字货币全覆盖

免费金融数据接口Python接入全攻略:股票期货外汇数字货币全覆盖
做量化、搞数据研究或者单纯想盯盘的朋友八成都有过这种体验指标想法写了一堆结果第一步就被行情数据卡住。打开Wind、Choice这类商业终端一看授权价格个人用户基本劝退去东财、腾讯网页上手动复制又low又容易出错。这几年我陆陆续续把股票、期货、外汇、数字货币四类市场的免费行情接口都接了个遍中间踩了不少坑也攒下一套可以直接用的Python接入方案。这篇就从头到尾讲清楚免费金融数据接口到底从哪来、实时性真实水平如何、代码怎么写不会跑两天就挂以及哪些坑你提前知道能省下大量时间。这篇文章适合谁看想搭建个人研究数据库的学生、独立量化爱好者、做应用开发的工程师都适用。不保证能替代商业终端做专业投资分析但用来做策略回测、盯盘提醒、数据可视化、个人研究足够用了。1. 四个市场的免费数据接口到底从哪里来先别急着复制代码搞清楚免费接口的来源比代码本身更重要。很多人接口用着用着就废了往往不是自己写错而是压根不知道背后数据是怎么来的。1.1 免费接口的两条来源路径市面上所有免费金融数据接口追根溯源只有两条路径。第一条路径是官方开放数据。比如欧洲央行公布的历史汇率、各国央行和交易所公开的市场数据以及加密货币交易所主动开放的行情接口。这一类接口的特点是相对稳定、格式规范、有明确的调用限制数据可信度高。为什么交易所愿意免费开放行情因为行情数据是引流产品真正的利润在交易手续费、增值服务和企业级数据授权上。第二条路径是爬虫类封装接口。典型代表是Python生态里的akshare、efinance这类库。它们的原理是把新浪财经、东方财富、交易所官网等公开页面上的数据通过程序化抓取后清洗成规整的DataFrame。这条路线的优势是零成本、覆盖面广但缺点是本质是网页爬虫一旦上游网页改版、字段改名或者加了反爬逻辑接口可能一夜之间失效。所以碰到这种接口最先要养成的习惯就是锁版本、做缓存、写异常兜底。理解这两条路径之后你就能明白为什么不同接口的可靠度和实时性差别这么大也就能理解后文我为什么反复强调“数据源切换”和“容错设计”。1.2 股票数据的三个开源主力A股免费数据接口里最常被提到的就是tushare、akshare和baostock。tushare是老牌接口数据覆盖面广但高频分钟级数据需要积分积分靠贡献社区或付费获取。对纯新手来说注册后拿基础积分能用日线级别的行情做研究和回测但想用它做盘中分钟级跟踪就受限了。akshare是我用得最多的一个。它整合了A股、港美股、期货、基金、宏观数据等大量内容接口命名非常直白比如股票实时快照就叫stock_zh_a_spot_em意思是东方财富的A股全市场快照。缺点是更新频繁有时候两个小版本之间函数名就变了。我自己的习惯是固定版本号每次升级前先跑一遍冒烟测试确认核心函数没变化再上生产。baostock的特点是免费且稳重历史日线数据质量不错适合做中长期回测。但它对实时行情支持有限分钟级数据也偏弱不太适合做日内盯盘类应用。如果你只是需要一个“知道今日所有A股最新价”的免费源akshare的东方财富快照接口是最快的路径代码后面会给。1.3 期货、外汇、数字货币怎么挑接口国内期货的免费数据源比股票更少。CTP是正规军行情质量最高但它需要期货账户和期货公司授权的接口个人申请门槛较高而且主要用于实盘交易终端不是用来搭个人数据库的。免费研究场景下我建议用akshare里的期货实时行情接口数据源是新浪财经的期货页面基本覆盖国内主力合约。要注意的是这里的“主力合约”判定和交易所官方不完全一致做研究可以做精确换月回测时得自己再加工。外汇这块反而是四个市场里最好处理的。因为汇率本质上是一个相对公开、中心化的数据欧洲央行每天都会发布参考汇率于是就有了frankfurter这类完全免费的API。它基于欧洲央行官方数据不需要注册、不需要Key请求格式也很干净。做跨境数据建模、汇率换算、财务数据处理都够用。如果想拿更多历史数据或更多货币对exchangerate.host、open.er-api.com也都是免费注册就能用的方案。数字货币的数据源最简单粗暴主流加密货币交易所几乎都把行情接口免费开放给开发者。不需要注册也能调REST接口拿最新价只是有频率限制。比如用交易所公开行情接口请求/api/v3/ticker/price就能拿到BTC、ETH等币种的实时价格。这里提醒一句由于不同地区对加密货币交易平台的合规要求不同接入之前先确认你所在区域允许访问的合规数据源下面是通用的代码逻辑。2. 实时API的“实时”含金量免费接口延迟实测“实时API”听起来很厉害但免费接口的实时性到底处在什么水平需要先给个判断标准。否则你按毫秒级交易的预期去用一定会失望。2.1 免费接口的延迟水平与延迟来源先说结论免费接口大多数是秒级延迟能做到几百毫秒已经算优秀。以我实测的经验来看A股免费实时行情接口基于新浪、东财页面抓取的正常延迟大概在1秒到3秒之间行情刷新频率一般也是3秒左右一次。如果遇到接口服务器繁忙或者网络抖动延迟到10秒也不奇怪。数字货币交易所的公开REST接口延迟通常在几百毫秒级别因为交易所本身就靠行情数据做基础设施性能投入比较大。外汇免费API的实时性要差一些因为官方参考汇率本身就不是逐笔撮合出来的行情更新时间可能是分钟级甚至每天几次。这里要理解一个链路免费接口的延迟并不是“你请求一次之后交易所才返回”而是数据经过“交易所数据源 - 爬虫程序抓取 - 数据整理 - 缓存 - 你的请求”这么一串流程。每个环节都会增加延迟尤其爬虫类的免费接口往往是别人程序定时去抓一次页面缓存下来再给你所以延迟是叠加出来的。2.2 不同量化场景对实时性的真实需求判断接口够不够用关键不是看延迟数字而是看你的场景对时效性的容忍度。如果你做的是日频或者周频的策略研究比如选股、财务因子分析、指数定投跟踪那延迟几秒还是几十秒没有任何区别真正要关注的是历史数据的完整性和复权质量。如果你是做分钟级别的盘中跟踪比如监控异动、做盘口提醒那秒级的免费接口是够用的前提是接口稳定别断。如果你要做tick级套利、抢单、高频交易免费接口基本就不用想了这个层级需要的是券商或交易所提供的专用行情通道而且往往是收费的。我自己有个比较务实的判断标准当你的策略持仓周期在分钟级以上时免费接口的实时性是合格的当你的策略需要“看到即交易”时免费接口只能用来做辅助监控不能做核心信号源。2.3 免费接口的隐形天花板频控和配额免费接口最容易被忽视的是请求频率限制。这不是写在你脸上的规则但一旦超了轻则限速重则封IP。数字货币交易所的公开接口通常有明确的权重限制比如每分钟最多多少请求。A股的免费爬虫接口虽然没有明确文档但你如果并发开太多很容易触发对方服务器的反爬策略导致IP被临时限制。外汇API通常给出免费套餐的每月请求限额超过之后要么等重置要么升级付费。我的建议是三个字慢一点。个人研究场景完全没必要毫秒级并发轮询一秒一次甚至几秒一次已经能覆盖绝大多数需求。如果手上有几百个股票要盯也不要用循环去快速请求而是分批拉全市场快照在本地做过滤。3. 一个函数搞定股票、期货、外汇、数字货币的实时行情聊完选型和实时性现在进入正题怎么把四类市场统一接入起来让调用方只面对一种数据结构。这样后面做监控、存储、告警都只需要写一遍逻辑。3.1 统一数据结构的思路四类市场返回的数据字段各不相同A股叫“最新价”期货叫“当前价”外汇叫“汇率”数字货币叫“price”。如果每个市场单独一套程序后续维护成本会很高。我采用的方案是设计一个统一的行情记录结构只保留最核心的字段交易标的、最新价格、报价时间、数据来源。调用方不需要关心底层对接的是哪个市场拿到就是一个统一的记录。这样的好处非常明显新增市场时只需要写一个对应的拉取函数然后在统一入口里加一个分支即可下游的存储逻辑、告警逻辑、展示逻辑全部复用。实际开发过程中我所有的行情监控脚本都基于这套结构。3.2 核心代码fetch_quote模块下面这份代码是一个最小可用版本。依赖只需要akshare和requests。import datetime import json import time import akshare as ak import requests # 统一行情记录结构 def build_quote(market, symbol, price, source): if price is None: return None return { market: market, # stock/futures/fx/crypto symbol: symbol, # 600519 / BTCUSDT / USDCNY price: float(price), time: datetime.datetime.now().strftime(%Y-%m-%d %H:%M:%S), source: source } # 1. A股实时行情用akshare拉全市场快照后按代码过滤 def fetch_cn_stock(symbol): try: df ak.stock_zh_a_spot_em() row df[df[代码] symbol] if row.empty: return None price row.iloc[0][最新价] # 停牌股票可能返回0或空值直接过滤 if price in (None, 0, -): return None return build_quote(stock, symbol, price, akshare_em) except Exception as e: print(f[stock] {symbol} error: {e}) return None # 2. 国内期货实时行情akshare有对应封装函数 def fetch_cn_futures(symbol): try: # 不同版本的akshare函数签名略有差异如果报错可以先看函数信息 df ak.futures_zh_spot(symbolsymbol) # 这里取最新价字段尽可能做兼容处理 price_col [col for col in df.columns if 当前 in col or price in col.lower()] if not price_col or df.empty: return None price df.iloc[0][price_col[0]] return build_quote(futures, symbol, price, akshare_future) except Exception as e: print(f[futures] {symbol} error: {e}) return None # 3. 外汇汇率frankfurter背后是欧洲央行官方数据 def fetch_fx(from_currency, to_currency): try: url fhttps://api.frankfurter.app/latest?from{from_currency}to{to_currency} resp requests.get(url, timeout5) data resp.json() price data[rates][to_currency] symbol f{from_currency}/{to_currency} return build_quote(fx, symbol, price, frankfurter) except Exception as e: print(f[fx] {from_currency}/{to_currency} error: {e}) return None # 4. 数字货币行情使用主流交易所公开API示例 def fetch_crypto(symbol): try: # symbol 如 BTCUSDT url fhttps://api.binance.com/api/v3/ticker/price?symbol{symbol} resp requests.get(url, timeout5) data resp.json() price data[price] return build_quote(crypto, symbol, price, binance) except Exception as e: print(f[crypto] {symbol} error: {e}) return None # 统一入口 def fetch_quote(market, symbol, paramsNone): if market stock: return fetch_cn_stock(symbol) elif market futures: return fetch_cn_futures(symbol) elif market fx: params params or {} return fetch_fx(params.get(from, USD), params.get(to, CNY)) elif market crypto: return fetch_crypto(symbol) return None几个关键点需要说一下。第一每个函数都单独做了异常捕获这是刻意的。免费接口随时可能因为网络、升级、反爬而报错如果异常直接抛出来整个监控进程就会挂掉。实际运维中一个数据源挂了其他数据源应该完全不受影响。第二所有函数返回的都是同一个字典结构。调用方拿到字典后可以做统一处理。如果某个接口返回None说明本次拉取失败下游可以跳过或告警。第三代码里的字段名我尽量做了兼容处理比如期货的最新价字段可能在不同版本里叫“当前价”或“price”。但更稳妥的做法是把akshare版本固定下来然后用dir(ak)查看实际函数名。3.3 调度与增量落盘数据接口不能手动一条条调用做研究至少要跑一个后台轮询把行情持续存下来。下面这段代码是一个简单的轮询器每隔5秒拉一次不同市场的指定标的并用标准库csv把数据增量写入文件。import csv import os def append_quote_to_csv(quote, filepath): if quote is None: return file_exists os.path.exists(filepath) with open(filepath, a, newline, encodingutf-8) as f: writer csv.DictWriter(f, fieldnameslist(quote.keys())) if not file_exists: writer.writeheader() writer.writerow(quote) def run_polling(interval5): targets [ (stock, 600519, None), (crypto, BTCUSDT, None), (fx, USDCNY, {from: USD, to: CNY}), (futures, V2305, None), ] filepath quotes.csv while True: for market, symbol, params in targets: quote fetch_quote(market, symbol, params) append_quote_to_csv(quote, filepath) if quote: print(f{quote[time]} | {market} {symbol} | {quote[price]}) time.sleep(interval) if __name__ __main__: run_polling()如果你的需求更复杂比如按天拆文件、多标的高频轮询、失败重试我建议把调度部分换成APScheduler或者直接用分布式调度框架。对于个人研究来说这段代码的运行效果已经相当不错了。我个人的习惯是把数据文件按日期拆分比如quotes_20250601.csv避免单文件无限增长后续做历史回放也方便。4. 从单次请求到自动轮询把接口真正跑起来代码写好了但直接扔到服务器上跑大概率前几个小时没事过两天就出幺蛾子。这一部分讲怎么把接口变成真正可靠的数据采集服务。4.1 连通性自检脚本第一次接入时先别急着跑轮询先做一轮连通性自检。把每个市场挨个请求一次记录延迟和返回结果确认所有数据源都通了再跑长时间任务。def self_check(): checks [ (stock, 600519, None), (futures, V2305, None), (fx, USDCNY, {from: USD, to: CNY}), (crypto, BTCUSDT, None), ] for item in checks: t0 time.time() q fetch_quote(item[0], item[1], item[2]) cost round(time.time() - t0, 3) print(f{item[0]} | {item[1]} | 耗时{cost}s | 结果{q})自检的作用不是跑一次就完事而是建立基线。以后发现数据长时间不更新先跑一遍自检马上能定位是哪个市场的问题而不是乱猜。我们实际维护中最常用的排查手段就是这个脚本。4.2 定时任务与数据落地轮询间隔的确定有讲究。有人觉得越快越好实际上过快的请求只会增加被封的风险而且很多免费数据源本身更新频率就是秒级你比它快也没用。我一般这样设置A股现货行情轮询间隔3秒到5秒因为免费源本身刷新频率就在3秒级别。数字货币行情轮询间隔1秒到3秒交易所REST接口响应很快但没必要太激进。外汇汇率轮询间隔30秒甚至更长因为官方汇率不会跳动那么频繁。期货行情轮询间隔3秒到5秒和A股类似。数据落盘方面前面用的csv方案适合数据量小的场景。如果每天要存几万行建议改用SQLite插入效率更高查询也更方便。我自己的做法是SQLite按交易日建表加一个time字段做索引。4.3 时间统一与数据清洗这四个市场的返回时间格式不同。A股和期货接口返回的是北京时间数字货币REST接口返回的是Unix毫秒时间戳外汇接口返回的是日期加币种。如果直接混在一起用时间对齐会出问题。我建议所有落盘数据统一成北京时间字符串同时保留一个“原始时间”字段。数字货币的时间戳转换代码很简单import datetime def ts_to_beijing(ts_ms): dt datetime.datetime.fromtimestamp(ts_ms / 1000, tzdatetime.timezone.utc) return (dt datetime.timedelta(hours8)).strftime(%Y-%m-%d %H:%M:%S)还要注意一些脏数据问题股票停牌时价格可能为0外汇接口偶尔返回None数字货币网络波动时可能拿到重复数据。最简单的处理方式是“异常值不落盘”并且对连续两次价格完全相同的数据做一个去重标记。真正做策略之前数据清洗这部分时间花得越足后面麻烦越少。5. 实操中最容易踩的坑与排查经验最后这部分是我最想写的。很多坑不是看文档能看出来的都是跑着跑着才暴露的。5.1 接口升级导致函数失效akshare这类库迭代非常快有时候几个月升一次大版本函数名说变就变。最典型的是我遇到过futures_zh_spot函数在某版本后参数从字符串改成了枚举结果代码没动突然报TypeError。解决思路有两个方向。一个是锁版本直接在依赖文件里固定你验证过的akshare版本不轻易升级。另一个是写冒烟测试每周末跑一次自检脚本确认所有核心接口都正常有问题提前发现。两个方向最好同时做。5.2 限流、被封与备源切换免费数据源被限制不是轰然一下而是温水煮青蛙。通常先表现为响应变慢然后部分请求返回空数据最后直接拒绝连接。如果轮询脚本里没有做异常兜底很有可能数据从昨天开始就是空的你还不知道。我的经验是任何重要数据源都要有一个备用源。比如A股行情东方财富的数据源被封了可以切换到腾讯的行情接口数字货币交易所A不通就换交易所B。切换的动作要自动化不能等人发现。最简单的实现就是主源连续失败3次后自动切换备用源并打一条告警日志。5.3 行情数据本身的质量问题免费接口另一个容易忽略的问题是数据质量。我遇到过几个典型案例股票停牌导致价格突然为0如果不做过滤会把0写入数据库后续算涨跌幅直接出现负的百分之百期货夜盘时间戳显示的是第二天日期导致日线切分错位数字货币某些币种流动性差成交价长期不更新看起来像接口挂了其实是市场没有成交。处理思路就一句话永远不要相信免费接口返回的数据是干净的。价格合法范围检查、时间戳合理性检查、更新频率检查这三样是基础中的基础。做实盘策略之前最好拿一个权威数据源做一段时间的交叉验证确认误差在可接受范围内。5.4 从Wind迁移到免费接口注意什么最近不少人问我团队之前用的是Wind的Python接口现在预算收紧想换免费方案能不能直接平替。我的回答是业务逻辑可以迁移但代码不能直接换。Wind接口最大的优势是字段全、标准统一、服务稳定。免费接口虽然也能拿到价格、成交量、涨跌幅等核心字段但字段命名不统一数据精度略有差异复权方式也需要自己确认。迁移时最好的做法是写一层字段映射函数把免费接口的列名统一映射成和Wind一致这样下游的CTA策略、回测引擎、风控模块都不需要大改。另外特别提醒Wind的某些特色数据比如盈利预测、一致预期、龙虎榜明细免费接口不一定全都有。迁移之前先把业务需要的字段清单列出来逐一确认免费接口能否覆盖。不要等代码写完才发现某个核心字段没有数据来源。免费接口并不是万能的但它给了个人开发者一个很低的试错门槛。我自己的体会是数据源这件事没有一劳永逸的方案重点不是找到“最好”的接口而是搭好一套“即使某个源挂了系统还能继续跑”的框架。风险厌恶型的做法就是多源备份、异常兜底、定期自检。如果你正准备搭自己的行情数据库别一上来就追求复杂架构先用这套最小方案把数据存起来跑通后再逐步加监控、加告警、加备用源你会发现金融数据接入这件事远没有想象中那么神秘。
02
RELATED NEWS

相关资讯

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

03
WHY YAOTU

想打造同款高转化官网?

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

◈

场景化定制

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

◐

营销型架构

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

▲

全周期服务

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

免费获取你的建站方案

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