【Python】常用Python金融数据接口库
【Python金融数据接口库深度剖析】第一章:Tushare —— 专业金融数据引擎
1. Tushare库引言与核心概述
Tushare 是一个开源的Python财经数据接口包,在国内金融量化分析领域得到了广泛应用。它致力于为金融分析师、量化研究员、学习者以及各类金融科技公司提供快速、整洁、便捷的金融数据获取方式。Tushare 的数据来源多样,覆盖了股票、指数、基金、期货、期权、债券、外汇、行业经济、国民经济等多个领域,尤其对A股市场的数据支持非常全面。
- 1.1 Tushare库的概述与定位
- 1.1.1 主要功能与特色
- 数据全面性: Tushare 提供了包括中国A股、港股、美股(部分)、期货、基金、宏观经济、行业数据等在内的海量金融数据。
- 接口统一性: 提供了统一的函数接口来获取不同类型的数据,简化了数据获取的复杂度。
- 数据质量: Tushare Pro版本(其付费高级版本)致力于提供更高质量、更及时、更稳定的数据服务。免费版本的数据在时效性和覆盖面上可能有所限制。
- 易用性: Pythonic的接口设计,返回数据主要格式为 Pandas DataFrame,非常便于后续的数据分析和处理。
- 社区支持: 拥有庞大的用户社区,遇到问题时相对容易找到解决方案或获得帮助。
- Pro版本与积分制: Tushare Pro引入了积分制度,用户通过注册、分享、贡献等方式获取积分,用以兑换更高权限的数据接口调用额度。这种模式在一定程度上保证了服务的可持续性。
- 1.1.2 数据覆盖范围 (以Tushare Pro为例)
- 股票市场:
- 日线、分钟线(1min, 5min, 15min, 30min, 60min)、tick级高频数据。
- 复权因子(前复权、后复权)。
- 上市公司基本信息、高管信息、股东信息。
- 财务报表(利润表、资产负债表、现金流量表)、财务指标。
- 分红送股、增发、配股、IPO信息。
- 融资融券数据、大宗交易、龙虎榜。
- 停复牌信息、限售股解禁。
- 每日涨跌停价格、每日市场表现统计。
- 指数:
- 主要市场指数(上证综指、深证成指、沪深300、中证500、创业板指等)的日线、分钟线行情。
- 指数基本信息、成分股列表及权重。
- 全球主要指数行情。
- 公募基金:
- 基金基本信息、基金净值(日度、周度)、复权净值。
- 基金份额数据、基金资产配置、基金持股明细。
- 期货市场:
- 国内主要期货交易所(上期所、大商所、郑商所、中金所、能源中心)的合约信息、日线、分钟线行情、持仓排名、仓单数据。
- 期权市场:
- 主要期权品种(如沪深300期权、个股期权)的合约信息、日线行情、T型报价、风险参数。
- 债券市场:
- 国债、企业债、可转债等的基本信息、发行信息、日线行情。
- 外汇市场:
- 主要货币对的即期汇率、远期汇率(部分)。
- 人民币外汇牌价。
- 港股与美股:
- 部分港股、美股的日线行情和基本信息(覆盖范围和实时性可能有限)。
- 宏观经济:
- 国民经济核算(GDP)、工业增加值、CPI、PPI、PMI、财政收支、货币供应量(M0, M1, M2)、利率、存款准备金率、社会融资规模、外汇储备等。
- 行业经济:
- 各行业相关的经济数据和景气指数。
- 新闻快讯与公告:
- 财经新闻、上市公司公告(部分)。
- 股票市场:
- 1.1.3 目标用户
- 个人投资者与爱好者: 进行基本的数据查询、图表绘制、简单策略回测。
- 金融分析师与研究员: 进行深入的市场分析、行业研究、公司估值。
- 量化交易者: 构建量化交易策略、进行回测与实盘交易的数据支持。
- 学术研究人员: 进行金融学、经济学科研所需的数据支撑。
- 金融科技公司: 作为其金融产品或服务的数据源之一。
- 1.1.4 与其他库的简要对比
- AkShare: 另一个功能强大且开源的Python财经数据接口库,数据源极为广泛,覆盖国内外众多市场和数据种类。与Tushare相比,AkShare的接口更为多样化,数据源更分散,可能在某些细分数据上更有优势,但Tushare Pro在A股数据的深度和专业性上可能有其独到之处。
- yfinance: 主要针对雅虎财经的数据,是获取国际股票市场(尤其是美股)历史行情和部分基本面数据的常用工具,简单易用,但数据种类不如Tushare和AkShare全面,且对国内A股支持有限。
- Quandl/Nasdaq Data Link: 提供大量核心金融数据和另类数据,很多数据是收费的,专业性强,适合机构用户和对特定数据集有需求的研究者。
- Pandas-Datareader: 早期可以方便地从多个在线数据源(包括Yahoo, Google Finance等)读取数据,但近年来由于数据源API的变更,部分接口的稳定性有所下降。
- 1.1.1 主要功能与特色
- 1.2 Tushare安装与环境配置
pip install tushare: 这行命令会从Python包索引(PyPI)下载并安装最新版本的Tushare库。pandas: Tushare返回的数据主要是Pandas DataFrame格式,因此Pandas是其核心依赖和黄金搭档。matplotlib: 通常用于数据的可视化,安装后方便对获取的数据进行图表展示。-i https://pypi.tuna.tsinghua.edu.cn/simple: 这部分是可选的,指定使用清华大学的镜像源进行下载,可以显著提高国内用户的下载速度。您也可以选择其他国内镜像源,如阿里云、豆瓣等。- 1.2.2 依赖项说明
Tushare的主要依赖项包括:pandas: 用于数据处理和DataFrame结构。lxml: 用于解析HTML/XML,部分接口可能需要。requests: 用于进行HTTP网络请求,从API获取数据。numpy: Pandas的底层依赖,用于数值计算。
通常情况下,pip install tushare会自动处理这些核心依赖的安装。
- 1.2.3 获取Tushare Pro API Token
虽然Tushare有免费接口,但其大部分高质量、高权限的数据接口都属于Tushare Pro版本,需要用户注册并获取API Token才能调用。请务必妥善保管您的Token,不要泄露给他人,以免被盗用。- 注册账户: 访问 Tushare Pro的官方网站 (https://tushare.pro) 并注册一个账户。
- 个人中心获取Token: 登录后,在“个人中心”或“接口TOKEN”类似的页面可以找到您的专属API Token。这个Token是一串唯一的字符串,是您调用Pro接口的凭证。
- 了解积分规则: Tushare Pro的接口调用权限与积分挂钩。不同的接口需要不同的积分才能无限制调用。新用户通常会有一定的初始积分,可以通过签到、分享、社区贡献、邀请好友或直接充值等方式提升积分。
import tushare as ts: 导入tushare库,并使用通用别名ts。import pandas as pd: 导入pandas库,使用别名pd。MY_TUSHARE_TOKEN = "YOUR_ACTUAL_TOKEN_HERE": 关键步骤。定义一个变量存储您的Tushare Pro Token。请务必将"YOUR_ACTUAL_TOKEN_HERE"替换为您自己账户的真实Token。 为了安全,不建议直接硬编码Token,更好的做法是将其存储在环境变量中,然后通过os.environ.get('TUSHARE_TOKEN')读取,或者存储在安全的配置文件中。if MY_TUSHARE_TOKEN == "YOUR_ACTUAL_TOKEN_HERE" or not MY_TUSHARE_TOKEN:: 检查用户是否已经将占位符Token替换掉。ts.set_token(MY_TUSHARE_TOKEN): 调用tushare库的set_token方法,将您的Token传递给库,这样库在后续的API请求中就会使用这个Token进行认证。pro = ts.pro_api(): 调用pro_api()方法,它会返回一个Tushare Pro API的接口对象。后续所有Tushare Pro的接口都通过这个pro对象来调用。如果Token无效或网络不通,这一步可能就会报错,或者在后续调用接口时报错。print("Tushare Pro APl 初始化成功!"): 打印一条消息,确认初始化过程已执行。print(f"Tushare版本: {ts.__version__}"): 打印当前安装的Tushare库的版本号,有助于问题排查。try...except块: 用于测试API初始化是否成功以及Token是否有效。df_cal = pro.trade_cal(exchange='', start_date='20240101', end_date='20240105'): 调用pro.trade_cal接口获取交易日历。这是一个相对基础的接口,通常对积分要求不高,适合用于测试连接。exchange=''表示获取所有交易所的日历。start_date和end_date指定日期范围。
if not df_cal.empty:: 检查返回的DataFrame是否有数据。print(df_cal.head()): 如果获取成功,打印数据的前几行。else: print(...): 如果未获取到数据,打印提示信息。except Exception as e: print(...): 如果在API调用过程中发生任何错误(如Token错误、网络问题、积分不足等),捕获异常并打印错误信息及排查建议。
- 1.3 Tushare核心设计理念与架构 (概念性探讨)Tushare的设计目标是提供一个简洁、高效的财经数据获取工具。其内部机制虽然对普通用户是透明的,但理解其大致工作方式有助于更好地使用它。
- 1.3.1 数据获取流程
- 客户端请求: 用户通过调用
pro.interface_name(parameters)(例如pro.daily(ts_code='000001.SZ')) 发起数据请求。 - 参数校验与封装 (本地): Tushare库本地代码可能会对用户传入的参数进行初步的校验(如日期格式、股票代码格式等)。
- API Token附加:
set_token设置的Token会自动附加到实际的网络请求中,作为身份验证凭据。 - HTTP请求构建: 库根据接口名称和参数,构建一个指向Tushare服务器API端点的HTTP请求(通常是POST或GET请求)。请求体中可能包含参数和Token。
- 网络传输: 请求通过互联网发送到Tushare的API服务器。
- 服务器端处理:
- 身份验证: 服务器首先验证Token的有效性。
- 权限校验: 根据Token关联账户的积分和所请求接口的权限要求,判断用户是否有权限访问该数据。
- 参数解析与数据查询: 服务器解析请求参数,然后在后端的数据库(或其他数据存储)中查询相应的数据。
- 数据格式化: 服务器将查询到的原始数据格式化为约定的格式(通常是JSON)。
- 频率限制检查: 服务器会检查用户的API调用频率是否超限。
- HTTP响应: 服务器将处理结果(成功时是数据,失败时是错误信息)封装在HTTP响应中返回给客户端。
- 响应解析 (本地): Tushare库接收到服务器的HTTP响应。
- 错误检查: 检查响应状态码和内容,判断请求是否成功。如果失败,可能会抛出异常或返回特定的错误提示。
- 数据解析与转换: 如果请求成功,库会解析响应中的数据(通常是JSON字符串)。
- Pandas DataFrame构建: Tushare会将解析后的结构化数据转换为Pandas DataFrame对象,这是其核心特色之一,极大地方便了用户后续的数据分析。
- 返回结果: 将构建好的DataFrame返回给用户调用的函数。
- 客户端请求: 用户通过调用
- 1.3.2 数据缓存机制
Tushare本身默认不提供复杂的客户端数据缓存机制。每次调用API接口通常都会发起一次网络请求。这确保了用户获取到的是相对最新的数据(取决于Tushare服务器数据的更新频率)。- 用户端缓存的必要性: 对于不经常变动的数据(如历史日线、公司基本信息、历史财务数据)或为了减少API调用次数(节省积分、避免超限),用户通常需要在自己的代码中实现缓存逻辑。
- 常见的用户端缓存方法:
- 文件缓存: 将获取到的DataFrame保存为CSV、Excel、Parquet、Feather等格式的文件。下次请求相同数据前,先检查本地文件是否存在且未过期。
- 数据库缓存: 将数据存入SQLite、MySQL、MongoDB等数据库中。
- 内存缓存: 对于短期内会频繁使用的小数据集,可以使用Python的
functools.lru_cache或其他内存缓存库。
我们将在后续的“运维与优化”章节详细讨论如何实现这些缓存策略。
- 直接抛出异常: 例如,网络连接错误、认证失败等可能会直接以Python异常的形式抛出。
- 返回特定错误码和信息的DataFrame/JSON: 对于某些业务逻辑错误(如参数错误、无数据、积分不足),Tushare的某些接口可能会返回一个包含错误代码 (
code) 和错误信息 (msg) 字段的特殊响应,而不是直接抛出异常。用户需要检查这些字段来判断请求的真实状态。 - 内置重试: Tushare库本身可能没有非常复杂的内置自动重试机制。如果一次API调用因为网络波动或服务器瞬时高负载而失败,用户可能需要自行实现重试逻辑(例如,使用
time.sleep()配合循环,或者使用tenacity这样的重试库)。
- 1.3.4 接口设计风格
Tushare Pro的接口设计相对统一和简洁:- 面向功能: 每个API函数对应一个特定的数据获取功能,函数名清晰地描述了其作用(如
daily获取日线行情,income获取利润表)。 - 参数化查询: 通过函数参数来指定查询条件(如股票代码
ts_code、日期trade_date、start_date、end_date等)。 - 统一的Pro API入口: 所有Pro版接口都通过
ts.pro_api()初始化后的pro对象进行调用。
- 面向功能: 每个API函数对应一个特定的数据获取功能,函数名清晰地描述了其作用(如
- 1.3.5 返回数据格式
- Pandas DataFrame: 这是Tushare最核心和最受欢迎的特性之一。绝大部分接口成功时都会返回一个Pandas DataFrame对象。
- 结构化: DataFrame提供了强大的结构化数据处理能力。
- 列名清晰: 返回的DataFrame通常具有语义清晰的列名(如
open,high,low,close,vol)。 - 数据类型: DataFrame中的数据列会自动推断或设置为合适的数据类型(如数值型、日期时间型、字符串型)。
- 易于集成: Pandas DataFrame可以无缝对接NumPy、SciPy、Matplotlib、Seaborn、Scikit-learn等众多Python数据科学生态库。
- JSON (底层): 虽然用户直接操作的是DataFrame,但Tushare库与服务器之间的数据交换格式很可能是JSON。库在内部完成了JSON到DataFrame的转换。
- 部分接口可能返回其他格式: 极少数特殊接口或较早版本的接口,其返回格式可能略有不同,但主流Pro接口以DataFrame为主。
- Pandas DataFrame: 这是Tushare最核心和最受欢迎的特性之一。绝大部分接口成功时都会返回一个Pandas DataFrame对象。
- 1.3.1 数据获取流程
1.3.3 错误处理与重试
Tushare库在API调用失败时,通常会通过以下方式向用户反馈错误:
# 示例:检查Tushare Pro接口返回的错误信息 (假设接口可能这样返回)# data_df = pro.some_interface(some_param='value')# if hasattr(data_df, 'get') and data_df.get('code') != 0: # 假设错误时code不为0# print(f"API调用出错: code={data_df.get('code')}, message={data_df.get('msg')}")# else:# # 处理正常数据# pass1.2.4 初始化Tushare Pro客户端
获取到Token后,在Python代码中需要初始化Tushare Pro的接口。
import tushare as ts # 导入tushare库,通常简写为tsimport pandas as pd # 导入pandas库,用于数据处理# 设置您的Tushare Pro Token# 强烈建议不要将Token硬编码在代码中,尤其是在共享或版本控制的代码里# 更好的方式是存储在环境变量或配置文件中# 示例:从环境变量读取 MY_TS_TOKEN = os.environ.get('TUSHARE_TOKEN')# 此处为演示方便,直接赋值。请替换为您自己的Token。 MY_TUSHARE_TOKEN ="YOUR_ACTUAL_TOKEN_HERE"# 将 'YOUR_ACTUAL_TOKEN_HERE' 替换成你自己的Token字符串if MY_TUSHARE_TOKEN =="YOUR_ACTUAL_TOKEN_HERE"ornot MY_TUSHARE_TOKEN:# 检查Token是否已替换print("请将 MY_TUSHARE_TOKEN 替换为您在Tushare Pro官网获取的真实Token。")# 提示用户替换Token# exit() # 如果未设置Token,可以选择退出程序或给出更友好的提示# 初始化Tushare Pro接口 ts.set_token(MY_TUSHARE_TOKEN)# 调用set_token方法,传入你的Token pro = ts.pro_api()# 初始化pro_api对象,后续通过该对象调用Pro版接口print("Tushare Pro APl 初始化成功!")# 打印成功初始化的消息print(f"Tushare版本: { ts.__version__}")# 打印当前安装的Tushare库版本号# 简单测试:获取一条财经日历数据 (通常对积分要求较低或免费)try: df_cal = pro.trade_cal(exchange='', start_date='20240101', end_date='20240105')# 调用交易日历接口ifnot df_cal.empty:# 检查返回的DataFrame是否为空print("\n成功获取交易日历数据 (部分示例):")# 打印获取成功的消息print(df_cal.head())# 打印DataFrame的前几行作为示例else:print("\n未能获取到交易日历数据,请检查Token有效性、积分或网络。")# 如果数据为空,则打印提示信息except Exception as e:# 捕获可能发生的异常print(f"\n调用pro.trade_cal接口失败: { e}")# 打印错误信息print("请检查您的Token是否正确、账户积分是否足够调用此接口,以及网络连接是否正常。")# 提供可能的错误原因和排查方向代码解释:
1.2.1 使用pip安装
Tushare库的安装非常简单,可以通过Python的包管理工具pip进行安装。建议在虚拟环境中进行安装,以避免与其他项目的依赖冲突。
# 创建并激活虚拟环境 (可选但推荐)# python -m venv tushare_env # 创建虚拟环境# source tushare_env/bin/activate # Linux/macOS激活# tushare_env\Scripts\activate # Windows激活# 安装Tushare库 pip install tushare pandas matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple 1.4 Tushare基础数据获取与处理 —— 股票行情数据
股票行情数据是金融分析中最基础也是最核心的数据类型。Tushare Pro提供了丰富的接口来获取不同频率、不同类型的股票行情数据。
- 接口说明:
pro.trade_cal(exchange, start_date, end_date, is_open)exchange(str, 可选): 交易所SSE上交所, SZSE深交所, CFFEX 中金所, SHFE上期所, DCE大商所, CZCE郑商所, INE上海国际能源交易中心。默认为空’',表示获取所有交易所的日历数据(对于A股主要是上交所和深交所的综合交易日)。start_date(str, 可选): 开始日期,格式YYYYMMDD。end_date(str, 可选): 结束日期,格式YYYYMMDD。is_open(str, 可选): 是否只获取开市日历,'0’休市, ‘1’交易,默认为空’'表示获取所有日历信息。
- 返回字段:
exchange(str): 交易所代码。cal_date(str): 日历日期。is_open(int): 是否交易,0休市,1交易。pretrade_date(str): 上一个交易日(当前日期是交易日才有这个字段,非交易日为空)。
- 代码示例与详细解释:
- 初始化: 前面的Token设置和
pro对象初始化是必须的。 - 示例1:
start_dt = "20231225",end_dt = "20240105": 定义了查询的起止日期。df_cal_all = pro.trade_cal(start_date=start_dt, end_date=end_dt): 调用trade_cal接口,不指定exchange和is_open,获取此期间所有交易所(主要是上交所和深交所在中国的综合日历)的开市和休市信息。df_cal_all.head(): 显示返回的DataFrame的前5行。sse_trading_days = df_cal_all[(df_cal_all['exchange'] == 'SSE') & (df_cal_all['is_open'] == 1)]: 使用Pandas的布尔索引筛选出上交所 (exchange == 'SSE') 并且是开市日 (is_open == 1) 的数据。
- 示例2:
exchange_code = "SZSE": 指定查询深交所的日历。is_open='1': 明确指定只获取开市日的日历。df_cal_open_szse = pro.trade_cal(...): 调用接口。df_cal_open_szse['cal_date_dt'] = pd.to_datetime(df_cal_open_szse['cal_date']): 将返回的日期字符串列cal_date转换为Pandas的datetime对象类型,存储在新列cal_date_dt中。这非常有用,因为datetime对象支持更丰富的日期时间操作。
- 示例3:
today_str = datetime.now().strftime('%Y%m%d'): 获取当前日期并格式化为Tushare接受的字符串格式。start_date_for_recent = (datetime.now() - timedelta(days=30)).strftime('%Y%m%d'): 计算30天前的日期作为获取近期日历的起始点,以确保能覆盖到最近的交易日(因为今天可能是非交易日)。df_recent_sse_open = pro.trade_cal(exchange='SSE', ..., is_open='1'): 获取上交所近期的开市日历。df_recent_sse_open = df_recent_sse_open.sort_values(by='cal_date', ascending=False): 将获取到的交易日按日期降序排列,这样最新的日期就在最前面。latest_5_trading_days = df_recent_sse_open['cal_date'].head(5).tolist(): 取出排在最前面的5个日期(即最近的5个交易日)并转换为Python列表。
- 示例4:
futures_exchange = "CFFEX": 指定查询中国金融期货交易所的日历。- 演示了如何获取特定期货交易所的交易日历。
- 应用场景与重要性:
- 数据对齐: 在合并不同来源、不同频率的数据时,确保所有数据都基于共同的交易日历进行对齐,避免因节假日错位导致分析错误。
- 回测系统: 量化回测时,策略的执行、持仓的更新、收益的计算都必须严格按照交易日进行。
- 日期计算: 计算N个交易日之前/之后的日期,跳过周末和法定节假日。
- 数据完整性检查: 确认获取到的行情数据或财务数据是否覆盖了所有预期的交易日。
- 接口说明:
pro.daily(ts_code, trade_date, start_date, end_date)ts_code(str, 可选): 股票代码,支持单个或多个股票代码(多个代码用逗号分隔,如’000001.SZ,600000.SH’)。如果为空,则获取所有股票的指定日期数据(数据量可能很大,需注意积分消耗和调用频率)。trade_date(str, 可选): 交易日期,格式YYYYMMDD。与start_date/end_date互斥,三者只能提供其一。start_date(str, 可选): 开始日期,格式YYYYMMDD。end_date(str, 可选): 结束日期,格式YYYYMMDD。
- 返回字段 (常用):
ts_code(str): TS股票代码,如 ‘000001.SZ’。trade_date(str): 交易日期。open(float): 开盘价。high(float): 最高价。low(float): 最低价。close(float): 收盘价。pre_close(float): 昨日收盘价。change(float): 涨跌额 (close - pre_close)。pct_chg(float): 涨跌幅 (%),(change / pre_close) * 100。vol(float): 成交量 (手)。注意:A股1手=100股。amount(float): 成交额 (千元)。
- 代码示例与详细解释:
1.4.2 获取股票日线行情 (daily)
日线行情数据是进行技术分析、策略回测、市场研究的基础。Tushare提供了 daily 接口来获取A股的日线行情数据。
import tushare as ts import pandas as pd import os import time # 导入time模块,用于演示分批获取时的延时# --- 初始化Tushare Pro接口 (假设已在前面执行过) ---# MY_TUSHARE_TOKEN = "YOUR_ACTUAL_TOKEN_HERE"# if MY_TUSHARE_TOKEN == "YOUR_ACTUAL_TOKEN_HERE" or not MY_TUSHARE_TOKEN:# print("警告:请确保已正确设置Tushare Pro Token。")# ts.set_token(MY_TUSHARE_TOKEN)# pro = ts.pro_api()# --- 结束初始化 ---# 确保pro对象已初始化 (如果这个代码块是独立运行的)if'pro'notinglobals():print("错误: Tushare Pro API尚未初始化。请先执行初始化代码块。")# exit()print("\n--- 1.4.2 获取股票日线行情 ---")# 示例1: 获取单只股票在指定日期范围内的日线行情 ts_code_single ='000001.SZ'# 平安银行TS代码 start_date_daily ='20231201'# 开始日期 end_date_daily ='20231215'# 结束日期print(f"\n示例1: 获取股票 { ts_code_single} 从 { start_date_daily} 到 { end_date_daily} 的日线行情")try: df_daily_single = pro.daily(ts_code=ts_code_single, start_date=start_date_daily, end_date=end_date_daily)# 调用daily接口ifnot df_daily_single.empty:# 检查DataFrame是否为空print(f"获取到 { ts_code_single} 的日线数据 (前5行):")print(df_daily_single.head())# 打印前5行print(f"\n数据总行数: { len(df_daily_single)}")# 打印总行数# 进行简单的数据清洗和转换 df_daily_single['trade_date']= pd.to_datetime(df_daily_single['trade_date'])# 将交易日期转为datetime对象 df_daily_single = df_daily_single.sort_values(by='trade_date', ascending=True)# 按交易日期升序排列 df_daily_single.set_index('trade_date', inplace=True)# 将交易日期设为索引,方便后续按日期操作print("\n清洗和设置索引后的数据 (后3行,已按日期升序):")print(df_daily_single[['open','high','low','close','vol','pct_chg']].tail(3))# 打印指定列的后3行else:print(f"未能获取到 { ts_code_single} 在该时间段的日线数据。")# 如果数据为空则打印提示except Exception as e:# 捕获异常print(f"错误:获取 { ts_code_single} 日线行情失败: { e}")# 打印错误信息# 示例2: 获取多只股票在指定单一交易日的日线行情 ts_codes_multiple ='000001.SZ,600036.SH,300750.SZ'# 平安银行, 招商银行, 宁德时代 trade_date_single ='20231208'# 指定单一交易日期print(f"\n示例2: 获取股票列表 ({ ts_codes_multiple}) 在交易日 { trade_date_single} 的日线行情")try: df_daily_multiple_oneday = pro.daily(ts_code=ts_codes_multiple, trade_date=trade_date_single)# 调用接口,传入多个TS代码和单个交易日ifnot df_daily_multiple_oneday.empty:# 检查DataFrame是否为空print(f"获取到 { trade_date_single} 的多股日线数据:")print(df_daily_multiple_oneday[['ts_code','open','close','pct_chg','vol']])# 打印指定列else:print(f"未能获取到 { ts_codes_multiple} 在 { trade_date_single} 的日线数据。")# 如果数据为空则打印提示except Exception as e:# 捕获异常print(f"错误:获取多股单日日线行情失败: { e}")# 打印错误信息# 示例3: 获取所有股票在某一交易日的日线行情 (数据量大,慎用,可能会有积分或频率限制)# Tushare Pro对单次获取所有股票数据有较高的积分要求,并且返回数据量很大,网络传输和处理时间也较长。# 此处仅为演示接口用法,实际使用中强烈建议分批获取或按需获取。 trade_date_all_stocks ='20231130'# 指定一个过去的交易日print(f"\n示例3: 获取所有A股在交易日 { trade_date_all_stocks} 的日线行情 (演示概念,实际运行时请注意资源消耗)")print("注意:此操作可能非常耗时且消耗大量积分,真实场景下不建议直接全市场拉取单日数据。")# 为避免实际执行,我们将此部分注释掉,如果需要测试请取消注释并确保有足够积分""" try: # df_daily_all_stocks = pro.daily(trade_date=trade_date_all_stocks) # 调用接口时不指定ts_code # if not df_daily_all_stocks.empty: # print(f"获取到 {trade_date_all_stocks} 的全市场日线数据 (前5行):") # print(df_daily_all_stocks[['ts_code', 'close', 'pct_chg']].head()) # print(f"\n全市场股票数量 (当日有行情): {len(df_daily_all_stocks)}") # # 计算当日涨停和跌停的股票数量 (简单示例,真实涨跌停需结合涨跌停价格) # # 涨停近似:pct_chg > 9.8 (科创板/创业板为 > 19.8,ST为 > 4.8),这里简化处理 # limit_up_approx = df_daily_all_stocks[df_daily_all_stocks['pct_chg'] > 9.8] # print(f"当日近似涨停股票数量 (pct_chg > 9.8%): {len(limit_up_approx)}") # else: # print(f"未能获取到 {trade_date_all_stocks} 的全市场日线数据。") except Exception as e: print(f"错误:获取全市场单日日线行情失败: {e}") """print("示例3中的全市场数据获取代码已注释,以防意外执行。")# 示例4: 分批获取多只股票在较长一段时间内的日线行情 (处理API单次返回数据量限制或积分策略)# Tushare接口对单次返回的数据量有限制 (例如几千条记录)。如果请求的数据量过大,需要分批。# 此外,为了避免过于频繁地调用,可以在每次调用之间加入短暂延时。 stock_list_long_term =['000001.SZ','600036.SH','300750.SZ','000333.SZ','601318.SH']# 较多股票列表 start_date_long ='20230101'# 开始日期 (时间跨度较长) end_date_long ='20230331'# 结束日期print(f"\n示例4: 分批获取股票列表在 { start_date_long} 到 { end_date_long} 的日线行情") all_daily_data_long_term =[]# 用于存储所有获取到的DataFrame片段for stock_code in stock_list_long_term:# 遍历股票列表中的每个代码print(</1.4.1 获取交易日历 (trade_cal)
在进行任何与交易日相关的分析之前,获取准确的交易日历是至关重要的一步。交易日历告诉我们哪些天是开市交易的,哪些天是休市的。
import tushare as ts import pandas as pd import os from datetime import datetime, timedelta # --- 初始化Tushare Pro接口 --- MY_TUSHARE_TOKEN ="YOUR_ACTUAL_TOKEN_HERE"# 请替换为您的真实Tokenif MY_TUSHARE_TOKEN =="YOUR_ACTUAL_TOKEN_HERE"ornot MY_TUSHARE_TOKEN:print("警告:请将 MY_TUSHARE_TOKEN 替换为您在Tushare Pro官网获取的真实Token才能运行后续代码。")# exit() # 如果未设置Token,可能需要退出 ts.set_token(MY_TUSHARE_TOKEN) pro = ts.pro_api()print("Tushare Pro API 初始化完毕。\n")# --- 结束初始化 ---print("--- 1.4.1 获取交易日历 ---")# 示例1: 获取指定日期范围内的所有日历信息 (包括开市和休市)try: start_dt ="20231225"# 定义开始日期 end_dt ="20240105"# 定义结束日期print(f"\n示例1: 获取 { start_dt} 到 { end_dt} 的所有日历信息 (SSE和SZSE综合)") df_cal_all = pro.trade_cal(start_date=start_dt, end_date=end_dt)# 调用接口获取所有日历信息ifnot df_cal_all.empty:# 检查返回的DataFrame是否为空print("获取到的日历数据 (前5行):")print(df_cal_all.head())# 打印前5行数据print(f"\n数据总行数: { len(df_cal_all)}")# 打印数据总行数# 筛选出上交所的交易日 sse_trading_days = df_cal_all[(df_cal_all['exchange']=='SSE')&(df_cal_all['is_open']==1)]# 筛选条件:交易所为SSE且is_open为1print(f"\n其中上交所 ({ start_dt}-{ end_dt}) 的交易日数量: { len(sse_trading_days)}")# 打印上交所交易日数量print("上交所交易日 (前5个):")print(sse_trading_days['cal_date'].head().to_list())# 打印上交所交易日列表的前5个else:print(f"未能获取到 { start_dt} 到 { end_dt} 的日历数据。")# 如果数据为空则打印提示except Exception as e:# 捕获异常print(f"错误:获取所有日历信息失败: { e}")# 打印错误信息# 示例2: 获取指定交易所、指定日期范围内仅开市的日历try: exchange_code ="SZSE"# 定义交易所代码为深交所 start_dt_open ="20240201"# 定义开始日期 end_dt_open ="20240229"# 定义结束日期print(f"\n示例2: 获取 { exchange_code} 从 { start_dt_open} 到 { end_dt_open} 仅开市的日历") df_cal_open_szse = pro.trade_cal(exchange=exchange_code, start_date=start_dt_open, end_date=end_dt_open, is_open='1')# 调用接口,设置is_open='1'ifnot df_cal_open_szse.empty:# 检查返回的DataFrame是否为空print(f"获取到 { exchange_code} 的开市日历数据 (前5行):")print(df_cal_open_szse.head())# 打印前5行数据print(f"\n{ exchange_code} 在该时间段内共有 { len(df_cal_open_szse)} 个交易日。")# 打印交易日总数# 将cal_date转换为datetime对象,方便后续处理 df_cal_open_szse['cal_date_dt']= pd.to_datetime(df_cal_open_szse['cal_date'])# 新增一列,将cal_date字符串转为datetime对象print("\n转换cal_date为datetime对象后的数据 (前2行,含新列):")print(df_cal_open_szse[['cal_date','cal_date_dt','pretrade_date']].head(2))# 打印包含新列的部分数据else:print(f"未能获取到 { exchange_code} 从 { start_dt_open} 到 { end_dt_open} 的开市日历数据。")# 如果数据为空则打印提示except Exception as e:# 捕获异常print(f"错误:获取 { exchange_code} 开市日历失败: { e}")# 打印错误信息# 示例3: 获取最近N个交易日 (以今天为基准,向前推算)try:print("\n示例3: 获取最近5个交易日 (基于SSE,从今天或上一个已知交易日向前推算)") today_str = datetime.now().strftime('%Y%m%d')# 获取今天的日期字符串,格式YYYYMMDD# 为了确保能取到数据,我们可以从今天往前推一段时间获取日历,然后筛选# 假设我们向前推30天获取日历数据,以保证能覆盖最近的交易日 start_date_for_recent =(datetime.now()- timedelta(days=30)).strftime('%Y%m%d')# 计算30天前的日期# 获取上交所近期的开市日历 df_recent_sse_open = pro.trade_cal(exchange='SSE', start_date=start_date_for_recent, end_date=today_str, is_open='1')# 获取SSE开市日历ifnot df_recent_sse_open.empty:# 检查DataFrame是否为空 df_recent_sse_open = df_recent_sse_open.sort_values(by='cal_date', ascending=False)# 按日期降序排列,最新的在前 latest_5_trading_days = df_recent_sse_open['cal_date'].head(5).tolist()# 取出最新的5个交易日并转为列表print(f"最近5个上交所交易日 (从新到旧): { latest_5_trading_days}")# 打印结果if latest_5_trading_days:# 检查列表是否为空 most_recent_trade_day = latest_5_trading_days[0]# 获取最新的一个交易日print(f"其中,最新的一个交易日是: { most_recent_trade_day}")# 打印最新交易日else:print(f"未能获取到 { start_date_for_recent} 至 { today_str} 的SSE开市日历数据。")# 如果数据为空则打印提示except Exception as e:# 捕获异常print(f"错误:获取最近交易日失败: { e}")# 打印错误信息# 示例4: 获取期货交易所的交易日历 (例如:中金所CFFEX)try: futures_exchange ="CFFEX"# 定义期货交易所代码为中金所 futures_start_dt ="20240301"# 定义开始日期 futures_end_dt ="20240310"# 定义结束日期print(f"\n示例4: 获取 { futures_exchange} 从 { futures_start_dt} 到 { futures_end_dt} 的交易日历 (仅开市)") df_cal_cffex = pro.trade_cal(exchange=futures_exchange, start_date=futures_start_dt, end_date=futures_end_dt, is_open='1')# 调用接口ifnot df_cal_cffex.empty:# 检查DataFrame是否为空print(f"获取到 { futures_exchange} 的开市日历数据:")print(df_cal_cffex)# 打印所有获取到的数据else:print(f"未能获取到 { futures_exchange} 从 { futures_start_dt} 到 { futures_end_dt} 的开市日历数据。")# 如果数据为空则打印提示except Exception as e:# 捕获异常print(f"错误:获取 { futures_exchange} 交易日历失败: { e}")# 打印错误信息代码解释: