I am attempting to replicate the RSI indicator value from TradingView using Rust and the Mexc API, but the value displayed is incorrect. Can you help me identify what I am doing wrong?
async fn get_symbol_rsi(client: Client, symbol: &str) -> AppResult<f64> {
let candles: Klines = client
.get(format!(
"https://contract.mexc.com/api/v1/contract/kline/{symbol}?interval=Min15"
))
.send()
.await?
.json()
.await?;
let mut closes = candles
.data
.close
.into_iter()
.rev() // So it shows from new candles
.take(15) // take the last 15 new candles (1 more because of the first one?)
.rev(); // reverse it back to the original order older to newer
// Get the gains and losses percentages
let mut gains = Vec::new();
let mut losses = Vec::new();
let prev_close = closes.next().unwrap();
for close in closes {
let diff = close - prev_close;
if diff > 0.0 {
gains.push(diff);
losses.push(0.0);
} else {
gains.push(0.0);
losses.push(diff.abs());
}
}
// Calculate the RSI based on RMA
let alpha = 1.0 / 14.0;
let mut rma_gains = gains[0];
let mut rma_losses = losses[0];
for i in 1..14 {
rma_gains = alpha * gains[i] + (1.0 - alpha) * rma_gains;
rma_losses = alpha * losses[i] + (1.0 - alpha) * rma_losses;
}
let rs = rma_gains / rma_losses;
let rsi = 100.0 - (100.0 / (1.0 + rs));
Ok(rsi)
}
The main difference from what I see is that you are using a Simple Moving Average for the
avg_upandavg_downvariables.TradingView uses a modified Exponential Moving Average called Relative Moving Average (RMA) for use in their Relative Strength Index (RSI) for those variables.
The difference is in the alpha variable:
Where EMA has
alpha = 2 / (length + 1)RMA has
alpha = 1 / lengthBelow is a function for RMA in Rust: