pythonstockrsi

Python - While trying to calculate RSI(Relative strength index - stock indicator) my results are "upside down" and shifted


I am trying to calculate RSI using simple functions. The general formula for it is:

RSI = 100/(1+RS), where RS = Exponential Moving Average of gains / -||- of losses.

Here is what I am getting: enter image description here

Here it is how should it look like: enter image description here

I have everything double checked or even triple checked, but I can't find any mistake. Thus I need your help, I know that the question is very simple though I need some help, I have no idea where I have made the mistake. The general idea of RSI is that it should be low where the price is "low" and high, where the price is high, and generally no matter what I try I have it upside down.

def EMA(close_price_arr, n):
    a = (2/n + 1)
    EMA_n = np.empty((1, len(close_price_arr)))

    for i in range(len(close_price_arr)):

        if i < n:
            # creating NaN values where it is impossible to calculate EMA to drop it later after connecting the whole database
            EMA_n[0, i] = 'NaN'
        if i >= n:
            # Calaculating nominator and denominator of EMA
            for j in range(n):
                nominator_ema += close_price_arr[i - j] * a**(j)
                denominator_ema += a**(j)

            EMA_n[0, i] = nominator_ema / denominator_ema
        nominator_ema = 0
        denominator_ema = 0
    return EMA_n

def gains(close_price_arr):
    gain_arr = np.empty((len(close_price_arr) - 1))
    for i in range(len(close_price_arr)):
        if i == 0:
            pass
        if i >= 1:
            if close_price_arr[i] > close_price_arr[i - 1]:
                gain_arr[i - 1] = (close_price_arr[i] - close_price_arr[i-1])
            else:
                gain_arr[i - 1] = 0
    return gain_arr

def losses(close_price_arr):
    loss_arr = np.empty((len(close_price_arr) - 1))
    for i in range(len(close_price_arr)):
        if i == 0:
            pass
        if i >= 1:
            if close_price_arr[i] < close_price_arr[i - 1]:
                loss_arr[i - 1] = abs(close_price_arr[i] - close_price_arr[i - 1])
            else:
                loss_arr[i - 1] = 0
    return loss_arr

def RSI(gain_arr, loss_arr, n):
    EMA_u = EMA(gain_arr, n)
    EMA_d = EMA(loss_arr, n)

    EMA_diff = EMA_u / EMA_d
    x,y = EMA_diff.shape
    print(x, y)



    RSI_n = np.empty((1, y))
    for i in range(y):
        if EMA_diff[0, i] == 'NaN':
            RSI_n[0, i] = 'NaN'
            print(i)
        else:
            RSI_n[0, i] = 100 / (1 + EMA_diff[0, i])
    return RSI_n


@contextmanager
def show_complete_array():
    oldoptions = np.get_printoptions()
    np.set_printoptions(threshold=np.inf)
    try:
        yield
    finally:
        np.set_printoptions(**oldoptions)

np.set_printoptions(linewidth=3000)

pd.set_option('display.max_columns', None)


# Specyfying root folder, file folder and file
FILE = 'TVC_SILVER, 5.csv'
FOLDER = 'src'
PROJECT_ROOT_DIR = '.'
csv_path = os.path.join(PROJECT_ROOT_DIR, FOLDER, FILE)

# reading csv
price_data = pd.read_csv(csv_path, delimiter=',')

price_data_copy = price_data.copy()

price_data_nodate = price_data.copy().drop('time', axis=1)

price_data_np = price_data_nodate.to_numpy(dtype='float32')

close_price = price_data_np[:, 3]

EMA15 = EMA(close_price_arr=close_price, n=15)
EMA55 = EMA(close_price_arr=close_price, n=55)

gain = gains(close_price_arr=close_price)
loss = losses(close_price_arr=close_price)

RSI14 = RSI(gain_arr=gain, loss_arr=loss, n=14)

Solution

  • Try this:

    """dataset is a dataframe"""
    
    def RSI(dataset, n=14):
        delta = dataset.diff()
        dUp, dDown = delta.copy(), delta.copy()
        dUp[dUp < 0] = 0
        dDown[dDown > 0] = 0
    
        RolUp = pd.Series(dUp).rolling(window=n).mean()
        RolDown = pd.Series(dDown).rolling(window=n).mean().abs()
        RS = RolUp / RolDown
        rsi= 100.0 - (100.0 / (1.0 + RS))
        return rsi