Allart
Allart

Reputation: 928

Calculate/replicate RSI from Tradingview's pine script

Im trying to recreate Tradingviews pine script RSI code into Javascript code. But having a hard time figuring out how it works. I made the basic RSI using a normal moving average calculation. But the pine script uses exponential weighted moving average. And there documentation is really hard to follow to me. This is the pine script.

//@version=4
study(title="Relative Strength Index", shorttitle="RSI", format=format.price, precision=2, resolution="")
len = input(14, minval=1, title="Length")
src = input(close, "Source", type = input.source)
up = rma(max(change(src), 0), len)
down = rma(-min(change(src), 0), len)
rsi = down == 0 ? 100 : up == 0 ? 0 : 100 - (100 / (1 + up / down))
plot(rsi, "RSI", color=#7E57C2)
band1 = hline(70, "Upper Band", color=#787B86)
bandm = hline(50, "Middle Band", color=color.new(#787B86, 50))
band0 = hline(30, "Lower Band", color=#787B86)
fill(band1, band0, color=color.rgb(126, 87, 194, 90), title="Background")

This is what I could make of it in Javascript:

// Period = 200
// Close variable is 200 closed values. Where [0] in array = oldest, [199] in array = newest value.

/**
 * Relative strength index. Based on closed periods.
 * 
 * @param {Array} close 
 * @param {Integer} period 
 * @returns 
 */
function calculateRSI(close, period) {

    // Only calculate if it is worth it. First {period - 1} amount of calculations aren't correct anyway.
    if (close.length < period) {
        return 50;
    }

    let averageGain = 0;
    let averageLoss = 0;
    const alpha = 1 / period;

    // Exponential weighted moving average.
    for (let i = 1; i < period; i++)
    {
        let change = close[i] - close[i - 1];

        if (change >= 0) {
            averageGain = alpha * change + (1 - alpha) * averageGain;
        } else {
            averageLoss = alpha * -change + (1 - alpha) * averageLoss;
        }
    }

    // Tried this too, but seems to not really matter.
    // To get an actual average.
    // averageGain /= period;
    // averageLoss /= period;

    // Calculate relative strength index. Where it can only be between 0 and 100.
    var rsi = 100 - (100 / (1 + (averageGain / averageLoss)));

    return rsi;
}

The results this function gives on my chart is not too bad, but it just isn't the same as I have it in Tradingview. I belive im missing something that the pine script does and I don't.

Things I dont understand of the pine script:

I might have too many questions on this, but I think if you show a somewhat working example in Javascript of the RSI calculation like they do. Then I can probably make sense of it.

Is my calculation in Javascript correct to the one in the pine script?

Upvotes: 2

Views: 5713

Answers (1)

Quant Freedom 1022
Quant Freedom 1022

Reputation: 19

in your change calculation you forgot to divide by close[i-1] ... and then you are not storing average gain and loss as an array

i tried to make my own function exactly how tradingview does and it still wont come out correctly

import numpy as np
candles = mufex_main.get_candles(symbol="BTCUSDT", timeframe='5m', candles_to_dl=200)

rsi_period = 14
closes = candles[:, 4]
close_shift = np.roll(candles[:, 4], 1)
close_shift[0] = np.nan
pchg = (closes-close_shift)/close_shift

alpha = 1/rsi_period
gain = np.where(pchg > 0, pchg, 0)
rma_up = np.zeros_like(gain)
avg_gain = np.full_like(gain, np.nan)

loss = np.where(pchg < 0, abs(pchg), 0)
rma_down = np.zeros_like(loss)
avg_loss = np.full_like(loss, np.nan)

for i in range(1, gain.size):
    rma_up[i] = alpha * gain[i] + (1 - alpha) * rma_up[i-1]
    rma_down[i] = alpha * loss[i] + (1 - alpha) * rma_down[i-1]

rma_up[:13] = 0
rma_down[:13] = 0

min_one = rsi_period - 1
for i in range(rsi_period-1, gain.size):
    avg_gain[i] = rma_up[i-rsi_period:i+1].mean()
    avg_loss[i] = rma_down[i-rsi_period:i+1].mean()

rs = avg_gain / avg_loss

print(100-(100/(1+rs)))

This even gives wrong answers which makes no sense because it is the same exact formula they are using

Upvotes: 0

Related Questions