【Python】常用Python金融数据接口库_tushare
【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.2 Tushare安装与环境配置
-
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
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才能调用。- 注册账户: 访问 Tushare Pro的官方网站 (https://tushare.pro) 并注册一个账户。
- 个人中心获取Token: 登录后,在“个人中心”或“接口TOKEN”类似的页面可以找到您的专属API Token。这个Token是一串唯一的字符串,是您调用Pro接口的凭证。
- 了解积分规则: Tushare Pro的接口调用权限与积分挂钩。不同的接口需要不同的积分才能无限制调用。新用户通常会有一定的初始积分,可以通过签到、分享、社区贡献、邀请好友或直接充值等方式提升积分。
请务必妥善保管您的Token,不要泄露给他人,以免被盗用。
-
1.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\" or not MY_TUSHARE_TOKEN: # 检查Token是否已替换 print(\"请将 MY_TUSHARE_TOKEN 替换为您在Tushare Pro官网获取的真实Token。\") # 提示用户替换Token # exit() # 如果未设置Token,可以选择退出程序或给出更友好的提示# 初始化Tushare Pro接口ts.set_token(MY_TUSHARE_TOKEN) # 调用set_token方法,传入你的Tokenpro = 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\') # 调用交易日历接口 if not 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是否正确、账户积分是否足够调用此接口,以及网络连接是否正常。\") # 提供可能的错误原因和排查方向
代码解释:
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
或其他内存缓存库。
我们将在后续的“运维与优化”章节详细讨论如何实现这些缓存策略。
-
1.3.3 错误处理与重试
Tushare库在API调用失败时,通常会通过以下方式向用户反馈错误:- 直接抛出异常: 例如,网络连接错误、认证失败等可能会直接以Python异常的形式抛出。
- 返回特定错误码和信息的DataFrame/JSON: 对于某些业务逻辑错误(如参数错误、无数据、积分不足),Tushare的某些接口可能会返回一个包含错误代码 (
code
) 和错误信息 (msg
) 字段的特殊响应,而不是直接抛出异常。用户需要检查这些字段来判断请求的真实状态。
# 示例:检查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:# # 处理正常数据# pass
- 内置重试: 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.4 Tushare基础数据获取与处理 —— 股票行情数据
股票行情数据是金融分析中最基础也是最核心的数据类型。Tushare Pro提供了丰富的接口来获取不同频率、不同类型的股票行情数据。
-
1.4.1 获取交易日历 (
trade_cal
)
在进行任何与交易日相关的分析之前,获取准确的交易日历是至关重要的一步。交易日历告诉我们哪些天是开市交易的,哪些天是休市的。-
接口说明:
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): 上一个交易日(当前日期是交易日才有这个字段,非交易日为空)。
-
代码示例与详细解释:
import tushare as tsimport pandas as pdimport osfrom datetime import datetime, timedelta# --- 初始化Tushare Pro接口 ---MY_TUSHARE_TOKEN = \"YOUR_ACTUAL_TOKEN_HERE\" # 请替换为您的真实Tokenif MY_TUSHARE_TOKEN == \"YOUR_ACTUAL_TOKEN_HERE\" or not 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) # 调用接口获取所有日历信息 if not 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为1 print(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\' if not 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开市日历 if not 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\') # 调用接口 if not 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}\") # 打印错误信息
代码解释:
- 初始化: 前面的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个交易日之前/之后的日期,跳过周末和法定节假日。
- 数据完整性检查: 确认获取到的行情数据或财务数据是否覆盖了所有预期的交易日。
-
-
1.4.2 获取股票日线行情 (
daily
)
日线行情数据是进行技术分析、策略回测、市场研究的基础。Tushare提供了daily
接口来获取A股的日线行情数据。-
接口说明:
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): 成交额 (千元)。
-
代码示例与详细解释:
import tushare as tsimport pandas as pdimport osimport 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\' not in globals(): 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接口 if not 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代码和单个交易日 if not 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(</
-