0

I am getting the following error:

Traceback (most recent call last):
  File "tests.py", line 101, in <module>
    test()
  File "tests.py", line 95, in test
    print(connorsRSI(df))
  File "/Users/WorkFLOW/app.py", line 14, in connorsRSI
    if data.loc[index, 'Diff'] > 0:
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pandas/core/generic.py", line 1478, in __nonzero__
    .format(self.__class__.__name__))
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

On this line if data.loc[index, 'Diff'] > 0:

And don't know how to fix it.

Anybody knows any other way to rewrite it?

I know there are other questions like this one but none has helped me solve this error.

-- UPDATE: df.head() ==>

                 High        Low       Open      Close   Volume  Adj Close
Date                                                                      
2019-11-04  98.529999  95.599998  96.349998  98.150002  3841000  98.150002
2019-11-05  98.989998  96.629997  98.129997  98.260002  2719900  98.260002
2019-11-06  99.180000  97.970001  98.680000  98.669998  2447900  98.669998
2019-11-07  99.290001  97.019997  99.290001  97.230003  2156400  97.230003
2019-11-08  98.500000  96.320000  96.910004  98.269997  2306600  98.269997

Full code here:

import pandas_datareader.data as web

def connorsRSI(df):
    data = df.copy()
    data = data[['Close']]  
    data['Close'] = round(data['Close'], 2) 
    data['Diff'] = data['Close'].diff()
    data['UpDown'] = 0

    for i, index in enumerate(data.index[1:]):
        if data.loc[index, 'Diff'] > 0:
            if data.loc[data.index[i], 'Diff'] > 0:
                data.loc[index, 'UpDown'] = data.loc[data.index[i], 'UpDown'] + 1
            else:
                data.loc[index, 'UpDown'] = 1
        else:
            if data.loc[data.index[i], 'Diff'] > 0:
                data.loc[index, 'UpDown'] = -1
            else:
                data.loc[index, 'UpDown'] = data.loc[data.index[i], 'UpDown'] - 1

    xpct = data['Diff'][-1]
    data2 = data.copy()
    data2=data2[-100:]
    counter = data2[data2['Diff'] < xpct].count()['Diff']
    percentrank = round((counter/(len(data2)))*100,2)
    rsi = round(talib.RSI(data['Close'], timeperiod=3)[-1],2)
    streak = round(talib.RSI(data['UpDown'], timeperiod=2)[-1],2)
    crsi = round((rsi+streak+percentrank)/3,2)

    return crsi

def test():
    df = web.DataReader('EA', 'yahoo', start, end)
    print(connorsRSI(df))
test()
edd
  • 301
  • 3
  • 9
  • 1
    Based on your code, there's a high chance that you actually don't need to loop at all, but its impossible to say without a sample df. Have you thought of giving that a try? Also if you absolutely have to loop you read this [thread](https://stackoverflow.com/questions/16476924/how-to-iterate-over-rows-in-a-dataframe-in-pandas) about how to loop over rows. – Ben Pap Feb 11 '20 at 23:45
  • 1
    Can you do a df.head() and show us what the dataframe contains ? You can just show 3-4 columns that you are using for ease. – Spandan Brahmbhatt Feb 11 '20 at 23:50
  • @BenPap I just added df.head() , I'm interested in optimizing the code, is there a way to do this without looping? – edd Feb 12 '20 at 00:05
  • @SpandanBrahmbhatt just added the df.head() to the question – edd Feb 12 '20 at 00:05
  • 1
    Does this answer your question? [Truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all()](https://stackoverflow.com/questions/36921951/truth-value-of-a-series-is-ambiguous-use-a-empty-a-bool-a-item-a-any-o) – AMC Feb 12 '20 at 02:18
  • 1
    Please share the entire error message. – AMC Feb 12 '20 at 02:19
  • 1
    _I'm interested in optimizing the code, is there a way to do this without looping?_ There probably is, yes. You need to rethink the entire function. – AMC Feb 12 '20 at 02:20
  • @AMC I just shared the entire error, and no that didn't answer the question I already had looked into that – edd Feb 12 '20 at 11:07
  • 1
    Please confirm, all you are tyring to do in the loop is make `updown` 1 if `diff` is positive and -1 if `diff ` is negative? As you set every value to `updown` to 0 initially – Ben Pap Feb 12 '20 at 23:19
  • @BenPap that is correct, but **ALSO** it will add `+1` or substract `-1` if `updown` is positive or negative respectively... i.e... if there are two positive diffs in a row, then updown would be 2.... updown basically counts the streak of positive or negative diffs, if current updown is 5 and next diff is negative, then streak resets and starts at -1, here's a screenshot I took [link](http://prntscr.com/r1wjmd) `diff` is the difference between `closing prices` and `updown` would be the `Streak Duration` – edd Feb 13 '20 at 17:18

1 Answers1

1
data['UpDown'] = (data['Diff'] > 0)
data['UpDown'] = data.groupby((df1['UpDown'] != data['UpDown'].shift()).cumsum()).cumcount() +1
data.loc[data['Diff'] < 0, 'UpDown'] *= -1

These three lines replace your loop. The first makes a bool to check whether diff is positive or negative. The second line counts consecutive increases or decreases, and finally the third makes consecutive decreases negative.

Ben Pap
  • 2,549
  • 1
  • 8
  • 17