4

I have got a df with value from forex market and I'm trying to put into the data frame the RSI, relative strength index(10), for each row in the df.

df.head()
Out[3]: 
        Date      Time     Open     High      Low    Close  Volume  OpenInt
0 2016-09-16  00:05:00  0.75183  0.75186  0.75160  0.75161       0        0
1 2016-09-16  00:10:00  0.75156  0.75156  0.75145  0.75149       0        0
2 2016-09-16  00:15:00  0.75156  0.75166  0.75152  0.75165       0        0
3 2016-09-16  00:20:00  0.75164  0.75165  0.75150  0.75156       0        0
4 2016-09-16  00:25:00  0.75156  0.75174  0.75153  0.75156       0        0

RSI is an indicator that tells you when the product is oversold or overbought; RSI = 100 - 100 / (1 + RS) where RS is the average gain of up periods in a given time frame / the average of loss of down period in a given time frame. In my case, time frame is 10.

df.change = df.Open - df.Close # find out if there is a gain or a loss

df.gain = df.change [df.change > 0] #column of gain

df.loss = df.change [df.change < 0]# column of loss

df.again = df.gain.rolling(center=False,window=10) #find the average gain in the last 10 periods 

df.aloss = df.loss.rolling(center=False,window=10) #find the average loss in the last 10 periods

Now is where the troubles begin; I need to get the RS:

df.rs = df.again/df.aloss

TypeErrorTraceback (most recent call last)
<ipython-input-13-2886bcd78f42> in <module>()
----> 1 df.rs = df.again/df.aloss

TypeError: unsupported operand type(s) for /: 'Rolling' and 'Rolling'

EDIT

df.gain.head(6)
Out[31]: 
0    0.00022
1    0.00007
3    0.00008
5    0.00002
7    0.00003
8    0.00002

df.loss.head(6)
Out[32]: 
2    -0.00009
6    -0.00019
9    -0.00013
14   -0.00002
15   -0.00011
20   -0.00008
dtype: float64
Asclepius
  • 57,944
  • 17
  • 167
  • 143
CronosVirus00
  • 129
  • 1
  • 1
  • 12
  • The rolling method returns a rolling object. You need to call a rolling-object method to return a series/dataframe: http://pandas.pydata.org/pandas-docs/stable/api.html#window – IanS Sep 26 '16 at 12:01
  • Rightly said. I think the rolling object is just getting initialized. You need to call the `.mean` method on it to compute the averages over a 10 period window. – Nickil Maveli Sep 26 '16 at 12:08
  • Hi both, as suggested i dit: df.aloss = pd.expanding_mean(df.loss,10) df.again = pd.expanding_mean(df.gain,10). However, when I go for df.rs=df.again/df.aloss as result I got a list of NaN... I think the problem is that df.again and df.aloss do not have the same number of index. I'll post both in the question – CronosVirus00 Sep 26 '16 at 12:11
  • 1
    @CronosVirus00, So you want to align both the indices to the default integer index to perform the division?`df['again'].reset_index(drop=True)/df['aloss'].reset_index(drop=True)` – Nickil Maveli Sep 26 '16 at 12:36
  • @NickilMaveli df['again'].reset_index(drop=True)/df['aloss'].rese‌​t_index(drop=True) File "", line 1 df['again'].reset_index(drop=True)/df['aloss'].rese‌​t_index(drop=True) I got this error and yes, you are right, I'm trying to align both indices – CronosVirus00 Sep 26 '16 at 13:23
  • @CronosVirus00, Could you edit the post with the full traceback of the error you've got? – Nickil Maveli Sep 26 '16 at 14:03

2 Answers2

4

This is the SMA based approach, not an EMA based approach.

delta = df.Close.diff()
window = 15
up_days = delta.copy()
up_days[delta<=0]=0.0
down_days = abs(delta.copy())
down_days[delta>0]=0.0
RS_up = up_days.rolling(window).mean()
RS_down = down_days.rolling(window).mean()
rsi= 100-100/(1+RS_up/RS_down)
Asclepius
  • 57,944
  • 17
  • 167
  • 143
DanGoodrick
  • 2,818
  • 6
  • 28
  • 52
4

For average gain or loss, opening price doesn't matter. It have to calculate always with closing price compared to previous candle stick's closing price.

def rsiFunc(prices, n=14):
deltas = np.diff(prices)
seed = deltas[:n+1]
up = seed[seed>=0].sum()/n
down = -seed[seed<0].sum()/n
rs = up/down
rsi = np.zeros_like(prices)
rsi[:n] = 100. - 100./(1.+rs)

for i in range(n, len(prices)):
    delta = deltas[i-1] # cause the diff is 1 shorter

    if delta>0:
        upval = delta
        downval = 0.
    else:
        upval = 0.
        downval = -delta

    up = (up*(n-1) + upval)/n
    down = (down*(n-1) + downval)/n

    rs = up/down
    rsi[i] = 100. - 100./(1.+rs)

return rsi

I took it from https://github.com/mtamer/python-rsi/blob/master/Stock%20Screener/rsi.py