做量化交易或者日常盯盘的人多多少少都动过自己拉数据的念头。市面上付费数据源不便宜免费的数据又经常缺字段、缺历史、更新延迟。我自己的做法是直接从东方财富的公开接口抓尤其是分时数据接口稳定、字段全、延迟低关键是代码写起来不费劲。这篇文章就围绕东方财富分时数据获取这件事展开从接口选型、参数含义、完整代码到基于分时数据计算多空趋势指标的思路和源码最后是实操中容易踩的坑。不管你只是想做个盯盘工具还是准备给自己的量化策略补充日内数据这篇都值得花五分钟看完。1. 先搞清楚东方财富的分时数据到底从哪里来1.1 我为什么选东方财富作为数据源做股票数据抓取可选的数据源很多新浪、腾讯、网易、东方财富还有券商自带的接口。我自己最终长期用的是东方财富原因有三个。第一接口返回的数据非常规整分时数据直接是逗号分隔的纯文本用简单的split就能解析成结构化数据不需要处理JSON嵌套也没有乱七八糟的加密参数。第二字段覆盖面足够广价格、均价、成交量、成交额、涨跌幅这些日内指标都有做技术分析绰绰有余。第三也是最关键的接口相对稳定不太容易因为请求频率低就封IP我自己实测每秒一次以内的请求频率持续跑一天都没问题。新浪的接口虽然也能用但经常出现数据延迟而且返回的是js变量包装的文本格式一致性差一些。腾讯的接口延迟最低但历史分钟数据补起来麻烦。综合下来东方财富在“免费、稳定、好解析”这三者之间的平衡是最好的。1.2 两个常用接口趋势分时与分钟K线东方财富和分时数据相关的接口主要有两个我这里把它们都列出来方便你理解后续代码里用的是哪一个。第一个是趋势分时接口对应的是行情软件里按回车键看到的那条白色分时价格线和黄色均价线。它的特点是一天只有240个采样点A股每天4小时交易每分钟1个点返回的是从9:30到15:00每个自然分钟的价格快照。这个接口是最贴近“分时图”这个概念的。第二个是分钟K线接口返回的是1分钟、5分钟、15分钟、30分钟、60分钟等任意周期的K线数据。它可以拉历史比如你要回测过去一年的5分钟K线用这个接口最合适。它和趋势分时接口的区别在于K线是聚合后的数据每个周期的开高低收、成交量趋势分时是逐分钟的快照数据。一句话总结如果只是想画分时图、判断当日多空强弱用趋势分时接口如果要做分钟级别的策略回测用分钟K线接口。两个接口都属于东方财富的数据接口体系请求方式是类似的。2. 动手之前接口参数与字段含义全拆解2.1 secid藏在数据里最大的坑无论用哪个接口都绕不开secid这个参数。它的格式是“市场代码.股票代码”市场代码只有两个值1代表上海证券交易所0代表深圳证券交易所。举个例子平安银行的股票代码是000001它属于深交所所以secid0.000001。浦发银行的代码是600000属于上交所secid1.600000。江南嘉捷这类北交所股票我在实践中发现用0开头通常是有效的不过北交所的字段返回情况和沪深略有差异需要单独处理。这个参数看起来简单但实际容易搞错。很多人在网上找到别人的代码复制过来结果自己换成另一只股票就报错了问题就出在这里。你不能只改股票代码必须连市场前缀一起改。建议的做法是用一个函数根据代码前缀自动判断市场6开头的是上交所0开头和3开头的是深交所。2.2 trends接口的核心参数与返回结构趋势分时接口的完整URL大概长这样https://push2his.eastmoney.com/api/qt/stock/trends/get?secid1.600000fields1f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13fields2f51,f52,f53,f54,f55,f56,f57,f58ndays1iscr0iscca0utfa5fd1943c7b386f172d6893dbfba10b参数说明如下ndays拉取多少个交易日的数据填1就是当天。fields1股票基础信息字段比如股票代码、名称、市场状态等一般固定用上面那一串就行。fields2分时数据的字段列表这才是重点。f51是日期时间f52是当前时刻价格f53是均价f54是成交量f55是成交额f56是最新价相对昨日收盘的涨跌幅单位是百分比吗不是单位是涨跌幅数值比如1.23表示涨1.23%f57是涨跌额f58是换手率。返回的JSON结构里最关键的是data.trends这个数组。每个元素是一个字符串像这样2025-01-10 09:30,10.15,10.10,11200,1136800,0.50,0.045,0.42用split(,)切成列表后从左到右依次对应fields2里定义的字段。建议你把这份对应关系保持在一张表里后面写代码解析时反复对照。2.3 字段对应关系哪些列是价格哪些是量我把自己常用的两套字段对应关系整理成了一张表。分时数据trends和分钟K线kline的字段顺序不同容易混。分时数据字段对应表字段名含义单位备注f51日期时间字符串格式yyyy-MM-dd HH:mmf52最新价元该分钟收盘价f53均价元当日累计成交额/累计成交量f54成交量手注意是手1手100股f55成交额元该分钟成交金额f56涨跌幅%相对昨日收盘价f57涨跌额元相对昨日收盘价f58换手率%当日累计换手分钟K线字段对应表分钟K线接口fields2通常设置成f51到f61顺序是日期、开、收、高、低、成交量、成交额、振幅、涨跌幅、涨跌额、换手率。这里有个特别容易搞混的地方K线字段的顺序是开、收、高、低不是开高低收。我第一次写解析代码时顺手按“开高低收”的顺序解析结果算出来的指标全错了。后来只能对着接口返回数据仔细核对才反应过来。3. Python快速抓分时数据完整可跑代码3.1 环境准备与依赖写代码之前先准备好环境。我用的是Python 3.9以上版本核心依赖只有两个requests用来发HTTP请求pandas用来做数据处理。另外建议装一个pytz后面处理时区要用。pip install requests pandas pytz如果你只是想快速测试不装pandas也行用纯Python的列表就能接住数据。但后续要做指标计算pandas的效率会高很多建议装上。3.2 抓取当日分时数据的核心代码下面这段代码是我实际在用的版本可以去掉了多余的东西保留了最核心的逻辑。它的流程是先根据股票代码判断市场然后请求趋势分时接口把返回的trends数组解析成结构化的列表。import requests import pandas as pd def get_secid(stock_code: str) - str: 根据股票代码自动判断市场前缀。 6开头是沪市0和3开头是深市北交所暂时也按深市处理。 if stock_code.startswith(6): return f1.{stock_code} elif stock_code.startswith((0, 3)): return f0.{stock_code} else: raise ValueError(f无法识别股票代码: {stock_code}) def fetch_trends(stock_code: str, ndays: int 1) - pd.DataFrame: 获取东方财富分时数据返回DataFrame。 secid get_secid(stock_code) url https://push2his.eastmoney.com/api/qt/stock/trends/get params { secid: secid, fields1: f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13, fields2: f51,f52,f53,f54,f55,f56,f57,f58, ndays: ndays, iscr: 0, iscca: 0, ut: fa5fd1943c7b386f172d6893dbfba10b, } headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: https://quote.eastmoney.com/, } resp requests.get(url, paramsparams, headersheaders, timeout10) resp.raise_for_status() data resp.json().get(data) if not data or trends not in data: raise RuntimeError(f接口返回异常: {data}) rows [] for item in data[trends]: parts item.split(,) rows.append({ time: parts[0], price: float(parts[1]), avg_price: float(parts[2]), volume: float(parts[3]), amount: float(parts[4]), pct_change: float(parts[5]), change: float(parts[6]), turnover: float(parts[7]), }) df pd.DataFrame(rows) df[time] pd.to_datetime(df[time]) return df if __name__ __main__: df fetch_trends(600000) print(df.head()) print(df.tail())这段代码跑通之后你手里就有了一个标准的DataFrame包含当天从9:30到15:00每一分钟的价格、均价、成交量等信息。这是后续所有衍生指标计算的基础。3.3 解析成DataFrame并追加涨跌幅等衍生字段拿到了原始的分时数据之后直接用还不够通常还需要追加一些衍生字段。比如分钟成交量占比每分钟成交量占全天成交量的比例用来判断哪个时段交易最活跃。价格位置最新价相对于当日最高价和最低价的位置公式是最新价 - 最低价/最高价 - 最低价这个指标用来看当前价格处于当日区间的什么水平。均线偏离度最新价 - 均价/ 均价衡量价格偏离当日持仓成本的程度。这些衍生字段的处理我直接写在同一个解析流程里代码不复杂但是很实用。def enrich_trends(df: pd.DataFrame) - pd.DataFrame: 在原始分时数据基础上追加衍生字段。 df df.copy() day_high df[price].max() day_low df[price].min() df[price_position] (df[price] - day_low) / (day_high - day_low) df[avg_deviation] (df[price] - df[avg_price]) / df[avg_price] * 100 df[volume_pct] df[volume] / df[volume].sum() * 100 df[cum_amount] df[amount].cumsum() return df做完这一步你的分时数据就已经具备了做简单量化分析的基础。接下来我们聊一个很多人关心的东西多空趋势指标。4. 从分时数据到多空趋势指标源码与思路4.1 多空趋势指标怎么设计才合理搜“东方财富多空趋势指标源码”的人很多但真正理解指标原理的没几个。我在这里不直接给你一个可以抄的指标源码因为不同人的交易风格不一样参数也不一样。我先讲清楚设计思路再给出一套可落地的基础版本。多空趋势指标的核心本质上是解决一个问题当前价格相对于市场平均持仓成本的位置。价格在成本线之上多方占优价格在成本线之下空方占优。分时数据里的均价线avg_price就是全市场当日持仓成本的平均值。所以最简单的多空趋势指标就是价格偏离均价的幅度。但这个指标太粗糙了单看价格偏离度忽略了成交量的权重。一个高开低走的股票均价线在开盘时被拉到很高但随后价格快速跌破均价这个过程中的成交量如果放大说明抛压很重。所以合理的设计思路应该是价格偏离度结合成交量确认。4.2 分时均线源码示例我们先写一个最基础的分时多空趋势指标。它的逻辑很简单当价格在均线上方且成交量放大时标记为多方强当价格在均线下方且成交量放大时标记为空方强。成交量是否放大用当前分钟量和过去N分钟平均量的比值来判断我个人习惯用过去20分钟的均值作为基准。def multi_short_trend(df: pd.DataFrame, volume_window: int 20) - pd.DataFrame: 基于分时数据计算多空趋势指标。 返回的DataFrame中trend列取值 1代表多方强势-1代表空方强势0代表震荡。 df df.copy() df[vol_ma] df[volume].rolling(windowvolume_window, min_periods1).mean() df[vol_ratio] df[volume] / df[vol_ma] trend [] for _, row in df.iterrows(): if row[price] row[avg_price] and row[vol_ratio] 1.2: trend.append(1) elif row[price] row[avg_price] and row[vol_ratio] 1.2: trend.append(-1) else: trend.append(0) df[trend] trend return df这段代码的实际效果是在分时图上标注出那些价格偏离均价且放量的关键节点。你用来复盘昨日走势的时候会发现自己能很清楚地看到每波拉升和杀跌对应的情绪爆发点。4.3 量价配合与背离的简单实现上面的版本还有一个缺陷它只看瞬间的状态没有考虑趋势的延续和背离。实盘中经常出现一种情况价格创了日内新高但成交量明显萎缩这就是量价背离大概率是诱多信号。量价背离的判断逻辑可以这样实现连续两个时间点价格高点在抬升但对应的成交量峰值在下降就标记背离。更严谨一点可以用价格涨跌幅和量能变化率的相关系数来量化。def detect_divergence(df: pd.DataFrame, lookback: int 30) - pd.DataFrame: 检测分时数据中的量价背离。 返回DataFrame中新增divergence列1为顶背离-1为底背离0为无背离。 df df.copy() df[price_high] df[price].rolling(windowlookback, min_periods1).max() df[vol_high] df[volume].rolling(windowlookback, min_periods1).max() divergence [] for i in range(len(df)): if i lookback: divergence.append(0) continue price_new_high df[price].iloc[i] df[price_high].iloc[i - 1] vol_not_new_high df[volume].iloc[i] df[vol_high].iloc[i - 1] * 0.8 if price_new_high and vol_not_new_high: divergence.append(1) else: divergence.append(0) df[divergence] divergence return df这套逻辑不是万能的但它能帮你把分时图里肉眼容易忽略的细节用代码固化下来。比如你复盘一只股票全天走势软件上只能看到价格和均线的位置关系但代码可以精确告诉你14:23这次创出日内新高的时候量能只有前高的60%这在操作上就是一个明确的减仓信号。5. 实操中必踩的坑与排查技巧5.1 接口返回空、403异常码怎么处理东方财富的接口虽然稳定但不是绝对没有反爬机制。我自己遇到的比较多的两类异常一是请求频率过高触发限制二是某些网络环境下需要额外的请求头。应对方案主要是两个方向第一降低请求频率。做数据抓取不是做实时行情推送一天240个数据点你不需要每秒请求一次。做盘中监控的建议至少间隔3秒以上再请求一次做盘后复盘的一天跑一次就够。实测下来超过每秒2次的持续请求半小时内大概率会被临时限制访问。第二补全请求头。Referer和User-Agent这两个字段最好带上Referer固定为https://quote.eastmoney.com/User-Agent用浏览器默认的即可。有部分网络环境下不带Referer会直接返回403。另外接口返回里有一种情况是返回了正常JSON但data字段是null。这种情况通常有两种可能股票代码输错了、股票停牌了。代码里对data为空的处理逻辑一定要写不要假设接口永远返回正常数据。5.2 时间戳与时区一个隐蔽的大坑东方财富返回的时间是北京时间格式是yyyy-MM-dd HH:mm。这在本地跑没有问题但如果你用的是云服务器特别是海外节点Python的datetime和pandas默认会使用UTC时区你如果直接做时间计算结果会偏移8小时。处理方法是读取时间字符串后手动指定时区为Asia/Shanghai。用pandas的话加一行就行。df[time] pd.to_datetime(df[time]).dt.tz_localize(Asia/Shanghai)注意这里用的是tz_localize不是tz_convert。因为原始时间没有时区信息是本地时间你要做的是告诉pandas这个时间属于哪个时区。如果你先convert会因为没有时区信息而报错。如果你想把时间转换为UTC做存储再在后面加一步df[time_utc] df[time].dt.tz_convert(UTC)5.3 停牌、新股、北交所的边界情况实战中还会遇到几类特殊股票处理不好代码会直接崩。第一类是停牌股。当天没有交易trends接口返回的数据是空数组。解析的时候data[trends]是None或空列表需要提前判断并跳过。我的习惯是定义一个常量表示“今日无数据”避免后续的指标计算传入空DataFrame。第二类是刚上市的新股。上市前5个交易日没有涨跌幅限制涨跌幅字段会超过10%但数据结构不变代码不用改。需要注意是次新股的均线数据参考意义不大因为上市首日没有历史筹码沉淀分时均价线只能反映当天的成本做多空趋势指标时要谨慎。第三类是北交所股票。我实测时发现北交所分时数据和沪深最大的不同是交易时间多出15分钟也就是从9:30到11:30、13:00到15:15每天有255个采样点。如果你用固定的240点做循环处理北交所数据会报索引越界。代码里不要写死长度用len(df)动态判断。5.4 关于接口和数据的一点点个人经验最后分享两个我自己一直在用的小习惯。第一个习惯是每次请求前先判断当前时间是否处于交易时段。A股交易时间是周一到周五的9:30到11:30、13:00到15:00周末和法定节假日不开盘。请求之前先用datetime判断一下如果非交易时段分时数据不会变化直接读取本地缓存就行。这个逻辑可以减少大量的无效请求也降低被限制的风险。第二个习惯是原始数据落地保存。我每次拉取数据都会在本地存一份CSV文件名带上日期和股票代码。后面即使策略代码改了、字段算错了还能拿原始数据重新算。自己写的数据获取代码一定要把原始数据留档因为解析代码可以重构但历史行情数据过了那天就没有了。数据获取只是第一步真正的价值在于你拿这些数据做了什么。把分时抓下来、指标算出来这只是个开始。你完全可以从这里继续延伸比如用分钟级数据做盘中预警监测价格快速突破均价线且放量的异动比如把多空趋势指标做成后台定时任务收盘后自动生成数据报告再比如把抓到的分时数据入库长期积累成自己的日内T0策略回测数据池。这些方向都值得慢慢折腾也欢迎在这条路上握个手互相交流。