I'm trying to make the exact rsi formula TradingView uses but in Java.
Not looking for a spoonfed answer, but a point in the right direction would be much appreciated!
Here's what I have, but the results do not line up: (periods.length=15, smoothing=true)
(When smoothing=false, data is accurate. Need to fix when smoothing=true)
Also, my periods are essentially just candles which line up 100% accurately with the data I'm comparing on TradeView.
public static double calculate(HistoricalTrade.Period[] periods, boolean smoothing) {
double trueLen = periods.length - 1; //-1 because we always need to include an extra period to get the prev close for our first true period!
//So if our rsi length is 14 we'll use this method with 15 periods and our trueLen = 14
double averageGain = 0, averageLoss = 0;
if(smoothing) { //"Exponential Moving Average" where a = 1 / N
for(int i = 1; i < periods.length; i++) {
HistoricalTrade.Period period = periods[i];
HistoricalTrade.Period prevPeriod = periods[i - 1];
double close = period.getClose().price;
double prevClose = prevPeriod.getClose().price;
double change = close - prevClose;
//change = (change / prevClose) * 100D; //as percent
double gain = Math.max(change, 0);
double loss = -Math.min(change, 0);
double alpha = 1D / trueLen;
averageGain = alpha * gain + (1D - alpha) * averageGain;
averageLoss = alpha * loss + (1D - alpha) * averageLoss;
}
} else { //"Simple Moving Average" (This block works as it should)
double gains = 0, losses = 0;
for(int i = 1; i < periods.length; i++) {
HistoricalTrade.Period period = periods[i];
HistoricalTrade.Period prevPeriod = periods[i - 1];
double close = period.getClose().price;
double prevClose = prevPeriod.getClose().price;
double change = close - prevClose;
//change = (change / prevClose) * 100D; //as percent
double gain = Math.max(change, 0);
double loss = -Math.min(change, 0);
gains += gain;
losses += loss;
}
averageGain = gains / trueLen;
averageLoss = losses / trueLen;
}
double rs = averageGain / averageLoss;
return 100D - (100D / (1D + rs));
}
TradingView Formula:
https://www.tradingview.com/support/solutions/43000502338-relative-strength-index-rsi/
RSI = 100 – 100/ (1 + RS)
RS = Average Gain of n days UP / Average Loss of n days DOWN
For a practical example, the built-in Pine Script function rsi(), could be replicated in long form as follows.
change = change(close)
gain = change >= 0 ? change : 0.0
loss = change < 0 ? (-1) * change : 0.0
avgGain = rma(gain, 14)
avgLoss = rma(loss, 14)
rs = avgGain / avgLoss
rsi = 100 - (100 / (1 + rs))
"rsi", above, is exactly equal to rsi(close, 14).
pine_rma(src, length) =>
alpha = 1/length
sum = 0.0
sum := na(sum[1]) ? sma(src, length) : alpha * src + (1 - alpha) * nz(sum[1])
Expected Results: (TradingView ETHUSD Candle 07/03/21 - 07:15 UTC)
"open": 2143.6,
"high": 2147.7,
"low": 2141.66,
"close": 2145.04,
"change": "+1.69 (+0.08%)",
"rsi": 51.73 <-- This is what we want!
Our Results:
"open": 2143.6,
"high": 2147.7,
"low": 2141.66,
"close": 2145.04,
"change": "+1.69 (+0.08%)",
"rsi": 45.92 (smoothing=true)
"rsi": 44.97 (smoothing=false)
And lastly, here's another formula I found useful: