Skip to content

Instantly share code, notes, and snippets.

@sangelxyz
Created December 18, 2024 17:30
Show Gist options
  • Save sangelxyz/4e556af04ff03fc8d643adec3236a89b to your computer and use it in GitHub Desktop.
Save sangelxyz/4e556af04ff03fc8d643adec3236a89b to your computer and use it in GitHub Desktop.
Tradingview RSI, RMA in rust
// This is messy, still needs work. it will calculate the correct value with over 100points.
// lower v
///! Converted from the offical examples from.
/// https://www.tradingview.com/pine-script-reference/v6/
#[derive(Debug, Clone)]
struct Series {
closes: Vec<f64>,
period: f64,
series_sum: Vec<f64>,
alpha: f64,
sma: Vec<f64>,
}
impl Series {
fn new(closes: Vec<f64>, period: usize) -> Self {
let period = period as f64;
Series {
closes,
period,
series_sum: Vec::new(),
sma: Vec::new(),
alpha: 1_f64 / period,
}
}
/// Returns the last value of series_sum or 0.0 if it's empty
// fn previous_sum(&self) -> f64 {
// *self.series_sum.last().unwrap_or(&0.0)
// }
// pine_rma(src, length) =>
// alpha = 1/length
// sum = 0.0
// sum := na(sum[1]) ? ta.sma(src, length) : alpha * src + (1 - alpha) * nz(sum[1])
fn pine_rma(&self, source: &Vec<f64>) -> f64 {
let mut sum = 0.0;
for (index, &src) in source.iter().enumerate() {
// On the first iteration, use a simple moving average (SMA)
let prev_sum = if index == 0 { 0.0 } else { sum }; // or use self.previous_sum() if you have that method
let sumd = if prev_sum == 0.0 {
self.clone().pine_sma(&source) // assuming self.pine_sma() is correct
} else {
self.alpha * src + (1_f64 - self.alpha) * prev_sum
};
sum = sumd; // Update sum for the next iteration
}
sum
}
///! pine_rsi(x, y) =>
// u = math.max(x - x[1], 0) // upward ta.change
// d = math.max(x[1] - x, 0) // downward ta.change
// rs = ta.rma(u, y) / ta.rma(d, y)
// res = 100 - 100 / (1 + rs)
// res
pub fn pine_rsi(&self) -> f64 {
let mut prev = 0.0;
let mut u = Vec::new();
let mut d = Vec::new();
// Calculate upward and downward changes
for &c in &self.closes {
let up = f64::max(c - prev, 0.0);
let down = f64::max(prev - c, 0.0);
u.push(up);
d.push(down);
prev = c; // Update the previous close value
}
// Calculate RMA for upward and downward changes
let rma_u = self.pine_rma(&u);
let rma_d = self.pine_rma(&d);
// Calculate RSI
let rs = if rma_d == 0.0 { 0.0 } else { rma_u / rma_d };
let rsi = 100.0 - 100.0 / (1.0 + rs);
rsi
}
// fn pine_rsi(self) -> f64 {
// let prev = None;
// let u: Vec<f64> = self.closes.clone().iter().map(|c| {
// let prev = if let Some(p) = prev { p } else { 0.0 };
// f64::max(c - prev, 0_f64)
// }).collect();
// let prev = None;
// let d: Vec<f64> = self.closes.clone().iter().map(|c| {
// let prev = if let Some(p) = prev { p } else { 0.0 };
// f64::max(prev - c, 0_f64)
// }).collect();
// let rs = self.clone().pine_rma(&u) / self.clone().pine_rma(&d);
// println!("ssss{}", self.clone().pine_rma(&u));
// let res = 100_f64 - 100_f64 / (1_f64 + rs);
// res
// }
// fn pine_rma2(&mut self, close: f64) {
// // Access the last value of series_sum without calling another method
// let prev_sum = 0.0;
// // Calculate the RMA using the previous value and the current close
// let sum = if *prev_sum == 0.0 { self.pine_sma() } else { self.alpha * close + (1_f64 - self.alpha) * prev_sum };
// // Push the new sum into the series_sum vector
// self.series_sum.push(sum);
// }
// close[i] works diffrently, it goes back
fn get_close(self, back_period: usize) -> f64 {
let len = self.series_sum.len(); // TODO: this should be an index of somekind, needs to be updated.
if back_period > len { return 0_f64 }
let close = *self.closes.get(len-back_period).unwrap_or(&0_f64);
close
}
///! Converted from example
// pine_sma(close, period) =>
// sum = 0.0
// for i = 0 to period - 1
// sum := sum + close[i] / period
// fn pine_sma(&mut self, src: &Vec<f64>) -> f64 {
// let mut sum = 0.0;
// let last_14: Vec<f64> = src.iter().rev().take(self.period as usize).cloned().collect();
// let sma = last_14.iter().sum::<f64>() / self.period;
// sma
// }
fn pine_sma(&mut self, src: &Vec<f64>) -> f64 {
let mut sum = 0.0;
let period = self.period as usize;
let len = src.len();
if len < period {
return 0.0; // Or handle cases where `src` has fewer than `period` elements
}
for i in 0..period {
// Use reverse indexing to access the last `period` elements
sum += src[len - 1 - i] / self.period;
}
sum
}
// fn series_rma(&mut self) {
// let closes = self.closes.clone(); // Clone the vector to avoid borrowing `self`
// for close in closes {
// self.pine_rma(close);
// println!("{:?}", self.pine_sma());
// }
// }
}
// Get RMA for all of series.
// rsi takes closes.
// u & d are seperate series, they hold rma data from a calculation.
//
// fn pine_rsi(series: &mut Series) {
// let closes = [1.2, 2.3, 3.2, 2.3, 3.2, 2.3, 3.2, 2.3, 3.2, 2.3, 3.2, 2.3, 3.2, 2.3, 3.2, 2.3, 3.2, 2.3, 1.1, 3.2, 2.3, 3.2].to_vec();
// // let mut series = Series::new(closes.clone(), 14);
// let series_index = series.series_sum.len();
// let current_close = series.closes.get(series_index).unwrap_or(&0.0);
// let prev_close = series.closes.get(series_index-1).unwrap_or(&0.0);
// //
// Series::new(,14)
// let u = f64::max(current_close - prev_close, 0_f64); //Upward ta max of current_close - previous_close and 0
// let d = f64::max(prev_close - current_close, 0_f64); // Downward ta max of previous close - current_close and 0
// let res = self.rma(u)
// }
fn main() {
let closes = [261.16, 260.05, 260.53, 259.67, 263.62, 262.99, 258.87, 251.12, 253.92, 254.85, 242.68, 220.11, 211.99, 212.08, 216.52, 212.42, 205.76, 207.3, 197.36, 200.84, 205.66, 218.51, 219.96, 219.27, 222.18, 222.11, 209.98, 214.65, 223.71, 237.41, 242.84, 233.59, 234.3, 235.6, 241.2, 234.21, 235.45, 236.08, 246.72, 244.14, 240.08, 238.83, 235.58, 238.72, 239.37, 242.64, 243.84, 239.74, 237.01, 239.29, 251.05, 253.5, 252.08, 257.22, 247.14, 254.5, 252.54, 256.61, 261.44, 253.18, 248.48, 248.42, 238.45, 237.93, 237.49, 240.45, 234.96, 233.94, 227.22, 218.89, 219.91, 215.55, 211.88, 212.19, 208.8, 209.14, 207.83, 182.63, 183.25, 190.93, 191.59, 187.29, 188.86, 187.91, 181.06, 185.1, 187.58, 189.56, 193.57, 188.13, 184.02, 188.71, 200.45, 199.95, 193.76, 194.77, 197.41, 191.97, 199.4, 199.73, 202.04, 201.88, 202.64, 188.14, 180.74, 176.54, 178.65, 175.34, 177.77, 177.54, 169.48, 162.5, 163.57, 173.8, 171.32, 175.66, 172.82, 170.83, 172.63, 177.67, 179.83, 175.79, 175.22, 166.63, 168.38, 171.11, 164.9, 172.98, 176.88, 171.76, 174.6, 171.05, 161.48, 157.11, 155.45, 149.93, 147.05, 142.05, 144.68, 162.13, 170.18, 168.29, 194.05, 183.28, 179.99, 180.01, 181.19, 184.76, 177.81, 174.72, 171.97, 168.47, 171.89, 177.55, 173.99, 174.84, 177.46, 174.95, 186.6, 180.11, 173.74, 179.24, 176.75, 176.19, 178.79, 178.08, 176.29, 174.77, 175.0, 177.94, 177.48, 173.79, 170.66, 177.29, 182.47, 178.01, 187.44, 184.86, 181.57, 183.01, 182.58, 187.35, 196.37, 197.42, 197.88, 209.86, 231.26, 246.39, 251.52, 252.94, 262.33, 263.26, 241.03, 248.23, 252.64, 256.56, 248.5, 249.23, 239.2, 251.51, 246.38, 215.99, 220.25, 219.8, 232.1, 222.62, 232.07, 216.86, 207.67, 198.88, 200.64, 191.76, 198.84, 200.0, 197.49, 207.83, 201.38, 214.14, 216.12, 222.72, 221.1, 223.27, 210.66, 220.32, 213.21, 209.21, 205.75, 206.28, 214.11, 210.6, 219.41, 230.17, 210.73, 216.27, 226.17, 228.13, 229.81, 230.29, 226.78, 227.87, 227.2, 243.92, 238.25, 250.0, 254.27, 257.02, 254.22, 260.46, 261.63, 258.02, 249.02, 240.66, 250.08, 240.83, 244.5, 241.05, 238.77, 217.8, 219.16, 219.57, 221.33, 220.89, 220.7, 218.85, 217.97, 213.65, 260.48, 269.19, 262.51, 259.52, 257.55, 249.85, 248.98, 242.84, 251.44, 288.53, 296.91, 321.22, 350.0, 328.49, 330.24, 311.18, 320.72, 338.74, 346.0, 342.03, 339.64, 352.56, 338.59, 338.23, 332.89, 345.16, 357.09, 351.42, 357.93, 369.49, 389.22, 389.79].to_vec();
//for i in 0..closes.len() {
let mut series = Series::new(closes.clone()[closes.len()-130..closes.len()].to_vec(), 14);
println!("{:?}", series.pine_rsi())
//}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment