1

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:

https://www.macroption.com/rsi-calculation/

NotArchon
  • 125
  • 1
  • 6

0 Answers0