backtesting.py多时间框架回测报错:RangeIndex类型不兼容问题修复
问题定位与修正:backtesting.py多时间框架回测报错TypeError
问题背景
用户编写基于backtesting.py的多时间框架回测程序,运行时触发如下错误:
TypeError: Only valid with DatetimeIndex, TimedeltaIndex or PeriodIndex, but got an instance of 'RangeIndex'
完整代码如下:
import os import warnings from datetime import datetime !pip install pandas_ta > /dev/null 2>&1 import pandas as pd import pandas_ta as ta import numpy as np import matplotlib.pyplot as plt !pip install --upgrade backtesting > /dev/null 2>&1 from backtesting import Backtest, Strategy from backtesting.lib import resample_apply, crossover from backtesting.test import SMA from google.colab import drive drive.mount('/content/drive') # ------------------------------------------------------- # Data pre-processing # ------------------------------------------------------- # File path to retrieve file_name = "/content/drive/.../EURUSD_M15_2023" # If a pickle file exists, retrieve it try: data = pd.read_pickle(f"{file_name}.pkl") # If a pickle file does not exist, retrieve the csv except: data = pd.read_table(f"{file_name}.csv", sep='\t') # Change column names (Must include Open, High, Low, Close) data = data.rename(columns={'<OPEN>': 'Open', '<HIGH>': 'High', '<LOW>': 'Low', '<CLOSE>': 'Close', '<VOL>': 'Volume'}) # Convert the date of the data to datetime type data['datetime'] = pd.to_datetime(data['<DATE>']+ ' '+ data['<TIME>']) # Specify datetime as the index data = data.set_index('datetime') # Save as a pkl file and store it in the drive data.to_pickle(f"{file_name}.pkl") # ------------------------------------------------------- # Logic Description # ------------------------------------------------------- class Strategry(Strategy): def init(self): rsi_window = 14 upper_bound = 70 lower_bound = 30 close = pd.Series(self.data.Close) self.daily_rsi = self.I(ta.rsi, close, self.rsi_window) self.weekly_rsi = resample_apply('W-FRI', ta.rsi, pd.Series(self.data.Close), self.rsi_window) def next(self): if (crossover(self.daily_rsi, self.upper_bound) and self.weekly_rsi[-1] > self.upper_bound): self.position.close() elif (crossover(self.lower_bound, self.daily_rsi) and self.lower_bound > self.weekly_rsi[-1]): self.buy()
问题定位
- 索引类型丢失:读取pickle文件时,原本设置的DatetimeIndex被转为RangeIndex,导致
resample_apply无法按时间周期重采样,触发类型错误。 - 类名拼写错误:
Strategry应为Strategy,会导致策略无法正确初始化。 - 参数作用域问题:
rsi_window、upper_bound、lower_bound是init方法的局部变量,next方法无法访问,后续会引发NameError。
修正方法
1. 强制保留DatetimeIndex
读取pickle后强制转换索引为DatetimeIndex,避免类型丢失:
try: data = pd.read_pickle(f"{file_name}.pkl") # 强制转换索引为DatetimeIndex data.index = pd.to_datetime(data.index) except: # 原csv处理代码不变 ...
2. 修正策略类拼写
将类名改为正确的自定义名称(避免与父类冲突):
class MyStrategy(Strategy): ...
3. 调整参数为类属性
把策略参数定义为类属性,确保init和next方法都能访问:
class MyStrategy(Strategy): # 定义类属性参数 rsi_window = 14 upper_bound = 70 lower_bound = 30 def init(self): close = pd.Series(self.data.Close) self.daily_rsi = self.I(ta.rsi, close, self.rsi_window) self.weekly_rsi = resample_apply('W-FRI', ta.rsi, pd.Series(self.data.Close), self.rsi_window) def next(self): if (crossover(self.daily_rsi, self.upper_bound) and self.weekly_rsi[-1] > self.upper_bound): self.position.close() elif (crossover(self.lower_bound, self.daily_rsi) and self.lower_bound > self.weekly_rsi[-1]): self.buy()
4. 补充回测执行代码
原代码缺少回测运行逻辑,添加以下代码触发回测:
# 初始化回测 bt = Backtest(data, MyStrategy, cash=10000, commission=0.001) # 运行回测 results = bt.run() # 打印结果 print(results) # 可视化回测 bt.plot()
内容的提问来源于stack exchange,提问作者TY00
相关产品推荐
相关产品推荐

