pythonpandastechnical-indicator

Applying a function to a Pandas Dataframe


I have this code with me. And I need to pass a pandas data frame in it as a parameter. It returns errors.

The Logic for the Technical Analysis Indicator is this

def williams_ad(data, high_col='High', low_col='Low', close_col='Close'):
    data['williams_ad'] = 0.
    
    for index,row in data.iterrows():
        if index > 0:
            prev_value = data.at[index-1, 'williams_ad']
            prev_close = data.at[index-1, close_col]
            if row[close_col] > prev_close:
                ad = row[close_col] - min(prev_close, row[low_col])
            elif row[close_col] < prev_close:
                ad = row[close_col] - max(prev_close, row[high_col])
            else:
                ad = 0.
                                                                                                        
            data.set_value(index, 'williams_ad', (ad+prev_value))
        
    return data

Documentation for the above code.

William's Accumulation/Distribution
Source: https://www.metastock.com/customer/resources/taaz/?p=125
Params: 
    data: pandas DataFrame
    high_col: the name of the HIGH values column
    low_col: the name of the LOW values column
    close_col: the name of the CLOSE values column
    
Returns:
    copy of 'data' DataFrame with 'williams_ad' column added

What is the right way to use this

williams_ad()

I tried several ways. But unable to debug.

import pandas as pd
import yfinance as yF
import datetime
df = yF.download(tickers = "SPY",  # list of tickers
            period = "5y",         # time period
            interval = "1d",       # trading interval
            prepost = False,       # download pre/post market hours data?
            repair = True)         # repair obvious price errors e.g. 100x?

Now I tried to pass df as an argument in place of data.

williams_ad(df)

I get a type error:

TypeError: '>' not supported between instances of 'Timestamp' and 'int'

The default index is Date Timestamp in my pandas data frame. In the first if condition, it is checking if index > 0. This is returning an error. How to overcome this issue?

Comment request dtypes:

Open           float64
High           float64
Low            float64
Close          float64
Adj Close      float64
Volume           int64
williams_ad    float64

Solution

  • The code below works well.

    import pandas as pd
    import yfinance as yF
    import datetime
    
    
    df1 = yF.download(tickers = "SPY",  # list of tickers
                period = "5y",         # time period
                interval = "1d",       # trading interval
                prepost = False,       # download pre/post market hours data?
                repair = True)         # repair obvious price errors e.g. 100x?
    
    df1['Close_Yesterday'] = df1['Close'].shift(1)
    df1['min_Lt_Ct-1'] = df1[['Low','Close_Yesterday']].min(axis=1)
    df1['max_Ht_Ct-1'] = df1[['High','Close_Yesterday']].min(axis=1)
    
    
    df1['X_Today_PRICE_INCREASING'] = df1['Close'] - df1['min_Lt_Ct-1']
    df1['X_Today_PRICE_DECREASING'] = df1['Close'] - df1['max_Ht_Ct-1']
    
    df1["X Today"] = df1.apply(lambda x: x.X_Today_PRICE_DECREASING if (x.X_Today_PRICE_DECREASING < 0) else x.X_Today_PRICE_INCREASING, axis = 1)
    
    
    df1['ADWM'] = df1['X Today'].cumsum()
    
    df1.head()
    

    It is implemented according to the formula of Williams Accumulation and Distribution.