🚀 AI 一键生成 ptrade 策略代码
立即体验

ptrade 获取大量历史数据太慢?教你用 is_dict 参数实现百倍级速度优化

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

问题描述

ptrade 性能优化:使用 is_dict 加速 get_history 数据获取
ptrade 获取大量历史数据太慢,如何通过 is_dict 参数进行速度优化?

解决方案

ptrade 性能优化:使用 is_dict 加速 get_history 数据获取

在 ptrade 平台编写量化策略时,频繁或批量调用 get_historyget_price 获取历史行情数据是常见的操作。然而,当订阅的股票池较大(如几百只股票)或获取的 K 线数量较多时,默认返回的 pandas.DataFramepandas.Panel 对象会因为 Pandas 内部重建索引和格式转换而产生极大的耗时,导致策略出现卡顿甚至超时。

为了解决这一痛点,ptrade 提供了 is_dict 参数。通过将 is_dict 设置为 True,API 将直接返回结构化的 NumPy 数组(numpy.ndarray),绕过 Pandas 的封装,从而实现数据获取速度的质的飞跃。


一、 为什么 is_dict=True 能极大地加速?

  1. 避免 Pandas 封装开销:Pandas 的 DataFrame 在构建时需要处理行索引(DatetimeIndex)和列索引,对于多股多字段数据,这种内存重构非常耗时。而 is_dict=True 返回的是原生的 NumPy 结构化数组,内存连续,创建速度极快。
  2. 数据格式紧凑:返回的 OrderedDict 结构中,Key 为股票代码,Value 为 NumPy 数组,非常适合高频循环和快速数值计算(如配合 TA-Lib 使用)。

二、 get_historyis_dict 参数详解

1. 接口定义

get_history(count, frequency='1d', field='close', security_list=None, fq=None, include=False, fill='nan', is_dict=False)
  • is_dict:选填参数,默认为 False。设置为 True 时,返回字典格式 {str: array()},取数速度相对较快。

2. 返回数据格式对比

  • is_dict=False(默认)
    返回 pandas.DataFramepandas.Panel。在多股多字段下,行索引为时间,列索引为股票代码和字段。

  • is_dict=True
    返回 OrderedDict。其结构如下:

    OrderedDict([
        ('600570.SS', array([
            (202309220931, 11.03, 11.07), 
            (202309220932, 11.07, 11.05)
        ], dtype={'names': ['datetime', 'open', 'close'], 'formats': ['i8', 'f8', 'f8']}))
    ])
    

三、 优化实战:代码示例

以下是一个完整的 ptrade 策略示例,展示了如何使用 is_dict=True 批量获取历史数据,并高效提取其中的收盘价进行均线计算。

def initialize(context):
    # 设置操作的股票池(以沪深300成分股为例,标的数量较多时优化效果极明显)
    g.security = get_index_stocks('000300.XBHS')
    set_universe(g.security)

def handle_data(context, data):
    # 1. 开启 is_dict=True 获取过去5天的收盘价和开盘价
    # 此时返回的是 OrderedDict,速度比默认返回 DataFrame 快数倍至数十倍
    history_dict = get_history(
        count=5, 
        frequency='1d', 
        field=['open', 'close'], 
        security_list=g.security, 
        is_dict=True
    )
    
    if not history_dict:
        return
        
    # 2. 高效遍历和处理数据
    for security in g.security:
        if security in history_dict:
            # 获取该只股票的 NumPy 结构化数组
            stock_data = history_dict[security]
            
            # 直接通过字段名提取数据,无需转化为 DataFrame
            close_prices = stock_data['close']  # 这是一个 numpy.ndarray
            open_prices = stock_data['open']
            
            # 计算 5 日均价
            ma5 = close_prices.mean()
            
            # 获取当前最新价
            current_price = data[security]['close']
            
            # 简单的均线突破策略逻辑
            if current_price > ma5 and get_position(security).amount == 0:
                order(security, 100)
                log.info(f"{security} 突破5日均线,买入 100 股")

四、 更多 ptrade 数据获取性能优化建议

  1. get_price 同样支持 is_dict:在研究模块或盘前准备阶段,如果需要获取大段时间的历史数据,调用 get_price 时也务必加上 is_dict=True
  2. 避免多线程冲突:根据 ptrade 官方文档,get_historyget_price 接口不支持多线程同时调用。请避免在 run_dailyrun_interval 等定时任务中,与 handle_data 框架模块在同一时刻并发调用这两个接口,否则可能会偶现获取数据为空的现象。
  3. L2 逐笔数据强制推荐 is_dict:在交易模块中,如果获取股票数很多( >200只 )的 Level 2 逐笔数据(如 get_individual_transaction),必须使用 is_dict=True,否则由于数据量过大,默认格式极易返回 None