pub mod strategy_001; pub mod strategy_002; pub mod strategy_003; pub mod strategy_004; pub mod strategy_005; pub mod strategy_006; pub mod strategy_007; pub mod strategy_008; pub mod strategy_009; pub mod strategy_010; pub mod future_strategy_short; pub mod future_strategy_long; // pub mod strategy_test; pub mod strategy_manager; use crate::coex::exchange_team::get_server_epoch; use crate::coex::order_team::{limit_order_sell, select_filled_buy_orders}; use crate::coin_health_check_team::request_others::{ExchangeInfo, TradeFee}; use crate::database_control::*; use crate::decimal_funcs::*; use crate::value_estimation_team::datapoints::price_data::{CandleType, RealtimePriceData}; use crate::value_estimation_team::indicators::adx::{adx, AdxData}; use crate::value_estimation_team::indicators::bollingerband::{bollingerband, BollingerBandData}; use crate::value_estimation_team::indicators::dema::{dema, DemaData}; use crate::value_estimation_team::indicators::ema::{ema, ema_opclo, EmaData}; use crate::value_estimation_team::indicators::heatmap_volume::{ heatmap_volume, HeatMapLevel, HeatmapVolumeData, }; 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, sma_opclo,sma_open, SmaData}; use crate::value_estimation_team::indicators::stoch_rsi::{stoch_rsi, StochRsiData}; use crate::value_estimation_team::indicators::supertrend::{ supertrend, SuperTrendArea, SuperTrendSignal, SupertrendData, }; use crate::value_estimation_team::indicators::tema::{tema, TemaData}; use crate::value_estimation_team::indicators::wiliams_percent_r::{ wiliams_percent_r, WiliamsPercentR, }; use crate::future::Position; use futures::future::try_join_all; use reqwest::{Client, ClientBuilder}; use rust_decimal::prelude::Zero; use rust_decimal::{prelude::FromPrimitive, prelude::ToPrimitive, Decimal, RoundingStrategy}; use rust_decimal_macros::dec; use sqlx::FromRow; use std::collections::{HashMap, HashSet}; use std::sync::Arc; use strategy_manager::{insert_pre_suggested_coins, insert_future_coins}; use tokio::sync::Mutex; use crate::future::FuturesExchangeInfo; #[derive(Debug, Clone)] pub struct AllData { pub valid_symbol_vec: HashSet, pub rt_price_1m_vec: HashMap>, pub rt_price_30m_vec: HashMap>, pub rt_price_1d_vec: HashMap>, pub rt_price_1w_vec: HashMap>, pub rt_price_1mon_vec: HashMap>, } impl AllData { pub fn new() -> AllData { let a = AllData { valid_symbol_vec: HashSet::new(), rt_price_1m_vec: HashMap::new(), rt_price_30m_vec: HashMap::new(), rt_price_1d_vec: HashMap::new(), rt_price_1w_vec: HashMap::new(), rt_price_1mon_vec: HashMap::new(), }; a } } #[derive(Debug, FromRow, Clone)] pub struct TimeData { pub server_epoch: u64, pub local_epoch: u64, pub epoch_difference: i64, pub server_ymdhs: String, pub local_ymdhs: String, pub last_server_epoch: u64, pub last_server_ymdhs: String, } #[derive(Clone, Debug)] pub struct FilteredDataValue { pub closetime: i64, pub stoploss: Decimal, pub target_price: Decimal, pub current_price: Decimal, } impl FilteredDataValue { fn new() -> FilteredDataValue { let a = FilteredDataValue { closetime: 0, stoploss: Decimal::new(0, 8), target_price: Decimal::new(0, 8), current_price: Decimal::new(0, 8), }; a } } pub async fn duplicate_filter( registerer: i32, original_filtered_data: &HashMap, ) -> Result, Box> { let inspect_table_name_1 = String::from("buy_ordered_coin_list"); let inspect_table_name_2 = String::from("sell_ordered_coin_list"); let inspect_table_name_3 = String::from("pre_suggested_coin_list"); let inspect_table_name_4 = String::from("suggested_coin_list"); let mut filtered_data: HashMap = HashMap::new(); let mut filtered_data_arc: Arc>> = Arc::new(Mutex::new(filtered_data)); let mut task_vec = Vec::new(); for (symbol, filtered_data) in original_filtered_data { let mut exists_condition_build = String::from("symbol=\'"); exists_condition_build.push_str(symbol.as_str()); exists_condition_build.push_str("\' AND registerer="); exists_condition_build.push_str(registerer.to_string().as_str()); // exists_condition_build.push_str("\' AND close_time="); // exists_condition_build.push_str(element.1.to_string().as_str()); let exists_condition = Some(exists_condition_build); let exists_condition_c = exists_condition.clone(); let inspect_table_name_1_c = inspect_table_name_1.clone(); let inspect_table_name_2_c = inspect_table_name_2.clone(); let inspect_table_name_3_c = inspect_table_name_3.clone(); let inspect_table_name_4_c = inspect_table_name_4.clone(); let symbol_c = symbol.clone(); let filtered_data_c = filtered_data.clone(); let filtered_data_arc_c = Arc::clone(&filtered_data_arc); task_vec.push(tokio::spawn(async move { let inspect_result_1 = exists_record(&inspect_table_name_1_c, &exists_condition_c).await; let inspect_result_2 = exists_record(&inspect_table_name_2_c, &exists_condition_c).await; let inspect_result_3 = exists_record(&inspect_table_name_3_c, &exists_condition_c).await; let inspect_result_4 = exists_record(&inspect_table_name_4_c, &exists_condition_c).await; if inspect_result_1 == false && inspect_result_2 == false && inspect_result_3 == false && inspect_result_4 == false { let mut filtered_data_lock = filtered_data_arc_c.lock().await; filtered_data_lock.insert(symbol_c, filtered_data_c); } })); } try_join_all(task_vec).await?; let filtered_data_c = filtered_data_arc.lock().await.clone(); Ok(filtered_data_c) } pub async fn future_duplicate_filter( position: Position, original_filtered_data: &HashMap, future_exchange_info_map: &HashMap ) -> Result, Box> { let inspect_table_name_1 = String::from("future_ordered_coin_list"); let mut filtered_data: HashMap = HashMap::new(); let mut filtered_data_arc: Arc>> = Arc::new(Mutex::new(filtered_data)); let mut task_vec = Vec::new(); for (symbol, filtered_data) in original_filtered_data { let mut exists_condition_build = String::from("symbol=\'"); exists_condition_build.push_str(symbol.as_str()); // exists_condition_build.push_str("\' AND close_time="); // exists_condition_build.push_str(filtered_data.closetime.to_string().as_str()); exists_condition_build.push_str("\' AND position="); exists_condition_build.push_str("\'"); exists_condition_build.push_str(position.to_string().as_str()); exists_condition_build.push_str("\'"); let exists_condition = Some(exists_condition_build); let exists_condition_c = exists_condition.clone(); let inspect_table_name_1_c = inspect_table_name_1.clone(); let future_exchange_info_map_c = future_exchange_info_map.clone(); let symbol_c = symbol.clone(); let filtered_data_c = filtered_data.clone(); let filtered_data_arc_c = Arc::clone(&filtered_data_arc); task_vec.push(tokio::spawn(async move { if future_exchange_info_map_c.contains_key(&symbol_c) { let inspect_result_1 = exists_record(&inspect_table_name_1_c, &exists_condition_c).await; if inspect_result_1 == false { let mut filtered_data_lock = filtered_data_arc_c.lock().await; filtered_data_lock.insert(symbol_c, filtered_data_c); } } })); } try_join_all(task_vec).await?; let filtered_data_c = filtered_data_arc.lock().await.clone(); Ok(filtered_data_c) } pub async fn remove_keys( filtered_data: &mut HashMap, keys_to_remove: HashSet, ) { let len_prev = filtered_data.len(); // remove key-value in filtered_data for symbol in keys_to_remove { filtered_data.remove(&symbol); } let len_now = filtered_data.len(); // shrink capacity of filtered_data if len_now != len_prev { filtered_data.shrink_to_fit(); } } // useful functions for strategists pub async fn get_current_price_f64( symbol: &String, rt_price_map: &HashMap>, ) -> Option { if let Some(rt_vec) = rt_price_map.get(symbol) { if rt_vec.last().is_some_and(|a| a.close_price.is_normal()) { return Some(rt_vec.last().unwrap().close_price); } } None } pub async fn get_current_price_decimal( symbol: &String, rt_price_map: &HashMap>, ) -> Option<(Decimal, i64)> { if let Some(rt_vec) = rt_price_map.get(symbol) { if rt_vec.last().is_some_and(|a| a.close_price.is_normal()) { let current_price = rust_decimal::prelude::FromPrimitive::from_f64( rt_vec.last().unwrap().close_price, ) .unwrap(); let close_time = rt_vec.last().unwrap().close_time; return Some((current_price, close_time)); } } None } pub async fn get_time_data() -> TimeData { let table_name = String::from("time"); let columns = String::from("*"); let condition = None; let mut time_info = TimeData { server_epoch: 0, local_epoch: 0, epoch_difference: 0, server_ymdhs: String::new(), local_ymdhs: String::new(), last_server_epoch: 0, last_server_ymdhs: String::new() }; let select_result = select_record(&table_name, &columns, &condition, &time_info) .await .unwrap(); let a = select_result.first().unwrap().clone(); a }