AttributeError: 'Series' object has no attribute 'append' with pandas_ta library

190 Views Asked by At

I'm trying to apply technical finance indicators to data I fetch from Yahoo Finance. I found the pandas_ta library which seemed to fit my needs, however, applying a strategy gives me errors. Specifically, I want to use the AllStrategy (the default strategy), which applies all indicators to the data.

Initially, I was having issues with TA-Lab and thought this was related, however, after installing the TA-Lab source package and building it manually, I still encountered the same errors.

I found what seems to be a list of the categories that the AllStrategy is meant to apply using the help(df.ta.strategy)-command. When applying them separately, it seems like the "overlap" indicators are causing this specific issue. Additionally, applying the "trend" indicators outputs [X] Not an available strategy..

From what I can find it looks like the append from pandas has been deprecated, but is there a way to circumvent this? I found a post (and received an answer here) that said it could be temporarily fixed using pd.Series.append = pd.Series._append, but I get the same error with and without this line.

Also, quite pandas_ta-specific, but why are the "utility" indicators not an available strategy?

Any help is appreciated - even if you could point me in the direction of a library that does something similar I would be very thankful!


I have the following method to fetch and apply indicators:

import pandas as pd
import yfinance as yf
import pandas_ta as ta

pd.Series.append = pd.Series._append # Same error with and without this line

def fetch_and_analyze(ticker, interval='1d'):
    # Fetching historical data
    data = yf.download(ticker, period=period, interval=interval)
    
    # Check if data is empty
    if data.empty:
        print("No data fetched for ticker:", ticker)
        return pd.DataFrame()

    # Applying a simpler strategy from pandas_ta to ensure it works
    # data.ta.strategy('candles', timed=True)
    # data.ta.strategy('cycles', timed=True)
    # data.ta.strategy('momentum', timed=True)
    # data.ta.strategy('overlap', timed=True) <--- ERROR
    # data.ta.strategy('performance', timed=True)
    # data.ta.strategy('statistics', timed=True)
    # data.ta.strategy('trend', timed=True) 
    # data.ta.strategy('utility', timed=True) <- [X] Not an available strategy.
    # data.ta.strategy('volatility', timed=True)
    # data.ta.strategy('volume', timed=True)
    
    data.ta.strategy('all', timed=True)

    return data

data_with_indicators = fetch_and_analyze(ticker)

Which gives me the following error:

---------------------------------------------------------------------------
RemoteTraceback                           Traceback (most recent call last)
RemoteTraceback: 
"""
Traceback (most recent call last):
  File "C:\Python311\Lib\multiprocessing\pool.py", line 125, in worker
    result = (True, func(*args, **kwds))
                    ^^^^^^^^^^^^^^^^^^^
  File "C:\Python311\Lib\multiprocessing\pool.py", line 48, in mapstar
    return list(map(*args))
           ^^^^^^^^^^^^^^^^
  File "c:\Users\x\stock-analysis\Lib\site-packages\pandas_ta\core.py", line 467, in _mp_worker
    return getattr(self, method)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\x\stock-analysis\Lib\site-packages\pandas_ta\core.py", line 1225, in mcgd
    result = mcgd(close=close, length=length, offset=offset, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\x\stock-analysis\Lib\site-packages\pandas_ta\overlap\mcgd.py", line 24, in mcgd
    mcg_ds = close[:1].append(mcg_cell[1:])
             ^^^^^^^^^^^^^^^^
  File "c:\Users\x\stock-analysis\Lib\site-packages\pandas\core\generic.py", line 6204, in __getattr__
    return object.__getattribute__(self, name)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Series' object has no attribute 'append'
"""

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

AttributeError                            Traceback (most recent call last)
Cell In[124], line 1
----> 1 data_with_indicators = fetch_and_analyze(ticker)

Cell In[123], line 20
      8     return pd.DataFrame()
     10 # Applying a simpler strategy from pandas_ta to ensure it works
     11 # data.ta.strategy('candles', timed=True)
     12 # data.ta.strategy('cycles', timed=True)
   (...)
     18 # data.ta.strategy('volatility', timed=True)
     19 # data.ta.strategy('volume', timed=True)
---> 20 data.ta.strategy('all', timed=True)
     22 return data

File c:\Users\x\stock-analysis\Lib\site-packages\pandas_ta\core.py:792, in AnalysisIndicators.strategy(self, *args, **kwargs)
    789         self._last_run = get_time(self.exchange, to_string=True)
    791 # Apply prefixes/suffixes and appends indicator results to the  DataFrame
--> 792 [self._post_process(r, **kwargs) for r in results]
    794 if verbose:
    795     print(f"[i] Total indicators: {len(ta)}")

File c:\Users\x\stock-analysis\Lib\site-packages\pandas_ta\core.py:792, in <listcomp>(.0)
    789         self._last_run = get_time(self.exchange, to_string=True)
    791 # Apply prefixes/suffixes and appends indicator results to the  DataFrame
--> 792 [self._post_process(r, **kwargs) for r in results]
    794 if verbose:
    795     print(f"[i] Total indicators: {len(ta)}")

File C:\Python311\Lib\multiprocessing\pool.py:423, in <genexpr>(.0)
    415 result = IMapIterator(self)
    416 self._taskqueue.put(
    417     (
    418         self._guarded_task_generation(result._job,
   (...)
    421         result._set_length
    422     ))
--> 423 return (item for chunk in result for item in chunk)

File C:\Python311\Lib\multiprocessing\pool.py:873, in IMapIterator.next(self, timeout)
    871 if success:
    872     return value
--> 873 raise value

AttributeError: 'Series' object has no attribute 'append'
1

There are 1 best solutions below

0
A10 On

Would something like this work for you -- redefine the append method for your series object?

import pandas as pd # or your version

class Series(pd.Series):
    
    def append(self, b):
        self = pd.concat([self, b], ignore_index=True)
        return self 
    
pd.Series = Series

a = [i for i in range(10)]
b = [i + 10 for i in range(10)]

a = pd.Series(a)
b = pd.Series(b)

a.append(b)

This would allow you to use a custom append method and instead with the preferred concat syntax.