Navid Yaghmaei
Navid Yaghmaei

Reputation: 15

Backtrader throws attribute error on the data i have given

The Data I am using is throwing a Attribute Error:

[*********************100%***********************]  1 of 1 completed
Traceback (most recent call last):
  File "C:\Users\Navid\AppData\Roaming\JetBrains\PyCharmCE2024.2\scratches\scratch.py", line 58, in <module>
    cerebro.run()
  File "D:\MyFolders\Code\Oracle\venv\Lib\site-packages\backtrader\cerebro.py", line 1132, in run
    runstrat = self.runstrategies(iterstrat)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\MyFolders\Code\Oracle\venv\Lib\site-packages\backtrader\cerebro.py", line 1215, in runstrategies
    data._start()
  File "D:\MyFolders\Code\Oracle\venv\Lib\site-packages\backtrader\feed.py", line 203, in _start
    self.start()
  File "D:\MyFolders\Code\Oracle\venv\Lib\site-packages\backtrader\feeds\pandafeed.py", line 212, in start
    colnames = [x.lower() for x in self.p.dataname.columns.values]
                ^^^^^^^
AttributeError: 'tuple' object has no attribute 'lower'
from backend.src.strategies import SimpleMovingAverageCrossover
import backtrader as bt
import yfinance as yf

# Create a Cerebro engine instance
cerebro = bt.Cerebro()


# Download historical data from Yahoo Finance
data = bt.feeds.PandasData(dataname=yf.download('BTC-USD', start='2020-01-01', end='2020-12-31'))
cerebro.adddata(data)


# Run and plot
cerebro.run()
cerebro.plot()

What I tried: I have copy pasted the code from this website: https://blog.quantinsti.com/backtrader/ I have checked other stackoverflow questions I have asked ChatGPT I have used:

data = bt.feeds.YahooFinanceData('AAPL')
cerebro.adddata(data)

Which did't work either and also raised error trying to read 'AAPL'

Upvotes: 1

Views: 693

Answers (2)

David Wong
David Wong

Reputation: 21

Try to set multi_level_index=False:

   df = yf.download(ticker, start=start_date, end=end_date),multi_level_index=False)

Upvotes: 2

Porco
Porco

Reputation: 1

Try This Function

def GetDataFromYahoo(ticker, start_date, end_date):
    # Fetch data from Yahoo Finance
    df = yf.download(ticker, start=start_date, end=end_date)

    # Check if the DataFrame is empty
    if df.empty:
        raise ValueError(f"No data found for ticker {ticker} between {start_date} and {end_date}")

    # Flatten multi-level columns by dropping the 'Ticker' level
    if isinstance(df.columns, pd.MultiIndex):
        df.columns = df.columns.droplevel(1)  # Remove the second level (Ticker)

    # Reset the index and rename 'Date' to 'datetime'
    df.reset_index(inplace=True)
    df.rename(columns={'Date': 'datetime'}, inplace=True)
    df['datetime'] = pd.to_datetime(df['datetime'])  # Ensure datetime format is correct

    # Set 'datetime' as the index
    df.set_index('datetime', inplace=True)

    # Convert to Backtrader data format
    data = bt.feeds.PandasData(
        dataname=df,
        datetime=None,  # Backtrader will automatically pick the index as datetime
        open='Open',
        high='High',
        low='Low',
        close='Close',
        volume='Volume',
        openinterest=None  # No open interest
    )

    return data

Upvotes: -1

Related Questions