diff --git a/src/strategy_team/mod.rs b/src/strategy_team/mod.rs index 102998d..70581af 100644 --- a/src/strategy_team/mod.rs +++ b/src/strategy_team/mod.rs @@ -18,7 +18,7 @@ use crate::value_estimation_team::indicators::ema::{ema, EmaData}; use crate::value_estimation_team::indicators::heatmap_volume::{ heatmap_volume, HeatMapLevel, HeatmapVolumeData, }; -use crate::value_estimation_team::indicators::macd::{ema_macd, EmaMacd}; +use crate::value_estimation_team::indicators::macd::{ema_macd, MacdData}; use crate::value_estimation_team::indicators::rsi::{rsi, RsiData}; use crate::value_estimation_team::indicators::sma::{sma, SmaData}; use crate::value_estimation_team::indicators::stoch_rsi::{stoch_rsi, StochRsiData}; diff --git a/src/strategy_team/strategy_manager.rs b/src/strategy_team/strategy_manager.rs index 1cf624b..1e26121 100644 --- a/src/strategy_team/strategy_manager.rs +++ b/src/strategy_team/strategy_manager.rs @@ -37,6 +37,7 @@ pub async fn execute_list_up_for_buy( // let all_data_c4 = all_data.clone(); let all_data_c5 = all_data.clone(); let all_data_c6 = all_data.clone(); + let all_data_ct = all_data.clone(); // strategist_001(all_data).await?; // strategist_002(all_data).await?; // task_vec.push(tokio::spawn(async move { @@ -51,6 +52,9 @@ pub async fn execute_list_up_for_buy( task_vec.push(tokio::spawn(async move { crate::strategy_team::strategy_006::list_up_for_buy(all_data_c6).await; })); + task_vec.push(tokio::spawn(async move { + crate::strategy_team::strategy_test::strategist_test(all_data_ct).await; + })); try_join_all(task_vec).await?; Ok(()) diff --git a/src/strategy_team/strategy_test.rs b/src/strategy_team/strategy_test.rs index 810b0c2..6ae58c2 100644 --- a/src/strategy_team/strategy_test.rs +++ b/src/strategy_team/strategy_test.rs @@ -2,7 +2,7 @@ use super::{ dec, decimal_add, decimal_sub, ema, exists_record, insert_pre_suggested_coins, limit_order_sell, rsi, select_filled_buy_orders, stoch_rsi, supertrend, try_join_all, AllData, Arc, Client, ClientBuilder, Decimal, EmaData, ExchangeInfo, FilteredData, Mutex, - RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SupertrendData, TradeFee, update_record3, adx, AdxData + RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SupertrendData, TradeFee, update_record3, adx, AdxData, MacdData, ema_macd }; @@ -25,7 +25,7 @@ pub async fn strategist_test( // test_symbols.push(symbol_2); // test_symbols.push(symbol_3); - let a = adx(10, 10, &alldata.rt_price_30m_vec, &test_symbols).await?; + let a = ema_macd(3, 7, 3, &alldata.rt_price_1d_vec, &test_symbols).await?; println!("{:?}", a); Ok(()) diff --git a/src/value_estimation_team/indicators/ema.rs b/src/value_estimation_team/indicators/ema.rs index 7d3bf0d..fb102ec 100644 --- a/src/value_estimation_team/indicators/ema.rs +++ b/src/value_estimation_team/indicators/ema.rs @@ -2,7 +2,6 @@ #![allow(warnings)] use crate::database_control::*; use crate::value_estimation_team::datapoints::price_data::RealtimePriceData; -use csv::{DeserializeRecordsIter, StringRecord}; use futures::future::try_join_all; use serde::Deserialize; use sqlx::FromRow; diff --git a/src/value_estimation_team/indicators/macd.rs b/src/value_estimation_team/indicators/macd.rs index 143a202..e164ede 100644 --- a/src/value_estimation_team/indicators/macd.rs +++ b/src/value_estimation_team/indicators/macd.rs @@ -1,15 +1,38 @@ -use crate::value_estimation_team::indicators::ema::EmaData; +use crate::value_estimation_team::indicators::ema::{EmaData, ema}; +use crate::value_estimation_team::datapoints::price_data::RealtimePriceData; +use super::FilteredData; +use std::sync::Arc; +use tokio::{fs::*, io::AsyncWriteExt, sync::Mutex, time::*}; +use futures::future::try_join_all; #[derive(Debug, Clone)] -pub struct EmaMacd { +pub struct MacdData { pub macd_value: f64, + pub signal_value: f64, pub close_time: i64, } -impl EmaMacd { - fn new() -> EmaMacd { - let a = EmaMacd { +impl MacdData { + fn new() -> MacdData { + let a = MacdData { macd_value: 0.0, + signal_value: 0.0, + close_time: 0, + }; + a + } +} + +#[derive(Debug, Clone)] +pub struct TempData { + pub value: f64, + pub close_time: i64, +} + +impl TempData { + fn new() -> TempData { + let a = TempData { + value: 0.0, close_time: 0, }; a @@ -17,67 +40,121 @@ impl EmaMacd { } pub async fn ema_macd( - fast_ema: &Vec, - slow_ema: &Vec, - signal_length: usize, -) -> Result, Box> { - let mut macd = EmaMacd::new(); - let mut macd_vec: Vec = Vec::new(); - let mut macd_signal_vec: Vec = Vec::new(); - let mut macd_oscil_vec: Vec = Vec::new(); + fast_len: usize, + slow_len: usize, + signal_smoothing: usize, + input_rt_data: &Vec<(String, Vec)>, + filtered_symbols: &Vec +) -> Result)>, Box> { + let mut macd_oscil_vec: Vec<(String, Vec)> = Vec::new(); - if fast_ema.len() >= signal_length && slow_ema.len() >= signal_length { - let result = fast_ema.binary_search_by_key( - &slow_ema.first().unwrap().close_time, - |&EmaData { - ema_value, - close_time, - }| close_time, - ); - if result.is_ok() { - let temp_vec = fast_ema.get(result.unwrap()..).unwrap(); - let zipped = temp_vec.iter().zip(slow_ema); - for element in zipped { - macd.macd_value = element.0.ema_value - element.1.ema_value; - macd.close_time = element.0.close_time; - macd_vec.push(macd.clone()); - } + let fast_emas = ema(fast_len, input_rt_data, filtered_symbols).await?; + let slow_emas = ema(slow_len, input_rt_data, filtered_symbols).await?; + let mut macd_data_wrapper: Vec<(String, Vec)> = Vec::new(); + let mut macd_data_wrapper_arc = Arc::new(Mutex::new(macd_data_wrapper)); + let mut task_vec = Vec::new(); + for filtered_elem in filtered_symbols { + let fast_emas_c = fast_emas.clone(); + let slow_emas_c = slow_emas.clone(); + let filtered_elem_c = filtered_elem.clone(); + let macd_data_wrapper_arc_c = Arc::clone(&macd_data_wrapper_arc); + task_vec.push(tokio::spawn(async move { + let fast_search_result = fast_emas_c.iter().position(|x| x.0 == filtered_elem_c.symbol); + let slow_search_result = slow_emas_c.iter().position(|x| x.0 == filtered_elem_c.symbol); - // making signal - let macd_vec_window = macd_vec.windows(signal_length); - for window in macd_vec_window { - let mut sum_value = 0.0; - for element in window { - sum_value += element.macd_value; - } - macd.macd_value = sum_value / signal_length as f64; - macd.close_time = window.last().unwrap().close_time; - macd_signal_vec.push(macd.clone()); - } + if fast_search_result.is_some_and(|a| fast_emas_c[a].1.len() >= signal_smoothing) && + slow_search_result.is_some_and(|a| slow_emas_c[a].1.len() >= signal_smoothing) { + let fast_ema = fast_emas_c[fast_search_result.unwrap()].1.clone(); + let slow_ema = slow_emas_c[fast_search_result.unwrap()].1.clone(); + let result = fast_ema.binary_search_by_key( + &slow_ema.first().unwrap().close_time, + |&EmaData { + ema_value, + close_time, + }| close_time, + ); + if result.is_ok() { + // making MACD + let temp_vec = fast_ema.get(result.unwrap()..).unwrap(); + let zipped = temp_vec.iter().zip(slow_ema); + let mut macd = TempData::new(); + let mut macd_vec: Vec = Vec::new(); + for element in zipped { + macd.value = element.0.ema_value - element.1.ema_value; + macd.close_time = element.0.close_time; + macd_vec.push(macd.clone()); + } + + // making signal (smoothed MACD) + // TODO: this should be calculated in EMA (currently, SMA) + // let macd_vec_window = macd_vec.windows(signal_smoothing); + // let mut macd_signal_vec: Vec = Vec::new(); + // for window in macd_vec_window { + // let mut sum_value = 0.0; + // for element in window { + // sum_value += element.value; + // } + // macd.value = sum_value / signal_smoothing as f64; + // macd.close_time = window.last().unwrap().close_time; + // macd_signal_vec.push(macd.clone()); + // } + let mut macd_signal = TempData::new(); + let mut macd_signal_vec: Vec = Vec::new(); + let partial_vec1 = macd_vec.get(..signal_smoothing).unwrap(); + let partial_vec2 = macd_vec.get(signal_smoothing..).unwrap(); - let result = macd_vec.binary_search_by_key( - &macd_signal_vec.first().unwrap().close_time, - |&EmaMacd { - macd_value, - close_time, - }| close_time, - ); - if result.is_ok() { - let result = macd_vec.get(result.unwrap()..); - if result.is_some() { - if result.unwrap().len() == macd_signal_vec.len() { - let zipped = result.unwrap().iter().zip(macd_signal_vec); + let mut sma_for_initial_value = 0.0; + for element in partial_vec1 { + sma_for_initial_value += element.value; + } + sma_for_initial_value /= signal_smoothing as f64; - for element in zipped { - macd.macd_value = element.0.macd_value - element.1.macd_value; - macd.close_time = element.0.close_time; - macd_oscil_vec.push(macd.clone()); + macd_signal.value = sma_for_initial_value; + macd_signal.close_time = partial_vec1.last().unwrap().close_time; + macd_signal_vec.push(macd_signal.clone()); + + let alpha: f64 = 2.0 / (signal_smoothing as f64 + 1.0); + let mut ema_prev = sma_for_initial_value; + for element in partial_vec2 { + let ema_t = (1.0 - alpha) * ema_prev + alpha * element.value; + + macd_signal.value = ema_t; + macd_signal.close_time = element.close_time; + macd_signal_vec.push(macd_signal.clone()); + + ema_prev = ema_t; + } + + let result = macd_vec.binary_search_by_key( + &macd_signal_vec.first().unwrap().close_time, + |&TempData { + value, + close_time, + }| close_time, + ); + + if result.is_ok() { + let result = macd_vec.get(result.unwrap()..); + if result.is_some() { + let zipped = result.unwrap().iter().zip(macd_signal_vec); + + let mut macd_vec: Vec = Vec::new(); + for element in zipped { + let mut macd = MacdData::new(); + macd.macd_value = element.0.value; + macd.signal_value = element.1.value; + macd.close_time = element.0.close_time; + macd_vec.push(macd); + } + let mut macd_data_wrapper_lock = macd_data_wrapper_arc_c.lock().await; + macd_data_wrapper_lock.push((filtered_elem_c.symbol.clone(), macd_vec.clone())); } } } } - } + })); } - - Ok(macd_oscil_vec) + try_join_all(task_vec).await?; + let a = macd_data_wrapper_arc.lock().await.to_owned(); + Ok(a) }