bt回测报错AttributeError: 'Series' object has no attribute 'columns'如何解决
错误原因
- 直接触发报错的核心原因:
bt.Backtest要求传入的价格数据必须是以时间为索引、每列对应一个标的资产价格的DataFrame对象,你代码中传入的df["close"]是pandas Series类型,Series没有columns属性,因此框架读取价格数据的列名时抛出该异常。 - 此外代码还存在两处隐性问题:
- 未将Binance返回的原始K线数据中的时间戳转为datetime类型并设置为DataFrame索引,bt框架依赖时间索引完成回测时序计算。
- 未将K线的开高低收成交量等字段从字符串转为数值类型,也未补充MA30指标的计算逻辑,
SelectWhere的判断条件无法正常生效。
修复方案
按如下步骤修改代码即可解决问题:
- 先完成原始K线数据的清洗、索引设置和指标计算
- 将收盘价转为单列DataFrame传入回测
- 将选股条件转为和价格数据同索引的布尔DataFrame传入
SelectWhere
修改后的可运行代码如下:
import pandas as pd import talib import bt import matplotlib.pyplot as plt from binance.client import Client # 原始K线获取 client = Client() klines = client.get_historical_klines("BNBUSDT", Client.KLINE_INTERVAL_1DAY, "1 jul, 2021") df = pd.DataFrame(klines) # 数据清洗:重命名列、转数值、设置时间索引 df.rename(columns={ df.columns[0]: 'open time', df.columns[1]: 'open', df.columns[2]: 'high', df.columns[3]: 'low', df.columns[4]: 'close', df.columns[5]: 'volume' }, inplace=True) # 时间戳转datetime并设为索引 df['open time'] = pd.to_datetime(df['open time'], unit='ms') df.set_index('open time', inplace=True) # 开高低收转浮点型 df[['open', 'high', 'low', 'close', 'volume']] = df[['open', 'high', 'low', 'close', 'volume']].astype(float) # 计算MA30指标 df['MA30'] = talib.SMA(df['close'], timeperiod=30) # 构造回测用的价格DataFrame(单列,列名对应标的名称BNBUSDT) price_df = df[['close']].rename(columns={'close': 'BNBUSDT'}) # 构造选股条件布尔DataFrame signal_df = (df[['close']] > df[['MA30']].values).rename(columns={'close': 'BNBUSDT'}) # 定义策略 bt_strategy = bt.Strategy('AboveSMA', [bt.algos.SelectWhere(signal_df), bt.algos.WeighEqually(), bt.algos.Rebalance()]) # 创建回测并运行 bt_backtest = bt.Backtest(bt_strategy, price_df) bt_result = bt.run(bt_backtest) # 绘制回测结果 bt_result.plot(title='Backtest result') plt.show()
内容的提问来源于stack exchange,提问作者Leandro Quintana
相关产品推荐
相关产品推荐

