All vec operation was replaced with HashMap. Increase outstanding performance. Co-authored-by: Sik Yoon <younxxxx@gmail.com> Reviewed-on: http://192.168.1.100:3000/Sik/tradingbot/pulls/3
154 lines
6.5 KiB
Rust
154 lines
6.5 KiB
Rust
#![allow(unused)]
|
|
#![allow(warnings)]
|
|
|
|
use crate::database_control::*;
|
|
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
|
use crate::strategy_team::FilteredDataValue;
|
|
use futures::future::try_join_all;
|
|
use serde::Deserialize;
|
|
use sqlx::FromRow;
|
|
use std::f64::NAN;
|
|
use std::sync::Arc;
|
|
use tokio::{fs::*, io::AsyncWriteExt, sync::Mutex, time::*};
|
|
use super::HashMap;
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct RsiData {
|
|
pub rsi_value: f64,
|
|
pub close_time: i64,
|
|
}
|
|
impl RsiData {
|
|
pub fn new() -> RsiData {
|
|
let a = RsiData {
|
|
rsi_value: 0.0,
|
|
close_time: 0,
|
|
};
|
|
a
|
|
}
|
|
}
|
|
|
|
// Binance RSI (EMA, Closeprice, Wilder's weight, 150 candles)
|
|
pub async fn rsi(
|
|
rsi_number: usize,
|
|
input_rt_data: &HashMap<String, Vec<RealtimePriceData>>,
|
|
filtered_symbols: &HashMap<String, FilteredDataValue>,
|
|
) -> Result<HashMap<String, Vec<RsiData>>, Box<dyn std::error::Error + Send + Sync>> {
|
|
let instant = Instant::now();
|
|
|
|
let mut rsi_data_wrapper: HashMap<String, Vec<RsiData>> = HashMap::new();
|
|
let mut rsi_data_wrapper_arc = Arc::new(Mutex::new(rsi_data_wrapper));
|
|
|
|
let mut task_vec = Vec::new();
|
|
for (symbol, filtered_data) in filtered_symbols {
|
|
if let Some(rt_price_vec) = input_rt_data.get(symbol) {
|
|
let rsi_data_wrapper_arc_c = Arc::clone(&rsi_data_wrapper_arc);
|
|
let symbol_c = symbol.clone();
|
|
let mut input_rt_data_c = rt_price_vec.clone();
|
|
task_vec.push(tokio::spawn(async move {
|
|
let mut rsi_data_vec: Vec<RsiData> = Vec::new();
|
|
let mut rsi_data = RsiData::new();
|
|
let mut read_data_vec: Vec<RealtimePriceData> = Vec::new();
|
|
let mut read_price_buffer: Vec<RealtimePriceData> = Vec::new();
|
|
let mut prev_price: f64 = 0.0;
|
|
let mut current_price: f64 = 0.0;
|
|
let mut sum_increase: f64 = 0.0;
|
|
let mut sum_decrease: f64 = 0.0;
|
|
let mut rsi: f64 = 0.0;
|
|
let mut last_close_time = 0;
|
|
|
|
if input_rt_data_c.len() < rsi_number + 1 {
|
|
rsi_data.rsi_value = 0.0;
|
|
rsi_data.close_time = 0;
|
|
rsi_data_vec.push(rsi_data.clone());
|
|
} else {
|
|
if input_rt_data_c.len() >= (150 + rsi_number) as usize {
|
|
input_rt_data_c.reverse();
|
|
input_rt_data_c.truncate((150 + rsi_number) as usize);
|
|
input_rt_data_c.reverse();
|
|
}
|
|
let window_iter = input_rt_data_c.windows(rsi_number + 1);
|
|
|
|
let mut prev_avg_ups: Option<f64> = None;
|
|
let mut prev_avg_downs: Option<f64> = None;
|
|
let mut current_avg_ups: Option<f64> = None;
|
|
let mut current_avg_downs: Option<f64> = None;
|
|
|
|
for buffer in window_iter {
|
|
let mut up_vec: Vec<f64> = Vec::new();
|
|
let mut down_vec: Vec<f64> = Vec::new();
|
|
|
|
let buffer_window = buffer.windows(2);
|
|
for element in buffer_window {
|
|
if element.last().unwrap().close_price
|
|
- element.first().unwrap().close_price
|
|
> 0.0
|
|
{
|
|
up_vec.push(
|
|
element.last().unwrap().close_price
|
|
- element.first().unwrap().close_price,
|
|
);
|
|
down_vec.push(0.0);
|
|
} else if element.last().unwrap().close_price
|
|
- element.first().unwrap().close_price
|
|
< 0.0
|
|
{
|
|
up_vec.push(0.0);
|
|
down_vec.push(
|
|
(element.last().unwrap().close_price
|
|
- element.first().unwrap().close_price)
|
|
.abs(),
|
|
);
|
|
} else {
|
|
up_vec.push(0.0);
|
|
down_vec.push(0.0);
|
|
}
|
|
}
|
|
|
|
if current_avg_ups == None
|
|
&& current_avg_downs == None
|
|
&& prev_avg_ups == None
|
|
&& prev_avg_downs == None
|
|
{
|
|
// initial averages based on SMA
|
|
let mut avg_ups: f64 = up_vec.iter().sum();
|
|
avg_ups /= rsi_number as f64;
|
|
let mut avg_downs: f64 = down_vec.iter().sum();
|
|
avg_downs /= rsi_number as f64;
|
|
|
|
current_avg_ups = Some(avg_ups);
|
|
current_avg_downs = Some(avg_downs);
|
|
} else {
|
|
// [EMA]
|
|
let alpha = 1.0 / (rsi_number as f64); // Wilder's weight
|
|
current_avg_ups = Some(
|
|
alpha * up_vec.last().unwrap()
|
|
+ ((1.0 - alpha) * prev_avg_ups.unwrap()),
|
|
);
|
|
current_avg_downs = Some(
|
|
alpha * down_vec.last().unwrap()
|
|
+ ((1.0 - alpha) * prev_avg_downs.unwrap()),
|
|
);
|
|
}
|
|
prev_avg_ups = current_avg_ups;
|
|
prev_avg_downs = current_avg_downs;
|
|
|
|
let rs = current_avg_ups.unwrap()
|
|
/ (current_avg_downs.unwrap() + 0.00000001); // 0.00000001 is used to avoid division by 0
|
|
|
|
let rsi = 100.0 - (100.0 / (1.0 + rs));
|
|
|
|
rsi_data.rsi_value = rsi;
|
|
rsi_data.close_time = buffer.last().unwrap().close_time;
|
|
rsi_data_vec.push(rsi_data.clone());
|
|
}
|
|
let mut rsi_data_wrapper_lock = rsi_data_wrapper_arc_c.lock().await;
|
|
rsi_data_wrapper_lock.insert(symbol_c, rsi_data_vec.clone());
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
try_join_all(task_vec).await?;
|
|
let a = rsi_data_wrapper_arc.lock().await.to_owned();
|
|
Ok(a)
|
|
}
|