From 4a323815c82e6dab990485cf7a22d7b135373de9 Mon Sep 17 00:00:00 2001 From: Sik Yoon Date: Sun, 24 Mar 2024 06:04:15 +0900 Subject: [PATCH] New tema indicator --- src/strategy_team/mod.rs | 1 + src/strategy_team/strategy_006.rs | 8 +- src/value_estimation_team/indicators/tema.rs | 227 +++++++++++++------ 3 files changed, 160 insertions(+), 76 deletions(-) diff --git a/src/strategy_team/mod.rs b/src/strategy_team/mod.rs index c2c6cdb..412954c 100644 --- a/src/strategy_team/mod.rs +++ b/src/strategy_team/mod.rs @@ -26,6 +26,7 @@ use crate::value_estimation_team::indicators::stoch_rsi::{stoch_rsi, StochRsiDat use crate::value_estimation_team::indicators::supertrend::{supertrend, SupertrendData, SuperTrendArea, SuperTrendSignal}; use crate::value_estimation_team::indicators::adx::{AdxData, adx}; use crate::value_estimation_team::indicators::dema::{DemaData, dema}; +use crate::value_estimation_team::indicators::tema::{TemaData, tema}; use futures::future::try_join_all; use reqwest::{Client, ClientBuilder}; use rust_decimal::{prelude::FromPrimitive, prelude::ToPrimitive, Decimal, RoundingStrategy}; diff --git a/src/strategy_team/strategy_006.rs b/src/strategy_team/strategy_006.rs index 1bb4d91..f610afe 100644 --- a/src/strategy_team/strategy_006.rs +++ b/src/strategy_team/strategy_006.rs @@ -3,7 +3,7 @@ use super::{ limit_order_sell, rsi, select_filled_buy_orders, stoch_rsi, supertrend, try_join_all, AllData, Arc, Client, ClientBuilder, Decimal, EmaData, ExchangeInfo, FilteredDataValue, Mutex, RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SupertrendData, TradeFee, update_record3, adx, AdxData, get_server_epoch, MacdData, ema_macd, - BollingerBandData, ToPrimitive, duplicate_filter, HashMap, HashSet, remove_keys, SuperTrendArea, SuperTrendSignal, get_current_price, dema, DemaData + BollingerBandData, ToPrimitive, duplicate_filter, HashMap, HashSet, remove_keys, SuperTrendArea, SuperTrendSignal, get_current_price, dema, DemaData, tema, TemaData }; // BUY conditions @@ -24,9 +24,9 @@ pub async fn list_up_for_buy( filtered_data.insert(symbol.clone(), FilteredDataValue::new()); } - // for debugging dema - let dema_filtering = dema(9, &alldata.rt_price_1d_vec, &filtered_data).await?; - println!("{:?}", dema_filtering.get("API3USDT")); + // for debugging tema + let tema_filtering = tema(30, &alldata.rt_price_1d_vec, &filtered_data).await?; + println!("{:?}", tema_filtering.get("API3USDT")); // 2nd filtering: 1d MACD (3, 7, 30) cross let mut keys_to_remove: HashSet = HashSet::new(); diff --git a/src/value_estimation_team/indicators/tema.rs b/src/value_estimation_team/indicators/tema.rs index 421609a..b49bc23 100644 --- a/src/value_estimation_team/indicators/tema.rs +++ b/src/value_estimation_team/indicators/tema.rs @@ -1,87 +1,170 @@ #![allow(unused)] #![allow(warnings)] - use crate::database_control::*; -use csv::{DeserializeRecordsIter, StringRecord}; +use crate::value_estimation_team::datapoints::price_data::RealtimePriceData; +use futures::future::try_join_all; use serde::Deserialize; use sqlx::FromRow; -use tokio::{fs::*, io::AsyncWriteExt, time::*}; +use std::{iter::zip, sync::Arc}; +use tokio::{fs::*, io::AsyncWriteExt, sync::Mutex, time::*}; +use super::FilteredDataValue; +use std::collections::HashMap; +use super::ema::{ema, EmaData}; +#[derive(Clone, Debug)] +pub struct TemaData { + pub tema_value: f64, + pub close_time: i64, +} +impl TemaData { + fn new() -> TemaData { + let a = TemaData { + tema_value: 0.0, + close_time: 0, + }; + a + } +} + +// Binance TEMA (closeprice) pub async fn tema( - tema_number: usize, - input_ema_data: &Vec<(String, Vec<(f64, i64)>)>, - output_tema_data: &mut Vec<(String, Vec<(f64, i64)>)>, - valid_usdt_trades: &Vec, -) -> Result<(), Box> { - let alpha: f64 = 2.0 / (tema_number as f64 + 1.0); - let mut ema_2order: Vec = Vec::new(); - let mut ema_3order: Vec = Vec::new(); + moving_number: usize, + input_rt_data: &HashMap>, + filtered_symbols: &HashMap, +) -> Result>, Box> { + if filtered_symbols.is_empty() { + Err("Err")?; + } + let e1 = ema(moving_number, input_rt_data, filtered_symbols).await?; - let mut tema_data_wrapper: Vec<(String, Vec<(f64, i64)>)> = Vec::new(); - let mut tema_data_vec: Vec<(f64, i64)> = Vec::new(); - for symbol in valid_usdt_trades { - let symbol_search_result = input_ema_data.iter().position(|x| x.0 == *symbol); + // calculate EMA(EMA(n)) + let alpha: f64 = 2.0 / (moving_number as f64 + 1.0); + let mut ema_t: f64 = 0.0; + let mut ema_prev: f64 = 0.0; - tema_data_vec.clear(); - ema_2order.clear(); - ema_3order.clear(); + let mut ema_data_wrapper: HashMap> = HashMap::new(); + let mut ema_data_wrapper_arc = Arc::new(Mutex::new(ema_data_wrapper)); + let mut task_vec = Vec::new(); + for (symbol, e1_ema_vec) in &e1 { + let ema_data_wrapper_arc_c = Arc::clone(&ema_data_wrapper_arc); + let mut ema_data = EmaData::new(); + let mut ema_data_vec: Vec = Vec::new(); + let symbol_c = symbol.clone(); + let e1_ema_vec_c = e1_ema_vec.clone(); + task_vec.push(tokio::spawn(async move { + if e1_ema_vec_c.len() > moving_number { + let partial_vec1 = e1_ema_vec_c.get(..moving_number).unwrap(); + let partial_vec2 = e1_ema_vec_c.get(moving_number..).unwrap(); - match symbol_search_result { - Some(T) => { - if input_ema_data[T].1.len() < tema_number { - tema_data_vec.push((0.0, 0)); - } else { - // calculate 2order of ema from 1order of ema - let mut ema_prev = 0.0; - { - let partial_vec1 = input_ema_data[T].1.get(..tema_number).unwrap(); - let partial_vec2 = input_ema_data[T].1.get(tema_number..).unwrap(); - - let mut sma_for_initial_value = 0.0; - for element in partial_vec1 { - sma_for_initial_value += element.0; - } - sma_for_initial_value /= tema_number as f64; - ema_2order.push(sma_for_initial_value); - ema_prev = sma_for_initial_value; - - let mut index_2order: usize = 0; - for element in partial_vec2 { - ema_2order.push( - ((1.0 - alpha) * ema_2order[index_2order]) + (alpha * element.0), - ); - index_2order += 1; - } - } - - // calculate 3order of ema from 2order of ema - let mut index_3order: usize = 0; - for element in &ema_2order { - if element == ema_2order.first().unwrap() { - ema_3order.push(*element); - } else { - ema_3order.push( - ((1.0 - alpha) * ema_3order[index_3order]) + (alpha * (*element)), - ); - index_3order += 1; - } - } - - // write string - let mut index: usize = 0; - let mut tema_price: f64 = 0.0; - for element in &input_ema_data[T].1 { - tema_price = ((element.0 - ema_2order[index]) * 3.0) + ema_3order[index]; - tema_data_vec.push((tema_price, element.1)); - index += 1; - } - tema_data_wrapper.push((symbol.clone(), tema_data_vec.clone())); + let mut sma_for_initial_value = 0.0; + for element in partial_vec1 { + sma_for_initial_value += element.ema_value; } + sma_for_initial_value /= moving_number as f64; + + ema_data.ema_value = sma_for_initial_value; + ema_data.close_time = partial_vec1.last().unwrap().close_time; + ema_data_vec.push(ema_data.clone()); + + ema_prev = sma_for_initial_value; + + for element in partial_vec2 { + ema_t = (1.0 - alpha) * ema_prev + alpha * element.ema_value; + + ema_data.ema_value = ema_t; + ema_data.close_time = element.close_time; + ema_data_vec.push(ema_data.clone()); + + ema_prev = ema_t; + } + let mut ema_data_wrapper_lock = ema_data_wrapper_arc_c.lock().await; + ema_data_wrapper_lock.insert(symbol_c, ema_data_vec.clone()); } - None => {} + })); + + } + try_join_all(task_vec).await?; + let e2 = ema_data_wrapper_arc.lock().await.to_owned(); + + // calculate EMA(EMA(EMA(n))) + let mut ema_data_wrapper: HashMap> = HashMap::new(); + let mut ema_data_wrapper_arc = Arc::new(Mutex::new(ema_data_wrapper)); + let mut task_vec = Vec::new(); + for (symbol, e2_ema_vec) in &e2 { + let ema_data_wrapper_arc_c = Arc::clone(&ema_data_wrapper_arc); + let mut ema_data = EmaData::new(); + let mut ema_data_vec: Vec = Vec::new(); + let symbol_c = symbol.clone(); + let e2_ema_vec_c = e2_ema_vec.clone(); + task_vec.push(tokio::spawn(async move { + if e2_ema_vec_c.len() > moving_number { + let partial_vec1 = e2_ema_vec_c.get(..moving_number).unwrap(); + let partial_vec2 = e2_ema_vec_c.get(moving_number..).unwrap(); + + let mut sma_for_initial_value = 0.0; + for element in partial_vec1 { + sma_for_initial_value += element.ema_value; + } + sma_for_initial_value /= moving_number as f64; + + ema_data.ema_value = sma_for_initial_value; + ema_data.close_time = partial_vec1.last().unwrap().close_time; + ema_data_vec.push(ema_data.clone()); + + ema_prev = sma_for_initial_value; + + for element in partial_vec2 { + ema_t = (1.0 - alpha) * ema_prev + alpha * element.ema_value; + + ema_data.ema_value = ema_t; + ema_data.close_time = element.close_time; + ema_data_vec.push(ema_data.clone()); + + ema_prev = ema_t; + } + let mut ema_data_wrapper_lock = ema_data_wrapper_arc_c.lock().await; + ema_data_wrapper_lock.insert(symbol_c, ema_data_vec.clone()); + } + })); + + } + try_join_all(task_vec).await?; + let e3 = ema_data_wrapper_arc.lock().await.to_owned(); + + let mut tema_data_wrapper: HashMap> = HashMap::new(); + let mut tema_data_wrapper_arc = Arc::new(Mutex::new(tema_data_wrapper)); + let mut task_vec = Vec::new(); + for (symbol, e3_vec) in e3 { + if let (Some(e1_vec), Some(e2_vec)) = (e1.get(&symbol), e2.get(&symbol)) { + let tema_data_wrapper_arc_c: Arc>>> = Arc::clone(&tema_data_wrapper_arc); + let symbol_c = symbol.clone(); + let e1_vec_c = e1_vec.clone(); + let e2_vec_c = e2_vec.clone(); + task_vec.push(tokio::spawn(async move { + if e3_vec.last().unwrap().close_time == e1_vec_c.last().unwrap().close_time && + e3_vec.last().unwrap().close_time == e2_vec_c.last().unwrap().close_time && + e3_vec.len() < e1_vec_c.len() && + e3_vec.len() < e2_vec_c.len() && + e2_vec_c.len() < e1_vec_c.len() { + let mut tema_data_vec: Vec = Vec::new(); + let e1_vec_part = e1_vec_c.get(e1_vec_c.len()-e3_vec.len()..).unwrap(); + let e2_vec_part = e2_vec_c.get(e2_vec_c.len()-e3_vec.len()..).unwrap(); + let zipped_e1_e2 = e1_vec_part.iter().zip(e2_vec_part.iter()); + let zipped_e1_e2_e3 = zipped_e1_e2.zip(e3_vec.iter()); + for element in zipped_e1_e2_e3 { + let mut tema_data = TemaData::new(); + tema_data.close_time = element.0.0.close_time; + tema_data.tema_value = (3.0 * (element.0.0.ema_value - element.0.1.ema_value)) + element.1.ema_value; + tema_data_vec.push(tema_data); + } + let mut dema_data_wrapper_lock = tema_data_wrapper_arc_c.lock().await; + dema_data_wrapper_lock.insert(symbol_c, tema_data_vec.clone()); + } + })); } } - *output_tema_data = tema_data_wrapper; - // println!(" indicators/tema{}_sec 완료", tema_number); - Ok(()) + try_join_all(task_vec).await?; + let a = tema_data_wrapper_arc.lock().await.to_owned(); + + Ok(a) }