🚀 AI 一键生成 joinquant 策略代码

聚宽 JoinQuant 策略中 get_ticks 导致内存超限被强杀怎么办?

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

问题描述

get_ticks 容易导致内存占用过大,被强制杀掉?

我的程序中会针对每一个股票调用一次 get_ticks。
每次使用之后,即使通过 del ticks,也很容易导致内存占用过大,被强制杀掉。所以怀疑是不是 get_ticks本身有问题,悄悄摸摸占用了内存没释放?

解决方案

在 JoinQuant 聚宽平台中,频繁调用 get_ticks 导致内存占用过大并被系统强制杀掉进程(通常平台限制内存为 3G),是一个非常常见的问题。这通常并不是 get_ticks 本身存在恶意的内存泄漏,而是由 Python 的内存管理机制以及平台的底层缓存机制共同导致的。

为什么 del 之后内存依然没有释放?

  1. 平台的底层缓存机制:为了加快回测和运行速度,JoinQuant 默认开启了数据缓存。当你调用 get_ticks 时,底层可能会将这些庞大的 tick 数据缓存起来,导致即使你在应用层 del 了变量,底层缓存依然持有对这些数据的引用,内存无法释放。
  2. Python 的垃圾回收(GC)机制:Python 使用引用计数和分代回收机制。del ticks 仅仅是删除了变量名对对象的引用,如果存在循环引用或底层缓存引用,对象不会被销毁。此外,Python 的垃圾回收并不总是实时的,在密集循环中可能来不及回收就触发了平台的内存上限。
  3. Tick 数据本身极其庞大:Tick 数据包含买五卖五等大量盘口信息,如果股票池较大或获取的时间跨度较长,瞬间的内存峰值极高。

解决方案与优化建议

要彻底解决这个问题,建议结合以下几种方法对代码进行优化:

1. 关闭系统缓存(最关键)

在策略的 initialize 函数中调用 disable_cache()。这会关闭系统的默认缓存机制,防止底层悄悄囤积数据。注意:关闭缓存可能会导致策略整体运行速度有所下降,但能有效控制内存。

def initialize(context):
    # 关闭缓存,防止底层缓存大量 tick 数据导致内存超限
    disable_cache()
    # 其他初始化代码...

2. 手动触发垃圾回收

在循环获取每只股票的 tick 数据并在处理完毕后,除了使用 del,还可以引入 gc 模块,手动强制进行垃圾回收。

import gc

def handle_data(context, data):
    stocks = get_index_stocks('000300.XSHG')
    for stock in stocks:
        # 获取 tick 数据
        ticks = get_ticks(stock, end_dt=context.current_dt, count=100)
        
        # ... 进行你的数据处理逻辑 ...
        
        # 处理完毕后,删除变量并强制回收内存
        del ticks
        gc.collect()

3. 优化 get_ticks 的参数

  • 使用 df=False:默认情况下 df=False 返回的是 numpy.ndarray,这比 pandas.DataFrame (df=True) 的内存占用要小得多。如果不需要 DataFrame 的高级特性,尽量使用 numpy 数组。
  • 按需获取字段 (fields):默认会返回很多字段(如买五卖五等)。如果你只需要最新价和成交量,可以通过 fields 参数限制返回的数据列,大幅减少内存开销。
# 仅获取时间和最新价,且返回 numpy 数组
ticks = get_ticks(stock, end_dt=context.current_dt, count=100, fields=['time', 'current'], df=False)

4. 减少单次获取的数据量

尽量避免一次性获取过长时间跨度的 tick 数据。如果必须处理大量数据,考虑将大时间段拆分为多个小时间段,分批获取、分批处理、分批释放。

总结

在处理 Tick 级别的高频数据时,内存管理尤为重要。通过 disable_cache() + gc.collect() + 优化返回数据结构 的组合拳,基本可以彻底解决 get_ticks 导致的内存超限被杀进程的问题。