我尝试使用 Rust 和 Mexc API 从 TradingView 复制 RSI 指标值,但显示的值不正确。你能帮我找出我做错了什么吗?
async fn get_symbol_rsi(client: Client, symbol: &str) -> AppResult<f64> {
let rsi_len = 14;
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().take(15);
let mut gain = Vec::new();
let mut loss = Vec::new();
let mut prev_close = closes.next().unwrap();
for close in closes {
let diff = close - prev_close;
if diff > 0.0 {
gain.push(diff);
loss.push(0.0);
} else {
gain.push(0.0);
loss.push(diff.abs());
}
prev_close = close;
}
let avg_up = gain.iter().sum::<f64>() / rsi_len as f64;
let avg_down = loss.iter().sum::<f64>() / rsi_len as f64;
let rs = avg_up / avg_down;
let rsi = 100.0 - (100.0 / (1.0 + rs));
Ok(rsi)
}
感谢您的帮助。
与我所看到的主要区别在于,您对
avg_up
和 avg_down
变量使用简单移动平均线。
TradingView 使用修改后的指数移动平均线,称为“相对移动平均线 (RMA)”,用于这些变量的“相对强弱指数 (RSI)”。 差异在于 alpha 变量: EMA 有
alpha = 2 / (length + 1)
RMA 有
alpha = 1 / length
下面是 Rust 中的 RMA 函数:
fn rma(price_ndarray: &Array1<f32>, period: usize) -> Array1<f32>{
let length = price_ndarray.len() - period +1;
let mut result = Array1::<f32>::zeros(length);
result[0] = price_ndarray.slice(s![0..period]).sum();
for i in 1..length{
result[i] = result[i-1]+(price_ndarray[i+period-1]-result[i-1])*(1.0/(period as f32));
}
result
}