问题描述
解决方案
在 JoinQuant 聚宽平台上,想要一次性获取多只股票在一段时间内的市盈率(PE)数据,最推荐且最简便的方法是使用 get_valuation 函数。
该函数专门用于获取市值表(valuation)的数据,支持批量获取多只股票在指定时间段内的市盈率、市净率、总市值等数据,返回格式为 DataFrame。
以下是具体的实现代码和说明:
方法一:使用 get_valuation (推荐)
这是获取市盈率最直接的方法。
# -*- coding: utf-8 -*-
from jqdata import *
import pandas as pd
# 1. 设定股票列表
security_list = ['000001.XSHE', '600000.XSHG', '000002.XSHE']
# 2. 设定查询时间段
start_date = '2023-01-01'
end_date = '2023-01-10'
# 3. 调用 get_valuation 获取数据
# fields 参数说明:
# 'pe_ratio': 市盈率 (PE, TTM) - 滚动市盈率
# 'pe_ratio_lyr': 市盈率 (PE) - 静态市盈率
# 'turnover_ratio': 换手率
# 'market_cap': 总市值
df = get_valuation(
security_list,
start_date=start_date,
end_date=end_date,
fields=['pe_ratio', 'pe_ratio_lyr']
)
# 4. 打印结果
print(df)
返回结果示例 (DataFrame):
结果包含 code (股票代码), day (日期) 以及你请求的字段。
| code | day | pe_ratio | pe_ratio_lyr | |
|---|---|---|---|---|
| 0 | 000001.XSHE | 2023-01-03 | 6.1234 | 5.8888 |
| 1 | 000001.XSHE | 2023-01-04 | 6.2345 | 5.9999 |
| ... | ... | ... | ... | ... |
方法二:使用 get_fundamentals_continuously (通用方法)
如果你不仅需要市盈率,还需要同时查询利润表、资产负债表等其他表的数据,可以使用这个通用函数。
# -*- coding: utf-8 -*-
from jqdata import *
# 1. 设定股票列表
security_list = ['000001.XSHE', '600000.XSHG']
# 2. 构建查询对象 (查询 valuation 表中的 pe_ratio)
q = query(
valuation.pe_ratio
).filter(
valuation.code.in_(security_list)
)
# 3. 获取数据
# count=5 表示获取 end_date 往前推 5 个交易日的数据
# panel=False 建议设置为 False,直接返回 DataFrame 格式,方便处理
df = get_fundamentals_continuously(
q,
end_date='2023-01-10',
count=5,
panel=False
)
print(df)
注意事项
- 字段选择:
pe_ratio: 市盈率 (TTM),即滚动市盈率,更能反映近期盈利能力。pe_ratio_lyr: 市盈率 (LYR),即静态市盈率,基于上一年年报计算。
- 数据量限制:
get_valuation和get_fundamentals_continuously都有单次返回数据量的限制(通常为 5000 条左右)。如果查询的股票数量很多且时间跨度很长,建议分批次查询(例如按月循环或按股票分组循环),然后使用pd.concat合并结果。
- 停牌处理:
- 如果股票在期间停牌,
get_valuation返回的数据量可能会少于预期的天数(它只返回有交易数据的日期)。
- 如果股票在期间停牌,
Q&A
Q: get_valuation 和 get_fundamentals 有什么区别?
A: get_fundamentals 主要用于获取某一个时间点(横截面)的多只股票数据;而 get_valuation 和 get_fundamentals_continuously 专门用于获取一段时间内(时间序列)的多只股票数据。对于获取历史走势分析,后两者更合适。
Q: 如何处理返回数据量超过限制的问题?
A: 如果涉及全市场股票长周期的查询,建议写一个循环。例如,遍历每一只股票调用一次 get_valuation,或者将时间段切分成按月查询,最后将所有 DataFrame 拼接起来。
Q: 回测中可以使用这些函数吗?
A: 可以。在回测中,end_date 默认为回测当前的日期 (context.current_dt),要注意避免使用未来函数。在研究环境中则可以随意指定历史日期。