问题描述
在取财务数据时,平台限制一次只能取3000条记录,但是实际需要统计的数据可能有上万条。请教下,有没有有效的解决方法?有语句最好了。
谢谢。
解决方案
在 JoinQuant(聚宽)平台上,为了防止单次请求返回的数据量过大导致内存溢出或服务器压力过大,官方对 get_fundamentals 等财务数据查询 API 设置了单次返回条数的限制(官方文档目前标注的上限是 5000条)。
当您需要统计全市场(目前A股有5000多只股票)的财务数据时,单次查询必然会被截断。最有效且通用的解决方法是:分批获取(Batch Query)并拼接数据。
核心解决思路
将全市场的股票代码列表(或您需要查询的庞大股票池)切分成多个小批次(例如每批 500 只股票),然后利用 for 循环结合 in_() 过滤条件,分批调用 get_fundamentals,最后使用 pandas.concat 将所有批次的结果合并成一个完整的 DataFrame。
Python 代码示例
以下是一个封装好的分批获取财务数据的通用函数示例,您可以直接在研究环境或策略中使用:
import pandas as pd
from jqdata import *
def get_fundamentals_in_batches(base_query, date=None, statDate=None, batch_size=500):
"""
分批获取财务数据,突破单次 5000 条的限制。
:param base_query: 基础的 sqlalchemy query 对象(不需要包含 code.in_ 过滤)
:param date: 查询日期
:param statDate: 财报统计的季度或者年份
:param batch_size: 每批次查询的股票数量,建议设置在 500-1000 之间
:return: 包含所有查询结果的 pandas.DataFrame
"""
# 1. 获取全市场所有股票代码(如果您有特定的股票池,可以替换这里)
all_stocks = list(get_all_securities(['stock']).index)
result_list = []
# 2. 将股票列表分批
for i in range(0, len(all_stocks), batch_size):
batch_stocks = all_stocks[i : i + batch_size]
# 3. 在基础 query 上追加当前批次的股票过滤条件
# 注意:这里假设您查询的表中包含 valuation.code,如果是其他表请替换为对应的 code 字段
# 例如:income.code.in_(batch_stocks)
q = base_query.filter(valuation.code.in_(batch_stocks))
# 4. 获取当前批次数据
df = get_fundamentals(q, date=date, statDate=statDate)
if not df.empty:
result_list.append(df)
# 5. 合并所有批次的数据
if result_list:
final_df = pd.concat(result_list, ignore_index=True)
return final_df
else:
return pd.DataFrame()
# ================= 使用示例 =================
# 假设我们要查询全市场股票的总市值、市盈率和营业总收入
q = query(
valuation.code,
valuation.market_cap,
valuation.pe_ratio,
income.total_operating_revenue
)
# 调用分批获取函数(注意:date 和 statDate 只能传入一个)
all_data_df = get_fundamentals_in_batches(q, date='2023-10-10', batch_size=800)
print(f"成功获取到 {len(all_data_df)} 条财务数据!")
print(all_data_df.head())
注意事项与优化建议
- 表字段对应:在
filter中使用.in_()时,请确保使用的code字段与您query中查询的主表一致。例如,如果您只查income表,过滤条件应写为income.code.in_(batch_stocks)。 - Batch Size 设置:
batch_size不宜设置过大(避免单次依然超过5000条,特别是当您进行了复杂的连表查询导致产生多条记录时),也不宜设置过小(会导致 API 调用次数过多,降低运行速度)。通常设置为500到1000是比较稳妥的。 - 内存管理:如果您不仅查询全市场,还要查询多年的历史数据,合并后的 DataFrame 可能会非常大。建议在研究环境中操作,如果遇到内存瓶颈,可以考虑将每批次的数据直接追加写入到 CSV 文件中(使用
write_file或to_csv(mode='a')),而不是全部保存在内存里。