How to get the same rsi calculation as Trading view in python

Viewed 74

So I have been trying to replicate the rsi values of tradingview by hard coding it myself as a little project, but to no avail. What I am trying to do is a little different from the usual replicating of values as I am not operating on equivalent timeframes. I am trying to replicate the values of the rsi (which is on a smaller timeframe) over the chart (which is on a bigger time frame).

Here you will find my code:

def kline_subtraction(kline, i, period_path):

if kline == "low":
    low = get_low(period_path,i)
    low_a = get_low(period_path,i + 1)
    p_diff = get_procental_diff(low, low_a)  # low - low_a
    return p_diff
else:
    high = get_high(period_path, i)
    high_a = get_high(period_path, i + 1)
    p_diff = get_procental_diff(high, high_a)  # high - high_a
    return p_diff


def average_upward_downward_movement(m, period_, n, direction, kline, period_path):

curr_up_mov = 0
curr_down_mov = 0

p_diff_low = kline_subtraction("low", m, period_path)
p_diff_high = kline_subtraction("high", m, period_path)

p_diff_green = []
p_diff_red = []
i = 8
j = 0
counter = 0
if n == 1:
    while counter < period_:
        p_diff = kline_subtraction(kline, i, period_path)
        if p_diff > 0:
            p_diff_green.append(abs(p_diff))
        else:
            p_diff_red.append(abs(p_diff))

        counter += 1
        i += 8
    pre_avg_up = sum(p_diff_green) / period_
    pre_avg_down = sum(p_diff_red) / period_
    if direction == "up":
        return pre_avg_up
    else:
        return pre_avg_down

if direction == "up":
    if p_diff_low > 0:
        curr_up_mov = p_diff_low
    else:
        curr_down_mov = abs(p_diff_low)
    curr_mov = p_diff_low
    avg_ = (curr_up_mov + ((period_ - 1) * average_upward_downward_movement(m+1, period_, n - 1, direction, kline, period_path))) / period_
    return avg_
else:
    if p_diff_high > 0:
        curr_up_mov = p_diff_high
    else:
        curr_down_mov = abs(p_diff_high)
    curr_mov = p_diff_high
    avg_ = (curr_down_mov + ((period_ - 1) * average_upward_downward_movement(m + 1, period_, n - 1, direction,
                                                                            kline, period_path))) / period_
    return avg_


def rsi_calculation(m, period_, period_path):

global l_a
global b
global s

i = 0
j = 1
p_diff_green = []
p_diff_red = []
curr_up_mov = 0
curr_down_mov = 0

if l_a == "buy":
    avg_up = average_upward_downward_movement(m, period_, period_, "up", "low", period_path)
    avg_down = average_upward_downward_movement(m, period_, period_, "down", "low", period_path)
    rs = avg_up/avg_down
    rsi = 100 - (100 / (1 + rs))
    return rsi
else:
    avg_up = average_upward_downward_movement(m, period_, period_, "up", "high", period_path)
    avg_down = average_upward_downward_movement(m, period_, period_, "down", "high", period_path)
    rs = avg_up / avg_down
    rsi = 100 - (100 / (1 + rs))
    return rsi

"m" stands for the index of the klines I am using as base data. "third_period_path" refers to klines (datapoints) saved in a .txt file of a specific timeframe.

This is an example of what I am trying to achieve: 2022-03-22 11:00:00 RSI: 72.03

This what my result looks like: 2022-03-22 11:00:00 RSI: 65.46

I wouldn't mind if the values were a little "off" but they are not even in the same sequence (as in the previous rsi is higher or lower than the current). I have already succesfully replicated other indicators (MACD, Bollinger Bands etc.) and while their values were a little off, they were correct enough to work with.

Any help or a pointer in the right direction would be appreciated as I cannot see where I am messing up the code.

1 Answers

Please try the below formula, the key difference is using exponential average instead of simple average when you are calculating relative strength.

import numpy as np

def RSI(dataset, n):  
    delta = dataset.diff().dropna()
    u = delta * 0
    d = u.copy()
    u[delta > 0] = delta[delta > 0]
    d[delta < 0] = -delta[delta < 0]
    u[u.index[n-1]] = np.mean( u[:n] ) #first value is sum of avg gains
    u = u.drop(u.index[:(n-1)])
    d[d.index[n-1]] = np.mean( d[:n] ) #first value is sum of avg losses
    d = d.drop(d.index[:(n-1)])
    rs = u.ewm(n,min_periods=0,adjust=False,ignore_na=False).mean() / \
    d.ewm(n,min_periods=0,adjust=False,ignore_na=False).mean()
    rsi = 100 - 100 / (1 + rs)
    rsi = pd.DataFrame(rsi)
    rsi.rename(columns={'close':'rsi_'+str(n)}, inplace = True)
    return rsi
Related