🚀 AI 一键生成 joinquant 策略代码
立即体验
👉 AI 生成代码 👈

JoinQuant 策略报错 IndexError: index out of bounds for axis 0 怎么改?

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

问题描述

求大神指点!错误怎么改?

代码:
def initialize(context):
run_daily(period,time='every_bar')

#g.security = get_industry_stocks('B09')
g.security = list(get_all_securities(['stock']).index)
def period(context):
for stock in g.security:
close_data=get_bars(stock,count=583,unit='1d',fields=['close'])
MA5 = close_data['close'][-5].mean()
MA10 = close_data['close'][-10].mean()
MA20 = close_data['close'][-20].mean()
MA60 = close_data['close'][-60].mean()
MA120 = close_data['close'][-120].mean()
MA250 = close_data['close'][-250].mean()
MA583 = close_data['close'].mean()
current_price = close_data['close'][-1]
cash = context.portfolio.available_cash
if current_price > MA5 and MA5 > MA10 and MA10 > MA20 and MA20 > MA60 and MA60 > MA120 and MA120 > MA250 and MA250 > MA583 and (cash > 0):
order_value(stock,1000000)
elif current_price < MA5 and MA5 < MA10 and context.portfolio.positions[stock].closeable_amount > 0:
order_target(stock,0)
print(stock)
错误:
File "/tmp/strategy/user_code.py", line 15, in period
MA120 = close_data['close'][-120].mean()
IndexError: index -120 is out of bounds for axis 0 with size 76

解决方案

这个报错 IndexError: index -120 is out of bounds for axis 0 with size 76 的直接原因是:你获取到的这只股票的历史数据只有 76 天,而你试图去取倒数第 120 天的数据,导致了数组越界。 这通常是因为该股票上市时间较短,或者在回测的当前时间点,它存在的数据不足 583 天。

除了这个报错,你的代码中还有一个非常严重的逻辑错误
close_data['close'][-5].mean() 这种写法是错误的。[-5] 表示取倒数第 5 天的单日收盘价,一个数字求均值还是它本身,这并不是“过去5天的平均价”。正确的切片写法应该是 [-5:],表示取最后 5 天的数据构成数组,然后再求 .mean()

修改方案

  1. 增加数据长度判断:在计算均线前,判断获取到的数据长度是否满足最大周期(583天),如果不满足则跳过该股票。
  2. 修正均线计算切片:将 [-N] 改为 [-N:]

修改后的代码

def initialize(context):
    # 建议不要用 every_bar 跑全市场日线策略,极易超时。改为每天开盘运行一次即可
    run_daily(period, time='09:30')
    
    # 获取所有股票
    g.security = list(get_all_securities(['stock']).index)

def period(context):
    for stock in g.security:
        # 获取数据,注意 get_bars 返回的是 numpy 数组或 DataFrame
        close_data = get_bars(stock, count=583, unit='1d', fields=['close'], include_now=True)
        
        # 1. 核心修改:判断数据长度是否足够 583 天,不足则跳过该股票
        if len(close_data) < 583:
            continue
            
        # 2. 核心修改:修正切片语法,加上冒号 ':'
        MA5 = close_data['close'][-5:].mean()
        MA10 = close_data['close'][-10:].mean()
        MA20 = close_data['close'][-20:].mean()
        MA60 = close_data['close'][-60:].mean()
        MA120 = close_data['close'][-120:].mean()
        MA250 = close_data['close'][-250:].mean()
        MA583 = close_data['close'].mean() # 已经是583个数据了,直接求均值
        
        current_price = close_data['close'][-1]
        cash = context.portfolio.available_cash
        
        # 买入逻辑
        if current_price > MA5 and MA5 > MA10 and MA10 > MA20 and MA20 > MA60 and MA60 > MA120 and MA120 > MA250 and MA250 > MA583 and (cash > 0):
            # 注意:全市场选股时,如果多只股票满足条件,100万资金可能不够分,建议按比例或判断可用资金
            order_value(stock, 1000000)
            print(f"买入: {stock}")
            
        # 卖出逻辑
        elif current_price < MA5 and MA5 < MA10 and context.portfolio.positions[stock].closeable_amount > 0:
            order_target(stock, 0)
            print(f"卖出: {stock}")

💡 进阶优化建议(必看)

你目前的策略逻辑是:每天遍历全市场 4000 多只股票,每只股票单独调用一次 get_bars 获取 583 天的数据。

在 JoinQuant 平台中,这种写法会导致极严重的性能问题(运行极慢甚至超时被系统强杀)。建议进行以下优化:

  1. 缩小股票池:不要直接用 get_all_securities,建议使用 get_index_stocks('000300.XSHG') (沪深300) 或过滤掉 ST、停牌、上市不足两年的股票。
  2. 批量获取数据:使用 historyget_price 传入股票列表(list),一次性获取多只股票的数据,而不是放在 for 循环里一只一只取。这能将运行速度提升几十倍。