🚀 AI 一键生成 ptrade 策略代码

ptrade 平台 get_fundamentals 财务数据调用失败的解决方案与代码示例

ptrade | 发布时间: 2026/5/28
以下内容由 EasyQuant 生成。

问题描述

财务数据调用失败

财务接口(如get_fundamentals)依赖在线调用,瞬时流量过大易失败。

解决方案

问题原因分析

在 ptrade 量化平台中,调用 get_fundamentals 接口获取财务数据时,如果遇到调用失败或返回空值(None/空DataFrame),通常是由以下两个原因引起的:

  1. 网络拥堵与在线获取机制get_fundamentals 接口底层是通过 HTTP 在线获取数据的。在盘中或回测的密集计算期,网络拥堵可能导致请求超时或应答失败。
  2. 严格的流量限制(流控):官方文档明确指出,该接口有严格的流量限制:每秒不得调用超过100次,单次最大调用量是500条数据(一条数据定义为一个股票对应一个表的一个字段)。如果策略中存在多股、多字段的循环查询,极易触发流控机制导致获取失败。

解决方案

为了保证策略的健壮性,必须在代码中加入保护机制

  1. 加入时间间隔(Sleep):在连续调用财务接口之间,使用 time.sleep() 强制暂停,避免触发每秒调用次数限制。
  2. 增加异常重试机制(Retry):封装一个带有重试逻辑的函数,当返回结果为空或发生异常时,等待片刻后重新发起请求。

最佳实践代码示例

以下是一个封装好的、带有重试机制和防流控延时的财务数据获取函数示例:

import time
import pandas as pd

def get_fundamentals_with_retry(security, table, fields=None, date=None, max_retries=3, sleep_time=1):
    '''
    带有重试机制的财务数据获取函数
    :param security: 股票代码或列表
    :param table: 财务表名
    :param fields: 字段名
    :param date: 查询日期
    :param max_retries: 最大重试次数
    :param sleep_time: 每次重试前的等待时间(秒)
    :return: DataFrame 或 None
    '''
    for attempt in range(max_retries):
        try:
            # 调用官方接口
            df = get_fundamentals(security, table, fields=fields, date=date)
            
            # 检查返回值是否有效(非空且包含数据)
            if df is not None and not df.empty:
                return df
            else:
                log.warning(f'第 {attempt + 1} 次获取财务数据为空,等待重试...')
        except Exception as e:
            log.error(f'第 {attempt + 1} 次获取财务数据发生异常: {e}')
        
        # 触发重试前等待,防止流控
        time.sleep(sleep_time)
    
    log.error('达到最大重试次数,获取财务数据失败!')
    return None

def initialize(context):
    g.security = ['600570.SS', '000001.SZ']
    set_universe(g.security)

def before_trading_start(context, data):
    # 使用封装好的函数获取数据
    # 假设我们需要获取资产负债表中的总资产
    funda_data = get_fundamentals_with_retry(
        security=g.security, 
        table='balance_statement', 
        fields='total_assets'
    )
    
    if funda_data is not None:
        log.info('成功获取财务数据:')
        log.info(funda_data)
    else:
        log.error('盘前获取财务数据失败,请检查网络或策略逻辑。')

def handle_data(context, data):
    pass

注意事项

  • 避免在 handle_data 中高频调用handle_data 在分钟或 Tick 级别会频繁触发,强烈建议将财务数据的获取逻辑放在 before_trading_start(盘前)或使用 run_daily 定时获取,并将结果缓存到全局变量 g 中供盘中调用。
  • 批量获取优于循环单只获取:尽量将多只股票代码组成 list 一次性传入 get_fundamentals,而不是使用 for 循环单只获取,这样可以大幅减少接口调用次数,降低触发流控的风险(但需注意单次500条数据的上限)。