东方财富实时行情API深度解析:Python实战获取5档盘口与30+核心字段
在量化交易和金融数据分析领域,实时行情数据的获取是构建交易策略的基础。东方财富网作为国内领先的金融数据服务商,其API接口提供了丰富而稳定的行情数据源。本文将深入解析东方财富实时行情API v2的使用方法,重点讲解如何通过Python获取完整的5档买卖盘口数据以及30多个关键字段。
1. 东方财富API接口概览
东方财富的实时行情API采用RESTful设计,通过HTTP GET请求即可获取JSON格式的行情数据。与公开网页版数据相比,API接口提供了更高效的数据获取方式,特别适合程序化交易和数据分析场景。
该API的核心特点包括:
- 实时性高:数据更新频率可达秒级,满足大多数量化交易需求
- 字段丰富:支持100+数据字段,涵盖价格、成交量、资金流向等多维度指标
- 稳定可靠:相比其他免费数据源,东方财富API具有更好的稳定性
- 无需认证:目前接口开放使用,不需要申请API密钥
典型请求URL结构如下:
http://push2.eastmoney.com/api/qt/stock/get?fltt=2&invt=2&fields=f43,f57,f58,...&secid=1.6005192. 关键参数详解
2.1 股票代码转换规则
东方财富API使用特殊的市场代码+股票代码组合来标识证券:
def convert_stock_code(code): """ 将标准股票代码转换为东方财富API识别的格式 :param code: 标准股票代码,如'sh600000'或'sz000001' :return: API可识别的secid参数值 """ if code.startswith('sh'): return f'1.{code[2:]}' # 沪市股票 elif code.startswith('sz'): return f'0.{code[2:]}' # 深市股票 else: raise ValueError("不支持的股票代码格式")2.2 fields参数字段映射表
fields参数是API最核心的部分,它决定了返回数据包含哪些字段。以下是部分重要字段的映射关系:
| 字段代码 | 含义 | 字段代码 | 含义 |
|---|---|---|---|
| f43 | 最新价 | f57 | 股票代码 |
| f58 | 股票名称 | f46 | 开盘价 |
| f44 | 最高价 | f45 | 最低价 |
| f60 | 最新成交量(手) | f48 | 成交额(元) |
| f47 | 成交量(股) | f168 | 换手率 |
| f116 | 总市值 | f117 | 流通市值 |
| f39-f40 | 卖一价/量 | f37-f38 | 卖二价/量 |
| f35-f36 | 卖三价/量 | f33-f34 | 卖四价/量 |
| f31-f32 | 卖五价/量 | f19-f20 | 买一价/量 |
| f17-f18 | 买二价/量 | f15-f16 | 买三价/量 |
| f13-f14 | 买四价/量 | f11-f12 | 买五价/量 |
3. Python实战:完整API请求与解析
下面是一个完整的Python实现,包含错误处理和性能优化:
import requests import json from datetime import datetime import time class EastMoneyAPI: def __init__(self): self.base_url = "http://push2.eastmoney.com/api/qt/stock/get" self.default_fields = ( "f57,f58,f43,f46,f44,f45,f60,f48,f47,f168,f116,f117," "f39,f40,f37,f38,f35,f36,f33,f34,f31,f32," "f19,f20,f17,f18,f15,f16,f13,f14,f11,f12" ) self.session = requests.Session() self.session.headers.update({ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Referer": "http://quote.eastmoney.com/" }) def get_realtime_data(self, stock_code, fields=None): """ 获取股票实时行情数据 :param stock_code: 带市场前缀的股票代码,如'sh600000' :param fields: 可选,自定义字段列表 :return: 解析后的行情数据字典 """ secid = self._convert_code(stock_code) params = { "fltt": 2, "invt": 2, "fields": fields or self.default_fields, "secid": secid, "_": int(time.time() * 1000) # 防止缓存 } try: resp = self.session.get(self.base_url, params=params, timeout=5) resp.raise_for_status() data = json.loads(resp.text)["data"] return self._parse_data(data) except Exception as e: print(f"获取行情数据失败: {e}") return None def _convert_code(self, code): """转换股票代码格式""" if code.startswith("sh"): return f"1.{code[2:]}" elif code.startswith("sz"): return f"0.{code[2:]}" else: raise ValueError("不支持的股票代码格式") def _parse_data(self, raw_data): """解析原始API返回数据""" return { "代码": raw_data.get("f57"), "名称": raw_data.get("f58"), "最新价": raw_data.get("f43"), "开盘价": raw_data.get("f46"), "最高价": raw_data.get("f44"), "最低价": raw_data.get("f45"), "成交量(手)": raw_data.get("f60"), "成交额(元)": raw_data.get("f48"), "换手率": raw_data.get("f168"), "总市值": raw_data.get("f116"), "流通市值": raw_data.get("f117"), "卖盘": [ {"价格": raw_data.get("f39"), "数量": raw_data.get("f40")}, {"价格": raw_data.get("f37"), "数量": raw_data.get("f38")}, {"价格": raw_data.get("f35"), "数量": raw_data.get("f36")}, {"价格": raw_data.get("f33"), "数量": raw_data.get("f34")}, {"价格": raw_data.get("f31"), "数量": raw_data.get("f32")}, ], "买盘": [ {"价格": raw_data.get("f19"), "数量": raw_data.get("f20")}, {"价格": raw_data.get("f17"), "数量": raw_data.get("f18")}, {"价格": raw_data.get("f15"), "数量": raw_data.get("f16")}, {"价格": raw_data.get("f13"), "数量": raw_data.get("f14")}, {"价格": raw_data.get("f11"), "数量": raw_data.get("f12")}, ], "更新时间": datetime.now().strftime("%Y-%m-%d %H:%M:%S") } # 使用示例 if __name__ == "__main__": api = EastMoneyAPI() data = api.get_realtime_data("sh600519") # 贵州茅台 print(json.dumps(data, indent=2, ensure_ascii=False))4. 高级应用与性能优化
4.1 批量获取多只股票数据
通过构造复合的secid参数,可以一次性获取多只股票的数据:
def get_batch_data(self, stock_codes, fields=None): """ 批量获取多只股票实时数据 :param stock_codes: 股票代码列表,如['sh600000', 'sz000001'] :param fields: 可选,自定义字段列表 :return: 各股票行情数据字典列表 """ secids = ",".join([self._convert_code(code) for code in stock_codes]) params = { "fltt": 2, "invt": 2, "fields": fields or self.default_fields, "secid": secids, "_": int(time.time() * 1000) } try: resp = self.session.get(self.base_url, params=params, timeout=10) resp.raise_for_status() items = json.loads(resp.text).get("data", {}).get("diff", []) return [self._parse_data(item) for item in items] except Exception as e: print(f"批量获取行情数据失败: {e}") return []4.2 使用异步IO提升效率
对于需要高频获取大量股票数据的场景,可以使用aiohttp库实现异步请求:
import aiohttp import asyncio async def fetch_async(session, url, params): async with session.get(url, params=params) as response: return await response.text() async def get_data_async(stock_codes): async with aiohttp.ClientSession() as session: tasks = [] for code in stock_codes: secid = convert_code(code) params = { "fltt": 2, "invt": 2, "fields": default_fields, "secid": secid, "_": int(time.time() * 1000) } task = fetch_async(session, base_url, params) tasks.append(task) return await asyncio.gather(*tasks)4.3 数据缓存与更新策略
提示:频繁请求API可能导致IP被限制,建议实现本地缓存机制
合理的缓存策略应该考虑:
- 对静态数据(如股票名称)使用长期缓存
- 对动态数据根据更新频率设置不同的过期时间
- 实现缓存失效时的自动更新机制
from cachetools import TTLCache class CachedAPI(EastMoneyAPI): def __init__(self, maxsize=1000, ttl=300): super().__init__() self.cache = TTLCache(maxsize=maxsize, ttl=ttl) def get_realtime_data(self, stock_code, fields=None): cache_key = f"{stock_code}:{fields or 'default'}" if cache_key in self.cache: return self.cache[cache_key] data = super().get_realtime_data(stock_code, fields) if data: self.cache[cache_key] = data return data5. 数据质量监控与异常处理
在实际应用中,我们需要建立完善的数据质量监控机制:
- 完整性检查:验证返回数据是否包含所有请求的字段
- 合理性验证:检查价格、成交量等数值是否在合理范围内
- 时效性监控:确保数据更新时间符合预期
- 异常值处理:对异常数据(如价格突变为0)进行过滤或标记
def validate_data(data, expected_fields): """ 验证行情数据质量 :param data: 待验证的数据字典 :param expected_fields: 预期包含的字段列表 :return: (是否有效, 错误信息) """ if not data: return False, "空数据" missing_fields = [f for f in expected_fields if f not in data] if missing_fields: return False, f"缺失字段: {missing_fields}" # 检查价格合理性 if data["最新价"] <= 0: return False, "无效价格" # 检查买卖盘口数据 for i in range(5): if data["卖盘"][i]["价格"] <=0 or data["卖盘"][i]["数量"] <0: return False, f"异常卖盘数据{i+1}" if data["买盘"][i]["价格"] <=0 or data["买盘"][i]["数量"] <0: return False, f"异常买盘数据{i+1}" return True, ""通过以上技术方案,我们可以构建一个稳定、高效的东方财富实时行情数据采集系统,为量化交易和金融分析提供可靠的数据支持。