Reputation: 928
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:
for loop
? I don't see it in there functions. If they don't, how do they calculate the average for a period of longer than 2? You have to loop for that right?rma
function work? This is their docs.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
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