0

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)
  • I didn't read your code but moving averages shift the data unless you center the window. Have you done that? – mozway Jul 25 '22 at 21:02
  • @mozway exponential moving averages aren't window based. – Mark Ransom Jul 25 '22 at 21:37
  • @MarkRansom true. I read too quickly and haven't seen this was **exponential**. That said, EWMA will also cause an apparent shift in the data. [Quick example (alpha=0.1)](https://i.stack.imgur.com/jK1CR.png) / [(alpha=0.5)](https://i.stack.imgur.com/9fF1K.png) a series with EWMA and EWMA on the reverse Series. One clearly sees the apparent shift, and the fact that the intensity of the shift depends on the weighting factor. – mozway Jul 26 '22 at 02:50

1 Answers1

0

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
razimbres
  • 4,715
  • 5
  • 23
  • 50