尝试使用回测来回测 yfinance 数据时,出现“类型错误:其他必须是 MultiIndex 或元组列表”

问题描述 投票:0回答:1

这是指定回测的代码部分。我在另一个数据框“数据”中已经有一个“信号”列,但这不是这里的问题。

temp = yf.download(
    symb,
    interval=interval,
    period=period
    )
temp.reset_index(inplace=True)
print(temp.columns)


class MyStrategy(Strategy):
    stop_factor = 0.02  # stop loss factor
    take_profit_factor = 0.04  # take profit factor for 1:2 risk-reward ratio

    def init(self):
        # Set up signals
        self.signal = self.data['signals']

    def next(self):
        # If the signal is a buy, we want to buy
        if self.signal == 1:
            self.buy(size=1, stop=self.data.close[-1] * (1 - self.stop_factor), takeprofit=self.data.close[-1] * (1 + self.take_profit_factor))
        # If the signal is a sell, we want to sell
        elif self.signal == -1:
            self.sell(size=1, stop=self.data.close[-1] * (1 + self.stop_factor), takeprofit=self.data.close[-1] * (1 - self.take_profit_factor))

# Backtest setup

bt = Backtest(temp, MyStrategy, cash=10000, commission=0.002)
stats = bt.run()

# Print the backtest results
print(stats) 

我尝试将索引更改为新的“Candle_No”列,并尝试重置索引,但没有任何效果。

这是实际显示的错误:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/usr/local/lib/python3.10/dist-packages/pandas/core/indexes/multi.py in _convert_can_do_setop(self, other)
   3853                 try:
-> 3854                     other = MultiIndex.from_tuples(other, names=self.names)
   3855                 except (ValueError, TypeError) as err:

8 frames
ValueError: Length of names must match number of levels in MultiIndex.

The above exception was the direct cause of the following exception:

TypeError                                 Traceback (most recent call last)
/usr/local/lib/python3.10/dist-packages/pandas/core/indexes/multi.py in _convert_can_do_setop(self, other)
   3856                     # ValueError raised by tuples_to_object_array if we
   3857                     #  have non-object dtype
-> 3858                     raise TypeError(msg) from err
   3859         else:
   3860             result_names = get_unanimous_names(self, other)

TypeError: other must be a MultiIndex or a list of tuples
pandas finance yahoo-finance back-testing pybacktest
1个回答
0
投票

您从

yfinance
收集的数据有
MultiIndex
列,特别是在以特定间隔下载数据时。你需要处理这个问题。为了测试解决方案,我需要添加数据(正如在评论中向您提到的,需要详细说明您的问题并且需要共享示例数据,特别是包含
data
变量的
signal
。因此,调整根据您的需求:

import pandas as pd
import yfinance as yf
from backtesting import Backtest, Strategy
import numpy as np

symb = "AAPL"
interval = "1d"
period = "1y"

temp = yf.download(
    symb,
    interval=interval,
    period=period
)
temp.reset_index(inplace=True)

temp['signals'] = np.random.choice([-1, 0, 1], size=len(temp))

if isinstance(temp.columns, pd.MultiIndex):
    temp.columns = ['_'.join(col).strip() if isinstance(col, tuple) else col for col in temp.columns]

temp.rename(columns={'Open': 'Open', 'High': 'High', 'Low': 'Low', 'Close': 'Close'}, inplace=True)

class MyStrategy(Strategy):
    stop_factor = 0.02
    take_profit_factor = 0.04

    def init(self):
        self.signal = self.data['signals']

    def next(self):
        if self.signal[-1] == 1:
            self.buy(size=1, sl=self.data.Close[-1] * (1 - self.stop_factor),
                     tp=self.data.Close[-1] * (1 + self.take_profit_factor))
        elif self.signal[-1] == -1:
            self.sell(size=1, sl=self.data.Close[-1] * (1 + self.stop_factor),
                      tp=self.data.Close[-1] * (1 - self.take_profit_factor))

bt = Backtest(temp, MyStrategy, cash=10000, commission=0.002)
stats = bt.run()

print(stats)

返回

[*********************100%%**********************]  1 of 1 completed
Start                                     0.0
End                                     251.0
Duration                                251.0
Exposure Time [%]                         0.0
Equity Final [$]                      10000.0
Equity Peak [$]                       10000.0
Return [%]                                0.0
Buy & Hold Return [%]               25.001282
Return (Ann.) [%]                         0.0
Volatility (Ann.) [%]                     NaN
Sharpe Ratio                              NaN
Sortino Ratio                             NaN
Calmar Ratio                              NaN
Max. Drawdown [%]                        -0.0
Avg. Drawdown [%]                         NaN
Max. Drawdown Duration                    NaN
Avg. Drawdown Duration                    NaN
# Trades                                  0.0
Win Rate [%]                              NaN
Best Trade [%]                            NaN
Worst Trade [%]                           NaN
Avg. Trade [%]                            NaN
Max. Trade Duration                       NaN
Avg. Trade Duration                       NaN
Profit Factor                             NaN
...
_equity_curve                   Equity  Dr...
_trades                   Empty DataFrame
...
dtype: object
© www.soinside.com 2019 - 2024. All rights reserved.