Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Relative Strength Index in python pandas

I am new to pandas. What is the best way to calculate the relative strength part in the RSI indicator in pandas? So far I got the following:

from pylab import * import pandas as pd import numpy as np    def Datapull(Stock):     try:         df = (pd.io.data.DataReader(Stock,'yahoo',start='01/01/2010'))         return df         print 'Retrieved', Stock         time.sleep(5)     except Exception, e:         print 'Main Loop', str(e)   def RSIfun(price, n=14):     delta = price['Close'].diff()     #-----------     dUp=     dDown=      RolUp=pd.rolling_mean(dUp, n)     RolDown=pd.rolling_mean(dDown, n).abs()      RS = RolUp / RolDown     rsi= 100.0 - (100.0 / (1.0 + RS))     return rsi  Stock='AAPL' df=Datapull(Stock) RSIfun(df) 

Am I doing it correctly so far? I am having trouble with the difference part of the equation where you separate out upward and downward calculations

like image 802
user3084006 Avatar asked Dec 11 '13 17:12

user3084006


People also ask

How do you calculate RSI from a data frame?

First Average Loss = Sum of Losses over the past 14 periods / 14 The second, and subsequent, calculations are based on the prior averages and the current gain loss: Average Gain = [(previous Average Gain) x 13 + current Gain] / 14. Average Loss = [(previous Average Loss) x 13 + current Loss] / 14.

How do you find relative strength index?

The relative strength index (RSI) is a popular momentum oscillator developed in 1978. The RSI provides technical traders with signals about bullish and bearish price momentum, and it is often plotted beneath the graph of an asset's price.

What does the relative strength index show?

The Relative Strength Index (RSI), developed by J. Welles Wilder, is a momentum oscillator that measures the speed and change of price movements. The RSI oscillates between zero and 100. Traditionally the RSI is considered overbought when above 70 and oversold when below 30.


1 Answers

It is important to note that there are various ways of defining the RSI. It is commonly defined in at least two ways: using a simple moving average (SMA) as above, or using an exponential moving average (EMA). Here's a code snippet that calculates various definitions of RSI and plots them for comparison. I'm discarding the first row after taking the difference, since it is always NaN by definition.

Note that when using EMA one has to be careful: since it includes a memory going back to the beginning of the data, the result depends on where you start! For this reason, typically people will add some data at the beginning, say 100 time steps, and then cut off the first 100 RSI values.

In the plot below, one can see the difference between the RSI calculated using SMA and EMA: the SMA one tends to be more sensitive. Note that the RSI based on EMA has its first finite value at the first time step (which is the second time step of the original period, due to discarding the first row), whereas the RSI based on SMA has its first finite value at the 14th time step. This is because by default rolling_mean() only returns a finite value once there are enough values to fill the window.

A comparison of the RSI calculated using exponential or simple moving average

import datetime from typing import Callable  import matplotlib.pyplot as plt import numpy as np import pandas as pd import pandas_datareader.data as web  # Window length for moving average length = 14  # Dates start, end = '2010-01-01', '2013-01-27'  # Get data data = web.DataReader('AAPL', 'yahoo', start, end) # Get just the adjusted close close = data['Adj Close']  # Define function to calculate the RSI def calc_rsi(over: pd.Series, fn_roll: Callable) -> pd.Series:     # Get the difference in price from previous step     delta = over.diff()     # Get rid of the first row, which is NaN since it did not have a previous row to calculate the differences     delta = delta[1:]       # Make the positive gains (up) and negative gains (down) Series     up, down = delta.clip(lower=0), delta.clip(upper=0).abs()      roll_up, roll_down = fn_roll(up), fn_roll(down)     rs = roll_up / roll_down     rsi = 100.0 - (100.0 / (1.0 + rs))      # Avoid division-by-zero if `roll_down` is zero     # This prevents inf and/or nan values.     rsi[:] = np.select([roll_down == 0, roll_up == 0, True], [100, 0, rsi])     rsi.name = 'rsi'      # Assert range     valid_rsi = rsi[length - 1:]     assert ((0 <= valid_rsi) & (valid_rsi <= 100)).all()     # Note: rsi[:length - 1] is excluded from above assertion because it is NaN for SMA.      return rsi  # Calculate RSI using MA of choice # Reminder: Provide ≥ `1 + length` extra data points! rsi_ema = calc_rsi(close, lambda s: s.ewm(span=length).mean()) rsi_sma = calc_rsi(close, lambda s: s.rolling(length).mean()) rsi_rma = calc_rsi(close, lambda s: s.ewm(alpha=1 / length).mean())  # Approximates TradingView.  # Compare graphically plt.figure(figsize=(8, 6)) rsi_ema.plot(), rsi_sma.plot(), rsi_rma.plot() plt.legend(['RSI via EMA/EWMA', 'RSI via SMA', 'RSI via RMA/SMMA/MMA (TradingView)']) plt.show() 
like image 159
Moot Avatar answered Sep 19 '22 21:09

Moot