问题描述
代码:
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()。
修改方案
- 增加数据长度判断:在计算均线前,判断获取到的数据长度是否满足最大周期(583天),如果不满足则跳过该股票。
- 修正均线计算切片:将
[-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 平台中,这种写法会导致极严重的性能问题(运行极慢甚至超时被系统强杀)。建议进行以下优化:
- 缩小股票池:不要直接用
get_all_securities,建议使用get_index_stocks('000300.XSHG')(沪深300) 或过滤掉 ST、停牌、上市不足两年的股票。 - 批量获取数据:使用
history或get_price传入股票列表(list),一次性获取多只股票的数据,而不是放在for循环里一只一只取。这能将运行速度提升几十倍。