问题描述
通过get_fundamentals获取一些代码的财务数据,前面的代码能获取到,取到688开头的代码就会获取失败?提示:获取688XXX.SS数据为空,请查看争取拿代码是否正确或联系管理员!
解决方案
在 ptrade 平台中使用 get_fundamentals 函数获取财务数据时,如果前面的股票代码能正常获取,但运行到后面(如 688 开头的科创板股票)时提示获取失败或数据为空,通常是由以下几个原因导致的:
1. 触发了 API 的流控限制(最常见原因)
根据 ptrade API 文档说明,get_fundamentals 接口为 HTTP 在线获取,存在严格的流量限制:每秒不得调用超过 100 次,单次最大调用量是 500 条数据。如果您在 for 循环中逐个遍历股票代码进行查询,很容易在运行一段时间后触发频率限制,导致后续的请求(如排在后面的 688 股票)被服务器拒绝并返回空数据。
2. 股票上市时间晚于查询日期
科创板(688开头)股票普遍上市时间较晚。如果您查询的财务数据日期(date 或 start_year)早于该股票的上市日期,接口自然会返回空数据。
3. 网络拥堵或请求超时
由于是 HTTP 请求,偶尔的网络波动也会导致单次请求失败。
💡 解决方案与代码优化建议
为了解决这个问题,建议对代码进行以下优化:
方案一:改用列表批量查询(强烈推荐)
不要在 for 循环中单只股票查询,而是将股票代码组成一个 list,一次性传入 get_fundamentals。这样不仅速度快,而且能有效避免触发每秒调用次数的限制。
def before_trading_start(context, data):
# 假设 g.security 是包含多只股票的列表,包括 688 开头的股票
# g.security = ['600570.SS', '688001.SS', '688002.SS', ...]
# 批量查询,注意单次查询的数据量(股票数 * 字段数)不要超过 500 条
try:
funda_data = get_fundamentals(
security=g.security,
table='balance_statement',
fields=['total_assets', 'total_liability'],
date='20230930'
)
log.info("批量获取财务数据成功")
log.info(funda_data)
except Exception as e:
log.error(f"获取财务数据异常: {e}")
方案二:在循环查询中加入 time.sleep() 和重试机制
如果业务逻辑必须逐个查询,或者批量查询的数据量超过了 500 条的限制,必须在循环中加入延时(time.sleep),并增加失败重试机制。
import time
def before_trading_start(context, data):
stock_list = ['600570.SS', '688001.SS', '688002.SS'] # 示例列表
for stock in stock_list:
max_retries = 3
for attempt in range(max_retries):
try:
# 逐个查询
df = get_fundamentals(stock, 'valuation', 'pe_dynamic')
if df is not None and not df.empty:
log.info(f"成功获取 {stock} 的数据")
break # 成功则跳出重试循环
else:
log.warning(f"{stock} 数据为空,可能未上市或触发流控,准备重试...")
except Exception as e:
log.error(f"查询 {stock} 发生异常: {e}")
# 每次请求后休眠 0.1 秒,失败重试前休眠更长时间
time.sleep(0.5 if attempt > 0 else 0.1)
总结排查步骤:
- 检查代码后缀:确保科创板代码后缀是
.SS(如688001.SS),这在 ptrade 中是正确的(上交所均为.SS)。 - 检查查询日期:确认查询的
date时,该 688 股票已经上市并发布了财报。 - 优化调用频率:严格遵守单次最大 500 条和每秒不超过 100 次的限制,优先使用
list批量传入,必要时引入time.sleep()。