diff --git a/src/coex/order_team.rs b/src/coex/order_team.rs index 1cf9b5a..fe2f3bd 100644 --- a/src/coex/order_team.rs +++ b/src/coex/order_team.rs @@ -636,6 +636,13 @@ async fn update_repeat_task( ), decimal_sub(dec!(1), trade_fee), ); + + // TODO: sell_count >=1 이면 expected_get_usdt 는 한번만 tradefee만 적용하여 업데이트 할 것. 현재는 수수료를 2번 (매수,매도)를 계산함. 아래 변수에 든 값으로 업데이트 하면 됨 + // let expected_get_usdt = + // decimal_mul(base_qty_to_be_ordered, price).round_dp_with_strategy( + // quote_commission_precision, + // RoundingStrategy::ToZero, + // ); let pure_profit_percent = ((expected_get_usdt.to_f64().unwrap() / element.used_usdt.to_f64().unwrap()) - 1.0) @@ -725,11 +732,12 @@ pub async fn limit_order_sell( .iter() .position(|trade_fee| trade_fee.symbol == buy_ordered_coin.symbol); if quote_asset_precision_option.is_some() && trade_fee_option.is_some() { - let quote_asset_precision = exchange_info_vec[quote_asset_precision_option.unwrap()].quote_asset_precision; + let quote_asset_precision = + exchange_info_vec[quote_asset_precision_option.unwrap()].quote_asset_precision; let trade_fee = trade_fee_vec[trade_fee_option.unwrap()].takercommission; let get_usdt = decimal_mul(sell_base_quantity, sell_base_price) - .round_dp_with_strategy(quote_asset_precision, RoundingStrategy::ToZero); + .round_dp_with_strategy(quote_asset_precision, RoundingStrategy::ToZero); let get_usdt_fee_adjusted = decimal_mul(get_usdt, decimal_sub(dec!(1), trade_fee)) .round_dp_with_strategy(quote_asset_precision, RoundingStrategy::ToZero); @@ -837,7 +845,9 @@ pub async fn limit_order_sell( .iter() .position(|trade_fee| trade_fee.symbol == buy_ordered_coin.symbol); if quote_asset_precision_option.is_some() && trade_fee_option.is_some() { - let quote_asset_precision = exchange_info_vec[quote_asset_precision_option.unwrap()].quote_asset_precision; + let quote_asset_precision = exchange_info_vec + [quote_asset_precision_option.unwrap()] + .quote_asset_precision; let trade_fee = trade_fee_vec[trade_fee_option.unwrap()].takercommission; let get_usdt = rust_decimal::prelude::FromStr::from_str( T.get("cummulativeQuoteQty").unwrap().as_str().unwrap(), @@ -853,7 +863,7 @@ pub async fn limit_order_sell( T.get("origQty").unwrap().as_str().unwrap(), ) .unwrap(); - + if T.get("status").unwrap().as_str().unwrap() == "FILLED" { insert_value_container.push(get_usdt.to_string()); // get_usdt insert_value_container.push(get_usdt_fee_adjusted.to_string()); @@ -862,24 +872,25 @@ pub async fn limit_order_sell( insert_value_container.push(0.0.to_string()); // get_usdt insert_value_container.push(0.0.to_string()); // get_usdt_fee_adjusted } - + insert_value_container.push(buy_ordered_coin.buy_price.to_string()); // buy_price - + if T.get("status").unwrap().as_str().unwrap() == "FILLED" { let sell_price = decimal_div(get_usdt, ordered_base_qty) .round_dp_with_strategy( quote_asset_precision, RoundingStrategy::ToZero, ); - insert_value_container.push(sell_price.to_string()); // sell_price + insert_value_container.push(sell_price.to_string()); + // sell_price } else { insert_value_container.push(0.0.to_string()); // sell_price } - + insert_value_container.push(buy_ordered_coin.stoploss.to_string()); // stoploss insert_value_container.push(buy_ordered_coin.target_price.to_string()); // target_price insert_value_container.push(ordered_base_qty.to_string()); // base_qty_ordered - + if T.get("status").unwrap().as_str().unwrap() == "FILLED" { let pure_profit_percent = decimal_mul( decimal_sub( @@ -898,10 +909,10 @@ pub async fn limit_order_sell( .push(buy_ordered_coin.maximum_profit_percent.to_string()); // maximum_profit_percent insert_value_container.push(buy_ordered_coin.registerer.to_string()); // registerer insert_value_container.push(buy_ordered_coin.is_long.to_string()); // is_long - + insert_values.push(insert_value_container.clone()); insert_records(&insert_table_name, &insert_columns, &insert_values).await; - + // delete record in buy_ordered_coin_list let delete_table_name = String::from("buy_ordered_coin_list"); let mut delete_condition = String::from("WHERE id = "); @@ -1188,13 +1199,14 @@ pub async fn cancel_buy_order( let trade_fee_option = trade_fee_vec .iter() .position(|trade_fee| trade_fee.symbol == order.symbol); - + let base_asset_precision_option = exchange_info_vec .iter() .position(|exchange_info| exchange_info.symbol == order.symbol); if trade_fee_option.is_some() && base_asset_precision_option.is_some() { - let trade_fee = trade_fee_vec[trade_fee_option.unwrap()].takercommission; + let trade_fee = + trade_fee_vec[trade_fee_option.unwrap()].takercommission; let base_qty_ordered = rust_decimal::prelude::FromStr::from_str( T.get("executedQty").unwrap().as_str().unwrap(), @@ -1204,7 +1216,9 @@ pub async fn cancel_buy_order( let base_qty_fee_adjusted = decimal_mul(base_qty_ordered, decimal_sub(dec!(1), trade_fee)); - let base_asset_precision = exchange_info_vec[base_asset_precision_option.unwrap()].base_asset_precision; + let base_asset_precision = exchange_info_vec + [base_asset_precision_option.unwrap()] + .base_asset_precision; let buy_price = decimal_div(cummulative_quote_qty, base_qty_ordered) .round_dp_with_strategy(8, RoundingStrategy::ToZero); @@ -1231,9 +1245,15 @@ pub async fn cancel_buy_order( // update available_usdt if order.used_usdt > cummulative_quote_qty { - add_available_usdt(decimal_sub(order.used_usdt, cummulative_quote_qty)); + add_available_usdt(decimal_sub( + order.used_usdt, + cummulative_quote_qty, + )); } else { - sub_available_usdt(decimal_sub(cummulative_quote_qty, order.used_usdt)); + sub_available_usdt(decimal_sub( + cummulative_quote_qty, + order.used_usdt, + )); } println!("partially buy {}", order.symbol); } @@ -1357,7 +1377,7 @@ pub async fn cancel_sell_order( insert_value_container.push(order.buy_price.to_string()); // buy_price insert_value_container.push(0.0.to_string()); // current_price insert_value_container.push(order.stoploss.to_string()); // stoploss - insert_value_container.push(order.target_price.to_string()); // current_price + insert_value_container.push(order.target_price.to_string()); // target_price insert_value_container.push(order.base_qty_ordered.to_string()); // base_qty_ordered insert_value_container.push(order.base_qty_ordered.to_string()); // base_qty_fee_adjusted insert_value_container.push(0.0.to_string()); // pure_profit_percent @@ -1370,15 +1390,18 @@ pub async fn cancel_sell_order( insert_records(&insert_table_name, &insert_columns, &insert_values).await; } else { let quote_asset_precision_option = exchange_info_vec - .iter() - .position(|exchange_info| exchange_info.symbol == order.symbol); + .iter() + .position(|exchange_info| exchange_info.symbol == order.symbol); let trade_fee_option = trade_fee_vec - .iter() - .position(|trade_fee| trade_fee.symbol == order.symbol); + .iter() + .position(|trade_fee| trade_fee.symbol == order.symbol); if quote_asset_precision_option.is_some() && trade_fee_option.is_some() { - let quote_asset_precision = exchange_info_vec[quote_asset_precision_option.unwrap()].quote_asset_precision; - let trade_fee = trade_fee_vec[trade_fee_option.unwrap()].takercommission; + let quote_asset_precision = exchange_info_vec + [quote_asset_precision_option.unwrap()] + .quote_asset_precision; + let trade_fee = + trade_fee_vec[trade_fee_option.unwrap()].takercommission; if base_qty_executed == base_qty_ordered { // FILLED case // update status FILLED @@ -1404,12 +1427,12 @@ pub async fn cancel_sell_order( ), dec!(100), ); - + let table_name = String::from("sell_ordered_coin_list"); let mut value_build = String::from("\'"); value_build.push_str("FILLED"); value_build.push('\''); - + let update_values = vec![ (String::from("status"), value_build), (String::from("get_usdt"), get_usdt.to_string()), @@ -1423,7 +1446,8 @@ pub async fn cancel_sell_order( pure_profit_percent.to_string(), ), ]; - let update_condition = vec![(String::from("id"), order.id.to_string())]; + let update_condition = + vec![(String::from("id"), order.id.to_string())]; update_record3(&table_name, &update_values, &update_condition) .await .unwrap(); @@ -1448,15 +1472,18 @@ pub async fn cancel_sell_order( RoundingStrategy::ToZero, ); let pure_profit_percent = decimal_mul( - decimal_sub(decimal_div(get_usdt_fee_adjusted, get_usdt), dec!(1)), + decimal_sub( + decimal_div(get_usdt_fee_adjusted, get_usdt), + dec!(1), + ), dec!(100), ); - + let table_name = String::from("sell_ordered_coin_list"); let mut value_build = String::from("\'"); value_build.push_str("FILLED"); value_build.push('\''); - + let update_values = vec![ (String::from("status"), value_build), (String::from("used_usdt"), used_usdt.to_string()), @@ -1475,13 +1502,15 @@ pub async fn cancel_sell_order( pure_profit_percent.to_string(), ), ]; - let update_condition = vec![(String::from("id"), order.id.to_string())]; + let update_condition = + vec![(String::from("id"), order.id.to_string())]; update_record3(&table_name, &update_values, &update_condition) .await .unwrap(); - + // insert record in [buy_ordered_coin_list] - let rest_base_qty = decimal_sub(base_qty_ordered, base_qty_executed); + let rest_base_qty = + decimal_sub(base_qty_ordered, base_qty_executed); let rest_base_qty_fee_adjusted = decimal_mul(rest_base_qty, decimal_sub(dec!(1), trade_fee)); let mut insert_values: Vec> = Vec::new(); @@ -1506,7 +1535,7 @@ pub async fn cancel_sell_order( insert_value_container.push(0.0.to_string()); // maximum_profit_percent insert_value_container.push(order.registerer.to_string()); // registerer insert_value_container.push(order.is_long.to_string()); // is_long - + insert_values.push(insert_value_container.clone()); insert_records(&insert_table_name, &insert_columns, &insert_values) .await; @@ -1668,22 +1697,24 @@ pub async fn query_buy_order( if trade_fee_option.is_some() && base_asset_precision_option.is_some() { let trade_fee = trade_fee_vec[trade_fee_option.unwrap()].takercommission; - let base_asset_precision = exchange_info_vec[base_asset_precision_option.unwrap()].base_asset_precision; + let base_asset_precision = exchange_info_vec + [base_asset_precision_option.unwrap()] + .base_asset_precision; let base_qty_ordered = rust_decimal::prelude::FromStr::from_str( T.get("executedQty").unwrap().as_str().unwrap(), ) .unwrap(); let base_qty_fee_adjusted = decimal_mul(base_qty_ordered, decimal_sub(dec!(1), trade_fee)); - + let cummulative_quote_qty = rust_decimal::prelude::FromStr::from_str( T.get("cummulativeQuoteQty").unwrap().as_str().unwrap(), ) .unwrap(); - + let buy_price = decimal_div(cummulative_quote_qty, base_qty_ordered) .round_dp_with_strategy(8, RoundingStrategy::ToZero); - + let update_values = vec![ (String::from("status"), value_build), // status (String::from("used_usdt"), cummulative_quote_qty.to_string()), // used_usdt @@ -1704,18 +1735,23 @@ pub async fn query_buy_order( update_record3(&table_name, &update_values, &update_condition) .await .unwrap(); - + if T.get("status").unwrap().as_str().unwrap() == "FILLED" { println!("buy {}", order.symbol); // update available_usdt if order.used_usdt > cummulative_quote_qty { - add_available_usdt(decimal_sub(order.used_usdt, cummulative_quote_qty)); + add_available_usdt(decimal_sub( + order.used_usdt, + cummulative_quote_qty, + )); } else { - sub_available_usdt(decimal_sub(cummulative_quote_qty, order.used_usdt)); + sub_available_usdt(decimal_sub( + cummulative_quote_qty, + order.used_usdt, + )); } } } - } else if T.get("status").unwrap().as_str().unwrap() == "CANCELED" { let update_table_name = String::from("suggested_coin_list"); let update_condition = vec![ @@ -1790,14 +1826,20 @@ pub async fn query_sell_order( .position(|trade_fee| trade_fee.symbol == order.symbol); if quote_asset_precision_option.is_some() && trade_fee_option.is_some() { - let quote_asset_precision = exchange_info_vec[quote_asset_precision_option.unwrap()].quote_asset_precision; + let quote_asset_precision = exchange_info_vec + [quote_asset_precision_option.unwrap()] + .quote_asset_precision; let trade_fee = trade_fee_vec[trade_fee_option.unwrap()].takercommission; let get_usdt = rust_decimal::prelude::FromStr::from_str( T.get("cummulativeQuoteQty").unwrap().as_str().unwrap(), ) .unwrap(); - let get_usdt_fee_adjusted = decimal_mul(get_usdt, decimal_sub(dec!(1), trade_fee)) - .round_dp_with_strategy(quote_asset_precision, RoundingStrategy::ToZero); + let get_usdt_fee_adjusted = + decimal_mul(get_usdt, decimal_sub(dec!(1), trade_fee)) + .round_dp_with_strategy( + quote_asset_precision, + RoundingStrategy::ToZero, + ); let ordered_base_qty = rust_decimal::prelude::FromStr::from_str( T.get("executedQty").unwrap().as_str().unwrap(), ) @@ -1808,12 +1850,12 @@ pub async fn query_sell_order( decimal_sub(decimal_div(get_usdt_fee_adjusted, order.used_usdt), dec!(1)), dec!(100), ); - + let table_name = String::from("sell_ordered_coin_list"); let mut value_build = String::from("\'"); value_build.push_str(T.get("status").unwrap().as_str().unwrap()); value_build.push('\''); - + let update_values = vec![ (String::from("status"), value_build), (String::from("get_usdt"), get_usdt.to_string()), diff --git a/src/strategy_team/mod.rs b/src/strategy_team/mod.rs index 56d8196..5ebc47c 100644 --- a/src/strategy_team/mod.rs +++ b/src/strategy_team/mod.rs @@ -9,6 +9,7 @@ pub mod strategy_manager; 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::RealtimePriceData; use crate::value_estimation_team::indicators::bollingerband::{bollingerband, BollingerBandData}; use crate::value_estimation_team::indicators::ema::{ema, EmaData}; @@ -24,11 +25,10 @@ use futures::future::try_join_all; use reqwest::{Client, ClientBuilder}; use rust_decimal::{prelude::FromPrimitive, prelude::ToPrimitive, Decimal, RoundingStrategy}; use rust_decimal_macros::dec; -use crate::decimal_funcs::*; use sqlx::FromRow; use std::sync::Arc; -use tokio::sync::Mutex; use strategy_manager::insert_pre_suggested_coins; +use tokio::sync::Mutex; #[derive(Debug, Clone)] pub struct AllData { @@ -84,4 +84,4 @@ impl FilteredData { }; a } -} \ No newline at end of file +} diff --git a/src/strategy_team/strategy_003.rs b/src/strategy_team/strategy_003.rs index 98c6d80..65a54f1 100644 --- a/src/strategy_team/strategy_003.rs +++ b/src/strategy_team/strategy_003.rs @@ -1,442 +1,495 @@ -use super::{ - dec, ema, exists_record, limit_order_sell, rsi, select_filled_buy_orders, stoch_rsi, - supertrend, try_join_all, AllData, Arc, Client, ClientBuilder, EmaData, ExchangeInfo, Mutex, - RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SupertrendData, TradeFee, -}; +// use super::{ +// dec, ema, exists_record, limit_order_sell, rsi, select_filled_buy_orders, stoch_rsi, +// supertrend, try_join_all, AllData, Arc, Client, ClientBuilder, EmaData, ExchangeInfo, Mutex, +// RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SupertrendData, TradeFee, +// insert_pre_suggested_coins, Decimal, FilteredData, decimal_add, decimal_sub +// }; -pub async fn list_up_for_buy( - alldata: &AllData, -) -> Result<(), Box> { - // print rt_price for debugging - // let a = alldata.rt_price_30m_vec.iter().position(|a| a.0 == "BTCUSDT"); - // println!("BTCUSDT: {:?}", alldata.rt_price_30m_vec[a.unwrap()].1.last().unwrap()); +// pub async fn list_up_for_buy( +// alldata: AllData, +// ) -> Result<(), Box> { +// // print rt_price for debugging +// // let a = alldata.rt_price_30m_vec.iter().position(|a| a.0 == "BTCUSDT"); +// // println!("BTCUSDT: {:?}", alldata.rt_price_30m_vec[a.unwrap()].1.last().unwrap()); - // 1st filtering: supertrend(ATR period 100, multiplier: 6.0, 30m close price), the area should be in UP area. - let mut filtered_2nd_symbols: Vec<(String, i64)> = Vec::new(); - let mut filtered_2nd_symbols_arc: Arc>> = - Arc::new(Mutex::new(filtered_2nd_symbols)); // (symbol, closetime) - let mut task_vec = Vec::new(); - let valid_symbol_vec_c = alldata.valid_symbol_vec.clone(); - for symbol in valid_symbol_vec_c { - let mut opclo_30m_vec: Vec = Vec::new(); - let mut supertrend_vec: Vec = Vec::new(); - let rt_price_30m_vec_c = alldata.rt_price_30m_vec.clone(); - let filtered_2nd_symbols_arc_c = Arc::clone(&filtered_2nd_symbols_arc); - task_vec.push(tokio::spawn(async move { - let opclo_30m_option = rt_price_30m_vec_c.iter().position(|x| *x.0 == symbol); - let supertrend_option_30m = - supertrend(&symbol, &rt_price_30m_vec_c, 100, 6.0, true).await; +// // 1st filtering: lookup tables if the tradepair is already there +// 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"); - if opclo_30m_option.is_some() && supertrend_option_30m.is_some() { - opclo_30m_vec = rt_price_30m_vec_c[opclo_30m_option.unwrap()].1.clone(); - supertrend_vec = supertrend_option_30m.unwrap(); +// let mut filtered_data_1st: Vec = Vec::new(); +// let mut filtered_data_1st_arc: Arc>> = +// Arc::new(Mutex::new(filtered_data_1st)); +// let mut task_vec = Vec::new(); - if opclo_30m_vec.len() >= 3 && supertrend_vec.len() >= 3 { - let supertrend_search_result = supertrend_vec.binary_search_by_key( - &opclo_30m_vec.last().unwrap().close_time, - |SupertrendData { - band_value, - signal, - area, - close_time, - }| *close_time, - ); - if supertrend_search_result.is_ok() { - if supertrend_vec[supertrend_search_result.unwrap()] - .area - .contains("UP") - { - let mut filtered_2nd_symbols_lock = - filtered_2nd_symbols_arc_c.lock().await; - filtered_2nd_symbols_lock - .push((symbol.clone(), opclo_30m_vec.last().unwrap().close_time)); - } - } - } - } - })); - } - try_join_all(task_vec).await?; +// for symbol in &alldata.valid_symbol_vec { +// 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(3.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_1st_arc_c = Arc::clone(&filtered_data_1st_arc); +// task_vec.push(tokio::spawn(async move { +// let mut filtered_data = FilteredData::new(); +// 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; - // 2nd filtering: lookup tables if the tradepair is already there - 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"); +// if inspect_result_1 == false +// && inspect_result_2 == false +// && inspect_result_3 == false +// && inspect_result_4 == false +// { +// let mut filtered_data_1st_lock = filtered_data_1st_arc_c.lock().await; - let mut filtered_3rd_symbols: Vec<(String, i64)> = Vec::new(); - let mut filtered_3rd_symbols_arc: Arc>> = - Arc::new(Mutex::new(filtered_3rd_symbols)); // (symbol, closetime) - let mut task_vec = Vec::new(); +// filtered_data.symbol = symbol_c; - let filtered_2nd_iter = filtered_2nd_symbols_arc.lock().await.clone().into_iter(); - for element in filtered_2nd_iter { - let mut exists_condition_build = String::from("symbol=\'"); - exists_condition_build.push_str(element.0.as_str()); - exists_condition_build.push_str("\' AND registerer="); - exists_condition_build.push_str(3.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 element_c = element.clone(); - let filtered_3rd_symbols_arc_c = Arc::clone(&filtered_3rd_symbols_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; +// filtered_data_1st_lock.push(filtered_data); +// } +// })); +// } +// try_join_all(task_vec).await?; - if inspect_result_1 == false - && inspect_result_2 == false - && inspect_result_3 == false - && inspect_result_4 == false - { - let mut filtered_3rd_symbols_lock = filtered_3rd_symbols_arc_c.lock().await; - filtered_3rd_symbols_lock.push(element_c); - } - })); - } - try_join_all(task_vec).await?; +// // 1st filtering: supertrend(ATR period 100, multiplier: 6.0, 30m close price), the area should be in UP area. +// let mut filtered_2nd_symbols: Vec<(String, i64)> = Vec::new(); +// let mut filtered_2nd_symbols_arc: Arc>> = +// Arc::new(Mutex::new(filtered_2nd_symbols)); // (symbol, closetime) +// let mut task_vec = Vec::new(); +// let valid_symbol_vec_c = alldata.valid_symbol_vec.clone(); +// for symbol in valid_symbol_vec_c { +// let mut opclo_30m_vec: Vec = Vec::new(); +// let mut supertrend_vec: Vec = Vec::new(); +// let rt_price_30m_vec_c = alldata.rt_price_30m_vec.clone(); +// let filtered_2nd_symbols_arc_c = Arc::clone(&filtered_2nd_symbols_arc); +// task_vec.push(tokio::spawn(async move { +// let opclo_30m_option = rt_price_30m_vec_c.iter().position(|x| *x.0 == symbol); +// let supertrend_option_30m = +// supertrend(&symbol, &rt_price_30m_vec_c, 100, 6.0, true).await; - // 3rd filtering: EMA30 > EMA 150 - let filtered_3rd_symbols_c = filtered_3rd_symbols_arc.lock().await.clone(); - let ema30_30m_data: Vec<(String, Vec)> = - ema(30, &alldata.rt_price_30m_vec, &filtered_3rd_symbols_c).await?; - let ema150_30m_data: Vec<(String, Vec)> = - ema(150, &alldata.rt_price_30m_vec, &filtered_3rd_symbols_c).await?; +// if opclo_30m_option.is_some() && supertrend_option_30m.is_some() { +// opclo_30m_vec = rt_price_30m_vec_c[opclo_30m_option.unwrap()].1.clone(); +// supertrend_vec = supertrend_option_30m.unwrap(); - let mut task_vec = Vec::new(); - let mut filtered_4th_symbols: Vec<(String, i64)> = Vec::new(); - let mut filtered_4th_symbols_arc: Arc>> = - Arc::new(Mutex::new(filtered_4th_symbols)); // (symbol, closetime) - for element in filtered_3rd_symbols_c { - let mut ema30_30m_vec: Vec = Vec::new(); - let mut ema150_30m_vec: Vec = Vec::new(); - let ema30_30m_option = ema30_30m_data.iter().position(|x| *x.0 == element.0); - let ema30_30m_option_c = ema30_30m_option.clone(); - let ema150_30m_option = ema150_30m_data.iter().position(|x| *x.0 == element.0); - let ema150_30m_option_c = ema150_30m_option.clone(); - let element_c = element.clone(); - let filtered_4th_symbols_arc_c = Arc::clone(&filtered_4th_symbols_arc); +// if opclo_30m_vec.len() >= 3 && supertrend_vec.len() >= 3 { +// let supertrend_search_result = supertrend_vec.binary_search_by_key( +// &opclo_30m_vec.last().unwrap().close_time, +// |SupertrendData { +// band_value, +// signal, +// area, +// close_time, +// }| *close_time, +// ); +// if supertrend_search_result.is_ok() { +// if supertrend_vec[supertrend_search_result.unwrap()] +// .area +// .contains("UP") +// { +// let mut filtered_2nd_symbols_lock = +// filtered_2nd_symbols_arc_c.lock().await; +// filtered_2nd_symbols_lock +// .push((symbol.clone(), opclo_30m_vec.last().unwrap().close_time)); +// } +// } +// } +// } +// })); +// } +// try_join_all(task_vec).await?; - if ema30_30m_option_c.is_some() && ema150_30m_option_c.is_some() { - ema30_30m_vec = ema30_30m_data[ema30_30m_option.unwrap()].1.clone(); - ema150_30m_vec = ema150_30m_data[ema150_30m_option.unwrap()].1.clone(); +// // 2nd filtering: lookup tables if the tradepair is already there +// 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"); - if ema30_30m_vec.len() >= 10 && ema150_30m_vec.len() >= 10 { - let ema30_30m_vec_c = ema30_30m_vec.clone(); - let ema150_30m_vec_c = ema150_30m_vec.clone(); +// let mut filtered_3rd_symbols: Vec<(String, i64)> = Vec::new(); +// let mut filtered_3rd_symbols_arc: Arc>> = +// Arc::new(Mutex::new(filtered_3rd_symbols)); // (symbol, closetime) +// let mut task_vec = Vec::new(); - task_vec.push(tokio::spawn(async move { - let ema30_search_result = ema30_30m_vec_c.binary_search_by_key( - &element_c.1, - |&EmaData { - ema_value, - close_time, - }| close_time, - ); - let ema150_search_result = ema150_30m_vec_c.binary_search_by_key( - &element_c.1, - |&EmaData { - ema_value, - close_time, - }| close_time, - ); +// let filtered_2nd_iter = filtered_2nd_symbols_arc.lock().await.clone().into_iter(); +// for element in filtered_2nd_iter { +// let mut exists_condition_build = String::from("symbol=\'"); +// exists_condition_build.push_str(element.0.as_str()); +// exists_condition_build.push_str("\' AND registerer="); +// exists_condition_build.push_str(3.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 element_c = element.clone(); +// let filtered_3rd_symbols_arc_c = Arc::clone(&filtered_3rd_symbols_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 ema30_search_result.is_ok() && ema150_search_result.is_ok() { - if ema30_30m_vec_c[ema30_search_result.unwrap() - 3].ema_value - > ema150_30m_vec_c[ema150_search_result.unwrap() - 3].ema_value - && ema30_30m_vec_c[ema30_search_result.unwrap() - 2].ema_value - > ema150_30m_vec_c[ema150_search_result.unwrap() - 2].ema_value - && ema30_30m_vec_c[ema30_search_result.unwrap() - 1].ema_value - > ema150_30m_vec_c[ema150_search_result.unwrap() - 1].ema_value - && ema30_30m_vec_c[ema30_search_result.unwrap()].ema_value - > ema150_30m_vec_c[ema150_search_result.unwrap()].ema_value - && ema30_30m_vec_c[ema30_search_result.unwrap()].ema_value - > ema30_30m_vec_c[ema30_search_result.unwrap() - 1].ema_value - && ema30_30m_vec_c[ema30_search_result.unwrap() - 1].ema_value - > ema30_30m_vec_c[ema30_search_result.unwrap() - 2].ema_value - && ema30_30m_vec_c[ema30_search_result.unwrap() - 2].ema_value - > ema30_30m_vec_c[ema30_search_result.unwrap() - 3].ema_value - { - let mut filtered_4th_symbols_lock = - filtered_4th_symbols_arc_c.lock().await; - filtered_4th_symbols_lock.push(element_c); - } - } - })); - } - } - } - try_join_all(task_vec).await?; +// if inspect_result_1 == false +// && inspect_result_2 == false +// && inspect_result_3 == false +// && inspect_result_4 == false +// { +// let mut filtered_3rd_symbols_lock = filtered_3rd_symbols_arc_c.lock().await; +// filtered_3rd_symbols_lock.push(element_c); +// } +// })); +// } +// try_join_all(task_vec).await?; - // 4th filtering: StochRSI (RSI length: 10, Stoch length: 10, smooth k: 3, smooth d: 3) 20 > k > kn-1 > kn-2 > kn-3, - let filtered_4th_symbol_c = filtered_4th_symbols_arc.lock().await.clone(); - let mut rsi10_30m_data: Vec<(String, Vec)> = - rsi(10, &alldata.rt_price_30m_vec, &filtered_4th_symbol_c).await?; - let stoch_rsi_data = stoch_rsi(&rsi10_30m_data, 10, 3, 3).await?; - let mut stoch_rsi10_30m_vec: Vec = Vec::new(); - let mut filtered_5th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime) - for element in filtered_4th_symbol_c { - let stoch_rsi10_30m_option = stoch_rsi_data.iter().position(|x| *x.0 == element.0); +// // 3rd filtering: EMA30 > EMA 150 +// let filtered_3rd_symbols_c = filtered_3rd_symbols_arc.lock().await.clone(); +// let ema30_30m_data: Vec<(String, Vec)> = +// ema(30, &alldata.rt_price_30m_vec, &filtered_3rd_symbols_c).await?; +// let ema150_30m_data: Vec<(String, Vec)> = +// ema(150, &alldata.rt_price_30m_vec, &filtered_3rd_symbols_c).await?; - if stoch_rsi10_30m_option.is_some() { - stoch_rsi10_30m_vec = stoch_rsi_data[stoch_rsi10_30m_option.unwrap()].1.clone(); +// let mut task_vec = Vec::new(); +// let mut filtered_4th_symbols: Vec<(String, i64)> = Vec::new(); +// let mut filtered_4th_symbols_arc: Arc>> = +// Arc::new(Mutex::new(filtered_4th_symbols)); // (symbol, closetime) +// for element in filtered_3rd_symbols_c { +// let mut ema30_30m_vec: Vec = Vec::new(); +// let mut ema150_30m_vec: Vec = Vec::new(); +// let ema30_30m_option = ema30_30m_data.iter().position(|x| *x.0 == element.0); +// let ema30_30m_option_c = ema30_30m_option.clone(); +// let ema150_30m_option = ema150_30m_data.iter().position(|x| *x.0 == element.0); +// let ema150_30m_option_c = ema150_30m_option.clone(); +// let element_c = element.clone(); +// let filtered_4th_symbols_arc_c = Arc::clone(&filtered_4th_symbols_arc); - if stoch_rsi10_30m_vec.len() >= 3 { - let stoch_rsi_search_result = stoch_rsi10_30m_vec - .binary_search_by_key(&element.1, |&StochRsiData { k, d, close_time }| { - close_time - }); - if stoch_rsi_search_result.is_ok() { - if 10.0 > stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap()].k - && stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap()].k - > stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap() - 1].k - && stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap() - 1].k - <= stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap() - 2].k - && stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap() - 2].k - <= stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap() - 3].k - { - filtered_5th_symbols.push(element); - } - } - } - } - } +// if ema30_30m_option_c.is_some() && ema150_30m_option_c.is_some() { +// ema30_30m_vec = ema30_30m_data[ema30_30m_option.unwrap()].1.clone(); +// ema150_30m_vec = ema150_30m_data[ema150_30m_option.unwrap()].1.clone(); - // final job: adding price information to filtered results - let mut filtered_symbols: Vec<(String, i64, f64)> = Vec::new(); // (symbol, closetime, current price) - let mut filtered_symbols_arc = Arc::new(Mutex::new(filtered_symbols)); - let mut task_vec = Vec::new(); - for element in filtered_5th_symbols { - let mut filtered_symbols_arc_c = Arc::clone(&filtered_symbols_arc); - let rt_price_30m_vec_c = alldata.rt_price_30m_vec.clone(); +// if ema30_30m_vec.len() >= 10 && ema150_30m_vec.len() >= 10 { +// let ema30_30m_vec_c = ema30_30m_vec.clone(); +// let ema150_30m_vec_c = ema150_30m_vec.clone(); - let elememt_c = element.clone(); - task_vec.push(tokio::spawn(async move { - let opclo_30m_option = rt_price_30m_vec_c.iter().position(|x| *x.0 == element.0); - if opclo_30m_option.is_some() { - if rt_price_30m_vec_c[opclo_30m_option.unwrap()] - .1 - .last() - .is_some() - { - let mut filtered_symbols_lock: tokio::sync::MutexGuard< - '_, - Vec<(String, i64, f64)>, - > = filtered_symbols_arc_c.lock().await; - filtered_symbols_lock.push(( - elememt_c.0, - elememt_c.1, - rt_price_30m_vec_c[opclo_30m_option.unwrap()] - .1 - .last() - .unwrap() - .close_price, - )); - } - } - })); - } +// task_vec.push(tokio::spawn(async move { +// let ema30_search_result = ema30_30m_vec_c.binary_search_by_key( +// &element_c.1, +// |&EmaData { +// ema_value, +// close_time, +// }| close_time, +// ); +// let ema150_search_result = ema150_30m_vec_c.binary_search_by_key( +// &element_c.1, +// |&EmaData { +// ema_value, +// close_time, +// }| close_time, +// ); - try_join_all(task_vec).await?; +// if ema30_search_result.is_ok() && ema150_search_result.is_ok() { +// if ema30_30m_vec_c[ema30_search_result.unwrap() - 3].ema_value +// > ema150_30m_vec_c[ema150_search_result.unwrap() - 3].ema_value +// && ema30_30m_vec_c[ema30_search_result.unwrap() - 2].ema_value +// > ema150_30m_vec_c[ema150_search_result.unwrap() - 2].ema_value +// && ema30_30m_vec_c[ema30_search_result.unwrap() - 1].ema_value +// > ema150_30m_vec_c[ema150_search_result.unwrap() - 1].ema_value +// && ema30_30m_vec_c[ema30_search_result.unwrap()].ema_value +// > ema150_30m_vec_c[ema150_search_result.unwrap()].ema_value +// && ema30_30m_vec_c[ema30_search_result.unwrap()].ema_value +// > ema30_30m_vec_c[ema30_search_result.unwrap() - 1].ema_value +// && ema30_30m_vec_c[ema30_search_result.unwrap() - 1].ema_value +// > ema30_30m_vec_c[ema30_search_result.unwrap() - 2].ema_value +// && ema30_30m_vec_c[ema30_search_result.unwrap() - 2].ema_value +// > ema30_30m_vec_c[ema30_search_result.unwrap() - 3].ema_value +// { +// let mut filtered_4th_symbols_lock = +// filtered_4th_symbols_arc_c.lock().await; +// filtered_4th_symbols_lock.push(element_c); +// } +// } +// })); +// } +// } +// } +// try_join_all(task_vec).await?; - // TODO: abnormal price filtering (too high current price) +// // 4th filtering: StochRSI (RSI length: 10, Stoch length: 10, smooth k: 3, smooth d: 3) 20 > k > kn-1 > kn-2 > kn-3, +// let filtered_4th_symbol_c = filtered_4th_symbols_arc.lock().await.clone(); +// let mut rsi10_30m_data: Vec<(String, Vec)> = +// rsi(10, &alldata.rt_price_30m_vec, &filtered_4th_symbol_c).await?; +// let stoch_rsi_data = stoch_rsi(&rsi10_30m_data, 10, 3, 3).await?; +// let mut stoch_rsi10_30m_vec: Vec = Vec::new(); +// let mut filtered_5th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime) +// for element in filtered_4th_symbol_c { +// let stoch_rsi10_30m_option = stoch_rsi_data.iter().position(|x| *x.0 == element.0); - // 6th filtering condition: MACD - // let mut opclo_30m_vec: Vec = Vec::new(); - // let mut ema3_1d_vec: &Vec = &Vec::new(); - // let mut ema10_1d_vec: &Vec = &Vec::new(); +// if stoch_rsi10_30m_option.is_some() { +// stoch_rsi10_30m_vec = stoch_rsi_data[stoch_rsi10_30m_option.unwrap()].1.clone(); - // let mut filtered_7th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime) - // for element in filtered_6th_symbols { - // let ema3_1d_option = alldata.ema3_1d_data.iter().position(|x| *x.0 == *element.0); - // let ema10_1d_option = alldata.ema10_1d_data.iter().position(|x| *x.0 == *element.0); +// if stoch_rsi10_30m_vec.len() >= 3 { +// let stoch_rsi_search_result = stoch_rsi10_30m_vec +// .binary_search_by_key(&element.1, |&StochRsiData { k, d, close_time }| { +// close_time +// }); +// if stoch_rsi_search_result.is_ok() { +// if 10.0 > stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap()].k +// && stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap()].k +// > stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap() - 1].k +// && stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap() - 1].k +// <= stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap() - 2].k +// && stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap() - 2].k +// <= stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap() - 3].k +// { +// filtered_5th_symbols.push(element); +// } +// } +// } +// } +// } - // if ema3_1d_option.is_some() && ema10_1d_option.is_some() { - // ema3_1d_vec = &alldata.ema3_1d_data[ema3_1d_option.unwrap()].1; - // ema10_1d_vec = &alldata.ema10_1d_data[ema10_1d_option.unwrap()].1; +// // final job: adding price information to filtered results +// let mut filtered_symbols: Vec<(String, i64, f64)> = Vec::new(); // (symbol, closetime, current price) +// let mut filtered_symbols_arc = Arc::new(Mutex::new(filtered_symbols)); +// let mut task_vec = Vec::new(); +// for element in filtered_5th_symbols { +// let mut filtered_symbols_arc_c = Arc::clone(&filtered_symbols_arc); +// let rt_price_30m_vec_c = alldata.rt_price_30m_vec.clone(); - // if ema3_1d_vec.len() > 20 && ema10_1d_vec.len() > 20 { - // let macd_vec = ema_macd(&ema3_1d_vec, &ema10_1d_vec, 10).await?; - // // let macd_search_result = macd_vec.binary_search_by_key(&element.1, |&EmaMacd{macd_value, close_time}|close_time); +// let elememt_c = element.clone(); +// task_vec.push(tokio::spawn(async move { +// let opclo_30m_option = rt_price_30m_vec_c.iter().position(|x| *x.0 == element.0); +// if opclo_30m_option.is_some() { +// if rt_price_30m_vec_c[opclo_30m_option.unwrap()] +// .1 +// .last() +// .is_some() +// { +// let mut filtered_symbols_lock: tokio::sync::MutexGuard< +// '_, +// Vec<(String, i64, f64)>, +// > = filtered_symbols_arc_c.lock().await; +// filtered_symbols_lock.push(( +// elememt_c.0, +// elememt_c.1, +// rt_price_30m_vec_c[opclo_30m_option.unwrap()] +// .1 +// .last() +// .unwrap() +// .close_price, +// )); +// } +// } +// })); +// } - // // if macd_search_result.is_ok() { - // if macd_vec.last().unwrap().macd_value - macd_vec[macd_vec.len() -2].macd_value >= 0.0 { - // filtered_7th_symbols.push(element); - // } - // // } - // } - // } - // } - let a = filtered_symbols_arc.lock().await.clone(); - super::strategy_manager::insert_pre_suggested_coins(3, false, &a, alldata, dec!(0)).await; +// try_join_all(task_vec).await?; - Ok(()) -} +// // TODO: abnormal price filtering (too high current price) -pub async fn list_up_for_sell( - all_data: &AllData, - exchange_info_vec: &Vec, - trade_fee_vec: &Vec, -) -> Result<(), Box> { - let filled_buy_orders = select_filled_buy_orders(3).await?; +// // 6th filtering condition: MACD +// // let mut opclo_30m_vec: Vec = Vec::new(); +// // let mut ema3_1d_vec: &Vec = &Vec::new(); +// // let mut ema10_1d_vec: &Vec = &Vec::new(); - if !filled_buy_orders.is_empty() { - let client = ClientBuilder::new() - .timeout(tokio::time::Duration::from_millis(5000)) - .build() - .unwrap(); +// // let mut filtered_7th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime) +// // for element in filtered_6th_symbols { +// // let ema3_1d_option = alldata.ema3_1d_data.iter().position(|x| *x.0 == *element.0); +// // let ema10_1d_option = alldata.ema10_1d_data.iter().position(|x| *x.0 == *element.0); - let mut sell_order_count = 0; - for element in filled_buy_orders { - if element.used_usdt >= dec!(10.0) { - // ignore coins having 10 usdt below because of not traded - let sell_percent_for_uptrend = |z: f64| 0.94 * z - 0.5; +// // if ema3_1d_option.is_some() && ema10_1d_option.is_some() { +// // ema3_1d_vec = &alldata.ema3_1d_data[ema3_1d_option.unwrap()].1; +// // ema10_1d_vec = &alldata.ema10_1d_data[ema10_1d_option.unwrap()].1; - let lot_step_size_option = exchange_info_vec - .iter() - .find(|exchange_info| exchange_info.symbol == element.symbol); - let quote_commission_precision_option = exchange_info_vec - .iter() - .find(|exchange_info| exchange_info.symbol == element.symbol); +// // if ema3_1d_vec.len() > 20 && ema10_1d_vec.len() > 20 { +// // let macd_vec = ema_macd(&ema3_1d_vec, &ema10_1d_vec, 10).await?; +// // // let macd_search_result = macd_vec.binary_search_by_key(&element.1, |&EmaMacd{macd_value, close_time}|close_time); - let opclo_30m_option = all_data - .rt_price_30m_vec - .iter() - .position(|x| *x.0 == element.symbol); +// // // if macd_search_result.is_ok() { +// // if macd_vec.last().unwrap().macd_value - macd_vec[macd_vec.len() -2].macd_value >= 0.0 { +// // filtered_7th_symbols.push(element); +// // } +// // // } +// // } +// // } +// // } +// let a = filtered_symbols_arc.lock().await.clone(); +// insert_pre_suggested_coins(3, false, &a, &alldata).await; - if lot_step_size_option.is_some() - && quote_commission_precision_option.is_some() - && opclo_30m_option.is_some() - { - let lot_step_size = lot_step_size_option.unwrap().stepsize; - let quote_commission_precision = quote_commission_precision_option - .unwrap() - .quote_commission_precision; - let base_qty_to_be_ordered = - element.base_qty_fee_adjusted.round_dp_with_strategy( - lot_step_size.normalize().scale(), - RoundingStrategy::ToZero, - ); +// Ok(()) +// } - let mut opclo_30m_vec = all_data.rt_price_30m_vec[opclo_30m_option.unwrap()] - .1 - .clone(); +// pub async fn list_up_for_sell( +// all_data: &AllData, +// exchange_info_vec: &Vec, +// trade_fee_vec: &Vec, +// ) -> Result<(), Box> { +// let filled_buy_orders = select_filled_buy_orders(3).await?; - opclo_30m_vec.pop(); - opclo_30m_vec.reverse(); - let mut opclo_sample_length: usize = 50; // 50 candle samsples - let nbr_of_exclusive: usize = 5; - opclo_30m_vec.truncate(opclo_sample_length); - opclo_30m_vec.sort_by(|a, b| { - (a.high_price - a.low_price).total_cmp(&(b.high_price - b.low_price)) - }); - opclo_30m_vec.truncate(opclo_sample_length - nbr_of_exclusive); - opclo_sample_length -= nbr_of_exclusive; +// if !filled_buy_orders.is_empty() { +// let client = ClientBuilder::new() +// .timeout(tokio::time::Duration::from_millis(5000)) +// .build() +// .unwrap(); - let mut sum_amplitude_candles = 0.0; - let mut sum_ratio_amp_body = 0.0; - for element in &opclo_30m_vec { - sum_amplitude_candles += - ((element.high_price / element.low_price) - 1.0) * 100.0; - sum_ratio_amp_body += (element.close_price - element.open_price).abs() - / (element.high_price - element.low_price); - } - let average_amplitude = sum_amplitude_candles / opclo_sample_length as f64; // percent unit - let average_ratio_amp_body = sum_ratio_amp_body / opclo_sample_length as f64; +// let mut sell_order_count = 0; +// for element in filled_buy_orders { +// if element.used_usdt >= dec!(10.0) { +// // ignore coins having 10 usdt below because of not traded +// let sell_percent_for_uptrend = |z: f64| 0.94 * z - 0.5; - let mut amplitude_variance = 0.0; - for element in &opclo_30m_vec { - amplitude_variance += ((((element.high_price / element.low_price) - 1.0) - * 100.0) - - average_amplitude) - .powi(2); - } - amplitude_variance = amplitude_variance / (opclo_sample_length - 1) as f64; - let standard_deviation_amplitude = amplitude_variance.sqrt(); +// let lot_step_size_option = exchange_info_vec +// .iter() +// .find(|exchange_info| exchange_info.symbol == element.symbol); +// let quote_commission_precision_option = exchange_info_vec +// .iter() +// .find(|exchange_info| exchange_info.symbol == element.symbol); - // let target_profit_percent = average_amplitude + (standard_deviation_amplitude * (average_ratio_amp_body)); - let target_profit_percent = |multiplier: f64| -> f64 { - if multiplier < 0.0 { - ((average_amplitude) * multiplier) - - (standard_deviation_amplitude * 2.0) // 2.0 sigma (recommand: 0.5 ~ 2.0(patient & greedy)) - } else { - ((average_amplitude) * multiplier) - + (standard_deviation_amplitude * 2.0) // 2.0 sigma (recommand: 0.5 ~ 2.0(patient & greedy)) - } - }; +// let opclo_30m_option = all_data +// .rt_price_30m_vec +// .iter() +// .position(|x| *x.0 == element.symbol); - if element.is_long == 0 || element.is_long == 1 { - if element.pure_profit_percent >= 0.0 { - let mut is_sell = false; - if element.maximum_profit_percent >= target_profit_percent(5.0) + 0.2 - && element.pure_profit_percent >= target_profit_percent(5.0) + 0.2 - { - println!( - "Selling {} 500% target_profit_percent: {:.3}", - element.symbol, element.pure_profit_percent - ); - is_sell = true; - } else if element.pure_profit_percent >= 7.0 { - println!("Selling {} 7% profit_percent", element.symbol); - is_sell = true; - } +// if lot_step_size_option.is_some() +// && quote_commission_precision_option.is_some() +// && opclo_30m_option.is_some() +// { +// let lot_step_size = lot_step_size_option.unwrap().stepsize; +// let quote_commission_precision = quote_commission_precision_option +// .unwrap() +// .quote_commission_precision; +// let base_qty_to_be_ordered = +// element.base_qty_fee_adjusted.round_dp_with_strategy( +// lot_step_size.normalize().scale(), +// RoundingStrategy::ToZero, +// ); - if is_sell == true { - // let mut sell_price_ahead: Decimal = Decimal::new(14, 8); - // sell_price_ahead = decimal_mul(decimal_add(decimal_mul(decimal_mul(rust_decimal::Decimal::from_f64(element.pure_profit_percent).unwrap(), dec!(0.01)), dec!(0.97)), dec!(1)), element.buy_price).round_dp_with_strategy(2, RoundingStrategy::ToZero); - limit_order_sell( - &element, - element.current_price, - base_qty_to_be_ordered, - &client, - &exchange_info_vec, - &trade_fee_vec, - ) - .await; - } - } else { - let mut is_sell = false; - if element.pure_profit_percent <= target_profit_percent(-2.5) - 0.2 - // -0.2 means about total trade fees. - { - println!( - "Selling {} -250% target_profit_percent: {:.3}", - element.symbol, element.pure_profit_percent - ); - is_sell = true; - } else if element.pure_profit_percent <= -5.0 { - println!("selling {} -5.0% profit", element.symbol); - is_sell = true; - } +// let mut opclo_30m_vec = all_data.rt_price_30m_vec[opclo_30m_option.unwrap()] +// .1 +// .clone(); - if is_sell == true { - limit_order_sell( - &element, - element.current_price, - base_qty_to_be_ordered, - &client, - &exchange_info_vec, - &trade_fee_vec, - ) - .await; - } - } - } - } - } - } - } +// opclo_30m_vec.pop(); +// opclo_30m_vec.reverse(); +// let mut opclo_sample_length: usize = 50; // 50 candle samsples +// let nbr_of_exclusive: usize = 5; +// opclo_30m_vec.truncate(opclo_sample_length); +// opclo_30m_vec.sort_by(|a, b| { +// (a.high_price - a.low_price).total_cmp(&(b.high_price - b.low_price)) +// }); +// opclo_30m_vec.truncate(opclo_sample_length - nbr_of_exclusive); +// opclo_sample_length -= nbr_of_exclusive; - Ok(()) -} +// let mut sum_amplitude_candles = 0.0; +// let mut sum_ratio_amp_body = 0.0; +// for element in &opclo_30m_vec { +// sum_amplitude_candles += +// ((element.high_price / element.low_price) - 1.0) * 100.0; +// sum_ratio_amp_body += (element.close_price - element.open_price).abs() +// / (element.high_price - element.low_price); +// } +// let average_amplitude = sum_amplitude_candles / opclo_sample_length as f64; // percent unit +// let average_ratio_amp_body = sum_ratio_amp_body / opclo_sample_length as f64; + +// let mut amplitude_variance = 0.0; +// for element in &opclo_30m_vec { +// amplitude_variance += ((((element.high_price / element.low_price) - 1.0) +// * 100.0) +// - average_amplitude) +// .powi(2); +// } +// amplitude_variance = amplitude_variance / (opclo_sample_length - 1) as f64; +// let standard_deviation_amplitude = amplitude_variance.sqrt(); + +// // let target_profit_percent = average_amplitude + (standard_deviation_amplitude * (average_ratio_amp_body)); +// let target_profit_percent = |multiplier: f64| -> f64 { +// if multiplier < 0.0 { +// ((average_amplitude) * multiplier) +// - (standard_deviation_amplitude * 2.0) // 2.0 sigma (recommand: 0.5 ~ 2.0(patient & greedy)) +// } else { +// ((average_amplitude) * multiplier) +// + (standard_deviation_amplitude * 2.0) // 2.0 sigma (recommand: 0.5 ~ 2.0(patient & greedy)) +// } +// }; + +// if element.is_long == 0 || element.is_long == 1 { +// if element.pure_profit_percent >= 0.0 { +// let mut is_sell = false; +// if element.maximum_profit_percent >= target_profit_percent(5.0) + 0.2 +// && element.pure_profit_percent >= target_profit_percent(5.0) + 0.2 +// { +// println!( +// "Selling {} 500% target_profit_percent: {:.3}", +// element.symbol, element.pure_profit_percent +// ); +// is_sell = true; +// } else if element.pure_profit_percent >= 7.0 { +// println!("Selling {} 7% profit_percent", element.symbol); +// is_sell = true; +// } + +// if is_sell == true { +// // let mut sell_price_ahead: Decimal = Decimal::new(14, 8); +// // sell_price_ahead = decimal_mul(decimal_add(decimal_mul(decimal_mul(rust_decimal::Decimal::from_f64(element.pure_profit_percent).unwrap(), dec!(0.01)), dec!(0.97)), dec!(1)), element.buy_price).round_dp_with_strategy(2, RoundingStrategy::ToZero); +// limit_order_sell( +// &element, +// element.current_price, +// base_qty_to_be_ordered, +// &client, +// &exchange_info_vec, +// &trade_fee_vec, +// ) +// .await; +// } +// } else { +// let mut is_sell = false; +// if element.pure_profit_percent <= target_profit_percent(-2.5) - 0.2 +// // -0.2 means about total trade fees. +// { +// println!( +// "Selling {} -250% target_profit_percent: {:.3}", +// element.symbol, element.pure_profit_percent +// ); +// is_sell = true; +// } else if element.pure_profit_percent <= -5.0 { +// println!("selling {} -5.0% profit", element.symbol); +// is_sell = true; +// } + +// if is_sell == true { +// limit_order_sell( +// &element, +// element.current_price, +// base_qty_to_be_ordered, +// &client, +// &exchange_info_vec, +// &trade_fee_vec, +// ) +// .await; +// } +// } +// } +// } +// } +// } +// } + +// Ok(()) +// } diff --git a/src/strategy_team/strategy_004.rs b/src/strategy_team/strategy_004.rs index d41dc8f..1771277 100644 --- a/src/strategy_team/strategy_004.rs +++ b/src/strategy_team/strategy_004.rs @@ -1,13 +1,13 @@ use super::{ - dec, ema, exists_record, limit_order_sell, rsi, select_filled_buy_orders, stoch_rsi, - supertrend, try_join_all, AllData, Arc, Client, ClientBuilder, EmaData, ExchangeInfo, Mutex, - RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SupertrendData, TradeFee, - insert_pre_suggested_coins, Decimal, FilteredData, decimal_add, decimal_sub + 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 }; // Triple SuperTrend strategy -// SuperTrend length: 10, multiplier: 5, already up area // SuperTrend length: 10, multiplier: 3, already up area +// SuperTrend length: 10, multiplier: 2, already up area // SuperTrend length: 10, multiplier: 1.2, buy signal pub async fn list_up_for_buy( alldata: AllData, @@ -59,32 +59,33 @@ pub async fn list_up_for_buy( && inspect_result_4 == false { let mut filtered_data_1st_lock = filtered_data_1st_arc_c.lock().await; - + filtered_data.symbol = symbol_c; - + filtered_data_1st_lock.push(filtered_data); } })); } try_join_all(task_vec).await?; - // 2nd filtering: supertrend(ATR period 10, multiplier: 5.0, 30m close price), the area should be in UP area. + // 2nd filtering: supertrend(ATR period 10, multiplier: 1.5, 30m close price), signal should be BUY let filtered_data_1st = filtered_data_1st_arc.lock().await.clone(); let mut filtered_data_2nd: Vec = Vec::new(); let mut filtered_data_2nd_arc: Arc>> = Arc::new(Mutex::new(filtered_data_2nd)); let mut task_vec = Vec::new(); - + for element in filtered_data_1st { let mut rt_30m_vec: Vec = Vec::new(); let mut supertrend_vec: Vec = Vec::new(); let rt_price_30m_vec_c = alldata.rt_price_30m_vec.clone(); let filtered_data_2nd_arc_c = Arc::clone(&filtered_data_2nd_arc); task_vec.push(tokio::spawn(async move { - let mut filtered_data = FilteredData::new(); - let rt_30m_option = rt_price_30m_vec_c.iter().position(|x| *x.0 == element.symbol); + let rt_30m_option = rt_price_30m_vec_c + .iter() + .position(|x| *x.0 == element.symbol); let supertrend_option_30m = - supertrend(&element.symbol, &rt_price_30m_vec_c, 10, 5.0, true).await; + supertrend(&element.symbol, &rt_price_30m_vec_c, 10, 1.5, true).await; if rt_30m_option.is_some() && supertrend_option_30m.is_some() { rt_30m_vec = rt_price_30m_vec_c[rt_30m_option.unwrap()].1.clone(); @@ -101,18 +102,29 @@ pub async fn list_up_for_buy( }| *close_time, ); if supertrend_search_result.is_ok() { - if supertrend_vec[supertrend_search_result.unwrap()] - .area - .contains("UP") + let current_price: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(rt_30m_vec.last().unwrap().close_price).unwrap(); + + if supertrend_vec[supertrend_search_result.unwrap()].signal.as_ref().is_some_and(|x| x.contains("BUY")) + && current_price + < rust_decimal::prelude::FromPrimitive::from_f64( + supertrend_vec[supertrend_search_result.unwrap()-1].band_value * 1.002, + ) + .unwrap() + && supertrend_vec[supertrend_search_result.unwrap()-1].band_value > supertrend_vec[supertrend_search_result.unwrap()].band_value { - let mut filtered_data_2nd_lock = - filtered_data_2nd_arc_c.lock().await; - + let mut filtered_data_2nd_lock = filtered_data_2nd_arc_c.lock().await; + let mut filtered_data = FilteredData::new(); filtered_data.symbol = element.symbol.clone(); filtered_data.closetime = rt_30m_vec.last().unwrap().close_time; - filtered_data.current_price = rust_decimal::prelude::FromPrimitive::from_f64(rt_30m_vec.last().unwrap().close_price).unwrap(); - filtered_data_2nd_lock - .push(filtered_data); + filtered_data.current_price = current_price; + filtered_data.stoploss = rust_decimal::prelude::FromPrimitive::from_f64(supertrend_vec[supertrend_search_result.unwrap()].band_value).unwrap(); + let target_price = decimal_add( + filtered_data.current_price, + decimal_sub(filtered_data.current_price, filtered_data.stoploss), + ); + filtered_data.target_price = target_price; + + filtered_data_2nd_lock.push(filtered_data); } } } @@ -121,7 +133,7 @@ pub async fn list_up_for_buy( } try_join_all(task_vec).await?; - // 3rd filtering: supertrend(ATR period 10, multiplier: 3.0, 30m close price), the area should be in UP area. + // 3rd filtering: supertrend(ATR period 50, multiplier: 4.0, 30m close price), the area should be in UP area. let filtered_data_2nd = filtered_data_2nd_arc.lock().await.clone(); let mut filtered_data_3rd: Vec = Vec::new(); let mut filtered_data_3rd_arc: Arc>> = @@ -134,9 +146,8 @@ pub async fn list_up_for_buy( let rt_price_30m_vec_c = alldata.rt_price_30m_vec.clone(); let filtered_data_3rd_arc_c = Arc::clone(&filtered_data_3rd_arc); task_vec.push(tokio::spawn(async move { - let mut filtered_data = FilteredData::new(); let supertrend_option_30m = - supertrend(&element.symbol, &rt_price_30m_vec_c, 10, 3.0, true).await; + supertrend(&element.symbol, &rt_price_30m_vec_c, 50, 4.0, true).await; if supertrend_option_30m.is_some() { supertrend_vec = supertrend_option_30m.unwrap(); @@ -158,13 +169,14 @@ pub async fn list_up_for_buy( { let mut filtered_3rd_symbols_lock = filtered_data_3rd_arc_c.lock().await; - + let mut filtered_data = FilteredData::new(); filtered_data.symbol = element.symbol.clone(); filtered_data.closetime = element.closetime; filtered_data.current_price = element.current_price; - - filtered_3rd_symbols_lock - .push(filtered_data); + filtered_data.stoploss = element.stoploss; + filtered_data.target_price = element.target_price; + + filtered_3rd_symbols_lock.push(filtered_data); } } } @@ -173,7 +185,7 @@ pub async fn list_up_for_buy( } try_join_all(task_vec).await?; - // 4th filtering: supertrend(ATR period 10, multiplier: 1.2, 30m close price), the area should be in UP area. + // 5th filtering: supertrend(ATR period 10, multiplier: 1.2, 30m close price), the area should be UP // set stoploss and target_price let filtered_data_3rd_c = filtered_data_3rd_arc.lock().await.clone(); let mut filtered_data_4th: Vec = Vec::new(); @@ -184,11 +196,11 @@ pub async fn list_up_for_buy( let mut supertrend_vec: Vec = Vec::new(); let rt_price_30m_vec_c = alldata.rt_price_30m_vec.clone(); let filtered_data_4th_arc_c = Arc::clone(&filtered_data_4th_arc); - + task_vec.push(tokio::spawn(async move { let supertrend_option_30m = supertrend(&element.symbol, &rt_price_30m_vec_c, 10, 1.2, true).await; - let mut filtered_data = FilteredData::new(); + if supertrend_option_30m.is_some() { supertrend_vec = supertrend_option_30m.unwrap(); @@ -203,24 +215,20 @@ pub async fn list_up_for_buy( }| *close_time, ); if supertrend_search_result.is_ok() { - let supertrend_prev_element = supertrend_vec[supertrend_search_result.unwrap()-1].clone(); - let supertrend_element = supertrend_vec[supertrend_search_result.unwrap()].clone(); - if supertrend_element.signal.is_some_and(|x| x.contains("BUY")) - && element.current_price < rust_decimal::prelude::FromPrimitive::from_f64(supertrend_prev_element.band_value * 1.003).unwrap() - { - let mut filtered_data_4th_lock = - filtered_data_4th_arc_c.lock().await; - + if supertrend_vec[supertrend_search_result.unwrap()] + .area + .contains("UP") + { + let mut filtered_data_4th_lock = filtered_data_4th_arc_c.lock().await; + let mut filtered_data = FilteredData::new(); filtered_data.symbol = element.symbol.clone(); filtered_data.closetime = element.closetime; filtered_data.current_price = element.current_price; - filtered_data.stoploss = rust_decimal::prelude::FromPrimitive::from_f64(supertrend_element.band_value).unwrap(); - let target_price = decimal_add(element.current_price, decimal_sub(element.current_price, filtered_data.stoploss)); - filtered_data.target_price = target_price; + filtered_data.stoploss = element.stoploss; + filtered_data.target_price = element.target_price; - filtered_data_4th_lock - .push(filtered_data); - } + filtered_data_4th_lock.push(filtered_data); + } } } } @@ -228,9 +236,91 @@ pub async fn list_up_for_buy( } try_join_all(task_vec).await?; - let final_filtered_data = filtered_data_4th_arc.lock().await.clone(); - insert_pre_suggested_coins(4, false, &final_filtered_data, &alldata).await; + // 4th filtering: StochRSI (RSI length: 3, Stoch length: 3, smooth k: 3, smooth d: 3) 80 > k > kn-1 + let filtered_4th_symbol_c = filtered_data_4th_arc.lock().await.clone(); + let mut rsi10_1d_data: Vec<(String, Vec)> = + rsi(3, &alldata.rt_price_1d_vec, &filtered_4th_symbol_c).await?; + let stoch_rsi_data = stoch_rsi(&rsi10_1d_data, 3, 3, 3).await?; + let mut stoch_rsi3_1d_vec: Vec = Vec::new(); + let mut filtered_data_5th: Vec = Vec::new(); + let mut filtered_data_5th_arc: Arc>> = + Arc::new(Mutex::new(filtered_data_5th)); + let mut task_vec = Vec::new(); + for element in filtered_4th_symbol_c { + let stoch_rsi3_1d_option = stoch_rsi_data.iter().position(|x| *x.0 == element.symbol); + let filtered_data_5th_arc_c = Arc::clone(&filtered_data_5th_arc); + if stoch_rsi3_1d_option.is_some() { + stoch_rsi3_1d_vec = stoch_rsi_data[stoch_rsi3_1d_option.unwrap()].1.clone(); + + if stoch_rsi3_1d_vec.len() >= 3 { + task_vec.push(tokio::spawn(async move { + let stoch_rsi_search_result = stoch_rsi3_1d_vec + .binary_search_by_key(&element.closetime, |&StochRsiData { k, d, close_time }| { + close_time + }); + if stoch_rsi_search_result.is_ok() { + if 95.0 >= stoch_rsi3_1d_vec[stoch_rsi_search_result.unwrap()].k + && stoch_rsi3_1d_vec[stoch_rsi_search_result.unwrap()].k + > stoch_rsi3_1d_vec[stoch_rsi_search_result.unwrap() - 1].k + && stoch_rsi3_1d_vec[stoch_rsi_search_result.unwrap()].k + > stoch_rsi3_1d_vec[stoch_rsi_search_result.unwrap()].d + { + let mut filtered_data_5th_lock = filtered_data_5th_arc_c.lock().await; + let mut filtered_data = FilteredData::new(); + filtered_data.symbol = element.symbol.clone(); + filtered_data.closetime = element.closetime; + filtered_data.current_price = element.current_price; + filtered_data.stoploss = element.stoploss; + filtered_data.target_price = element.target_price; + + filtered_data_5th_lock.push(filtered_data); + } + } + })); + } + } + } + + // 6th filtertering: coefficient-of-variation 0.5<= CV <= 1.0 + // 20개 amplitude 기준 CV 계산 + + // // 6th filtering: Avoid high volatility + // let filtered_data_5th_c = filtered_data_5th_arc.lock().await.clone(); + // let mut filtered_data_6th: Vec = Vec::new(); + // let mut filtered_data_6th_arc: Arc>> = + // Arc::new(Mutex::new(filtered_data_6th)); + // let mut task_vec = Vec::new(); + // for element in filtered_data_5th_c { + // let mut supertrend_vec: Vec = Vec::new(); + // let rt_price_30m_vec_c = alldata.rt_price_30m_vec.clone(); + // let filtered_data_6th_arc_c = Arc::clone(&filtered_data_5th_arc); + + // task_vec.push(tokio::spawn(async move { + // let mut filtered_data = FilteredData::new(); + // if rt_price_30m_vec_c.len() >= 50 { + + + // let mut filtered_data_5th_lock = filtered_data_6th_arc_c.lock().await; + + // filtered_data.symbol = element.symbol.clone(); + // filtered_data.closetime = element.closetime; + // filtered_data.current_price = element.current_price; + // filtered_data.stoploss = element.stoploss; + // filtered_data.target_price = element.target_price; + + // filtered_data_5th_lock.push(filtered_data); + + + + // } + // })); + // } + // try_join_all(task_vec).await?; + + let final_filtered_data = filtered_data_5th_arc.lock().await.clone(); + insert_pre_suggested_coins(4, false, &final_filtered_data, &alldata).await; + Ok(()) } @@ -246,10 +336,9 @@ pub async fn list_up_for_sell( .timeout(tokio::time::Duration::from_millis(5000)) .build() .unwrap(); - + let mut supertrend_vec: Vec = Vec::new(); for element in filled_buy_orders { if element.used_usdt >= dec!(10.0) { - let lot_step_size_option = exchange_info_vec .iter() .position(|exchange_info| exchange_info.symbol == element.symbol); @@ -261,35 +350,49 @@ pub async fn list_up_for_sell( .rt_price_30m_vec .iter() .position(|x| *x.0 == element.symbol); + let supertrend_option_30m = + supertrend(&element.symbol, &all_data.rt_price_30m_vec, 10, 1.5, true).await; if lot_step_size_option.is_some() && quote_commission_precision_option.is_some() && opclo_30m_option.is_some() + && supertrend_option_30m.is_some() { + // update stoploss + supertrend_vec = supertrend_option_30m.unwrap(); + let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(supertrend_vec.last().unwrap().band_value).unwrap(); + if supertrend_vec.last().unwrap().area.contains("UP") + && band_value > element.stoploss { + let update_table_name = String::from("buy_ordered_coin_list"); + let update_value = vec![ + (String::from("stoploss"), band_value.to_string()), + ]; + let update_condition = vec![(String::from("id"), element.id.to_string())]; + update_record3(&update_table_name, &update_value, &update_condition) + .await + .unwrap(); + } + let lot_step_size = exchange_info_vec[lot_step_size_option.unwrap()].stepsize; - let quote_commission_precision = exchange_info_vec[quote_commission_precision_option - .unwrap()] - .quote_commission_precision; + let quote_commission_precision = exchange_info_vec + [quote_commission_precision_option.unwrap()] + .quote_commission_precision; let base_qty_to_be_ordered = - element.base_qty_fee_adjusted.round_dp_with_strategy( + element.base_qty_ordered.round_dp_with_strategy( lot_step_size.normalize().scale(), RoundingStrategy::ToZero, ); - if (element.is_long == 0 || element.is_long == 1) && !element.current_price.is_zero() { - if element.current_price >= element.target_price && element.pure_profit_percent >= 0.1 { - println!("target selling {} {:.2}", element.symbol, element.pure_profit_percent); - limit_order_sell( - &element, - element.current_price, - base_qty_to_be_ordered, - &client, - &exchange_info_vec, - &trade_fee_vec, - ) - .await; - } else if element.current_price <= element.stoploss { - println!("stoploss selling {} {:.2}", element.symbol, element.pure_profit_percent); + if (element.is_long == 0 || element.is_long == 1) + && !element.current_price.is_zero() + { + if element.current_price >= element.target_price + && element.pure_profit_percent >= 0.1 + { + println!( + "target selling {} {:.2}", + element.symbol, element.pure_profit_percent + ); limit_order_sell( &element, element.current_price, @@ -299,7 +402,45 @@ pub async fn list_up_for_sell( &trade_fee_vec, ) .await; - } + } else if element.current_price <= element.stoploss { + println!( + "stoploss selling {} {:.2}", + element.symbol, element.pure_profit_percent + ); + limit_order_sell( + &element, + element.current_price, + base_qty_to_be_ordered, + &client, + &exchange_info_vec, + &trade_fee_vec, + ) + .await; + } + // TODO: sell_count가 1일 때 적용하기 + // else if (supertrend_vec + // .last() + // .unwrap() + // .signal + // .as_ref() + // .is_some_and(|x| x.contains("SELL")) + // || supertrend_vec.last().unwrap().area.contains("DOWN")) + // && (supertrend_vec.last().unwrap().close_time > element.close_time) + // { + // println!( + // "SELL signal selling {} {:.2}", + // element.symbol, element.pure_profit_percent + // ); + // limit_order_sell( + // &element, + // element.current_price, + // base_qty_to_be_ordered, + // &client, + // &exchange_info_vec, + // &trade_fee_vec, + // ) + // .await; + // } } } } @@ -307,4 +448,4 @@ pub async fn list_up_for_sell( } Ok(()) -} \ No newline at end of file +} diff --git a/src/strategy_team/strategy_manager.rs b/src/strategy_team/strategy_manager.rs index 7bd05fb..51d4686 100644 --- a/src/strategy_team/strategy_manager.rs +++ b/src/strategy_team/strategy_manager.rs @@ -7,8 +7,8 @@ use rust_decimal::Decimal; use serde::Deserialize; use super::{ - exists_record, insert_one_record, try_select_record, AllData, ExchangeInfo, FromRow, - RealtimePriceData, TradeFee, FilteredData, try_join_all + exists_record, insert_one_record, try_join_all, try_select_record, AllData, ExchangeInfo, + FilteredData, FromRow, RealtimePriceData, TradeFee, }; use crate::signal_association::signal_decision::*; use tokio::time::{sleep, Duration, Instant}; @@ -55,7 +55,6 @@ pub async fn execute_list_up_for_sell( exchange_info_vec: &Vec, trade_fee_vec: &Vec, ) -> Result<(), Box> { - crate::strategy_team::strategy_004::list_up_for_sell( all_data, exchange_info_vec, @@ -196,17 +195,17 @@ pub async fn insert_pre_suggested_coins( if is_dupe == false { let mut insert_values = vec![ - filtered_coin.symbol.clone(), // symbol - filtered_coin.closetime.to_string(), // close_time - filtered_coin.current_price.to_string(), // suggested_price - filtered_coin.current_price.to_string(), // current_price - filtered_coin.stoploss.to_string(), // stoploss - filtered_coin.target_price.to_string(), // target_price - server_epoch().await.to_string(), // registered_server_epoch - 0.0.to_string(), // profit_percent - 0.0.to_string(), // minimum_profit_percent - 0.0.to_string(), // maximum_profit_percent - registerer.to_string(), // registerer + filtered_coin.symbol.clone(), // symbol + filtered_coin.closetime.to_string(), // close_time + filtered_coin.current_price.to_string(), // suggested_price + filtered_coin.current_price.to_string(), // current_price + filtered_coin.stoploss.to_string(), // stoploss + filtered_coin.target_price.to_string(), // target_price + server_epoch().await.to_string(), // registered_server_epoch + 0.0.to_string(), // profit_percent + 0.0.to_string(), // minimum_profit_percent + 0.0.to_string(), // maximum_profit_percent + registerer.to_string(), // registerer ]; if is_long == true { @@ -282,17 +281,17 @@ pub async fn insert_pre_suggested_coins( if is_dupe == false { let mut insert_values = vec![ - filtered_coin.symbol.clone(), // symbol - filtered_coin.closetime.to_string(), // close_time - filtered_coin.current_price.to_string(), // suggested_price - filtered_coin.current_price.to_string(), // current_price - filtered_coin.stoploss.to_string(), // stoploss - filtered_coin.target_price.to_string(), // target_price - server_epoch().await.to_string(), // registered_server_epoch - 0.0.to_string(), // profit_percent - 0.0.to_string(), // minimum_profit_percent - 0.0.to_string(), // maximum_profit_percent - registerer.to_string(), // registerer + filtered_coin.symbol.clone(), // symbol + filtered_coin.closetime.to_string(), // close_time + filtered_coin.current_price.to_string(), // suggested_price + filtered_coin.current_price.to_string(), // current_price + filtered_coin.stoploss.to_string(), // stoploss + filtered_coin.target_price.to_string(), // target_price + server_epoch().await.to_string(), // registered_server_epoch + 0.0.to_string(), // profit_percent + 0.0.to_string(), // minimum_profit_percent + 0.0.to_string(), // maximum_profit_percent + registerer.to_string(), // registerer ]; if is_long == true { @@ -358,17 +357,17 @@ pub async fn insert_pre_suggested_coins( if is_dupe == false { let mut insert_values = vec![ - filtered_coin.symbol.clone(), // symbol - filtered_coin.closetime.to_string(), // close_time - filtered_coin.current_price.to_string(), // suggested_price - filtered_coin.current_price.to_string(), // current_price - filtered_coin.stoploss.to_string(), // stoploss - filtered_coin.target_price.to_string(), // target_price - server_epoch().await.to_string(), // registered_server_epoch - 0.0.to_string(), // profit_percent - 0.0.to_string(), // minimum_profit_percent - 0.0.to_string(), // maximum_profit_percent - registerer.to_string(), // registerer + filtered_coin.symbol.clone(), // symbol + filtered_coin.closetime.to_string(), // close_time + filtered_coin.current_price.to_string(), // suggested_price + filtered_coin.current_price.to_string(), // current_price + filtered_coin.stoploss.to_string(), // stoploss + filtered_coin.target_price.to_string(), // target_price + server_epoch().await.to_string(), // registered_server_epoch + 0.0.to_string(), // profit_percent + 0.0.to_string(), // minimum_profit_percent + 0.0.to_string(), // maximum_profit_percent + registerer.to_string(), // registerer ]; if is_long == true { @@ -418,17 +417,17 @@ pub async fn insert_pre_suggested_coins( if is_dupe == false { let mut insert_values = vec![ - filtered_coin.symbol.clone(), // symbol - filtered_coin.closetime.to_string(), // close_time - filtered_coin.current_price.to_string(), // suggested_price - filtered_coin.current_price.to_string(), // current_price - filtered_coin.stoploss.to_string(), // stoploss - filtered_coin.target_price.to_string(), // target_price - server_epoch().await.to_string(), // registered_server_epoch - 0.0.to_string(), // profit_percent - 0.0.to_string(), // minimum_profit_percent - 0.0.to_string(), // maximum_profit_percent - registerer.to_string(), // registerer + filtered_coin.symbol.clone(), // symbol + filtered_coin.closetime.to_string(), // close_time + filtered_coin.current_price.to_string(), // suggested_price + filtered_coin.current_price.to_string(), // current_price + filtered_coin.stoploss.to_string(), // stoploss + filtered_coin.target_price.to_string(), // target_price + server_epoch().await.to_string(), // registered_server_epoch + 0.0.to_string(), // profit_percent + 0.0.to_string(), // minimum_profit_percent + 0.0.to_string(), // maximum_profit_percent + registerer.to_string(), // registerer ]; if is_long == true { @@ -504,17 +503,17 @@ pub async fn insert_pre_suggested_coins( if is_dupe == false { let mut insert_values = vec![ - filtered_coin.symbol.clone(), // symbol - filtered_coin.closetime.to_string(), // close_time - filtered_coin.current_price.to_string(), // suggested_price - filtered_coin.current_price.to_string(), // current_price - filtered_coin.stoploss.to_string(), // stoploss - filtered_coin.target_price.to_string(), // target_price - server_epoch().await.to_string(), // registered_server_epoch - 0.0.to_string(), // profit_percent - 0.0.to_string(), // minimum_profit_percent - 0.0.to_string(), // maximum_profit_percent - registerer.to_string(), // registerer + filtered_coin.symbol.clone(), // symbol + filtered_coin.closetime.to_string(), // close_time + filtered_coin.current_price.to_string(), // suggested_price + filtered_coin.current_price.to_string(), // current_price + filtered_coin.stoploss.to_string(), // stoploss + filtered_coin.target_price.to_string(), // target_price + server_epoch().await.to_string(), // registered_server_epoch + 0.0.to_string(), // profit_percent + 0.0.to_string(), // minimum_profit_percent + 0.0.to_string(), // maximum_profit_percent + registerer.to_string(), // registerer ]; if is_long == true { @@ -574,17 +573,17 @@ pub async fn insert_pre_suggested_coins( if is_dupe == false { let mut insert_values = vec![ - filtered_coin.symbol.clone(), // symbol - filtered_coin.closetime.to_string(), // close_time - filtered_coin.current_price.to_string(), // suggested_price - filtered_coin.current_price.to_string(), // current_price - filtered_coin.stoploss.to_string(), // stoploss - filtered_coin.target_price.to_string(), // target_price - server_epoch().await.to_string(), // registered_server_epoch - 0.0.to_string(), // profit_percent - 0.0.to_string(), // minimum_profit_percent - 0.0.to_string(), // maximum_profit_percent - registerer.to_string(), // registerer + filtered_coin.symbol.clone(), // symbol + filtered_coin.closetime.to_string(), // close_time + filtered_coin.current_price.to_string(), // suggested_price + filtered_coin.current_price.to_string(), // current_price + filtered_coin.stoploss.to_string(), // stoploss + filtered_coin.target_price.to_string(), // target_price + server_epoch().await.to_string(), // registered_server_epoch + 0.0.to_string(), // profit_percent + 0.0.to_string(), // minimum_profit_percent + 0.0.to_string(), // maximum_profit_percent + registerer.to_string(), // registerer ]; if is_long == true { @@ -634,17 +633,17 @@ pub async fn insert_pre_suggested_coins( if is_dupe == false { let mut insert_values = vec![ - filtered_coin.symbol.clone(), // symbol - filtered_coin.closetime.to_string(), // close_time - filtered_coin.current_price.to_string(), // suggested_price - filtered_coin.current_price.to_string(), // current_price - filtered_coin.stoploss.to_string(), // stoploss - filtered_coin.target_price.to_string(), // target_price - server_epoch().await.to_string(), // registered_server_epoch - 0.0.to_string(), // profit_percent - 0.0.to_string(), // minimum_profit_percent - 0.0.to_string(), // maximum_profit_percent - registerer.to_string(), // registerer + filtered_coin.symbol.clone(), // symbol + filtered_coin.closetime.to_string(), // close_time + filtered_coin.current_price.to_string(), // suggested_price + filtered_coin.current_price.to_string(), // current_price + filtered_coin.stoploss.to_string(), // stoploss + filtered_coin.target_price.to_string(), // target_price + server_epoch().await.to_string(), // registered_server_epoch + 0.0.to_string(), // profit_percent + 0.0.to_string(), // minimum_profit_percent + 0.0.to_string(), // maximum_profit_percent + registerer.to_string(), // registerer ]; if is_long == true { @@ -659,18 +658,18 @@ pub async fn insert_pre_suggested_coins( } else { for filtered_coin in filtered_coins { let mut insert_values = vec![ - filtered_coin.symbol.clone(), // symbol - filtered_coin.closetime.to_string(), // close_time - filtered_coin.current_price.to_string(), // suggested_price - filtered_coin.current_price.to_string(), // current_price - filtered_coin.stoploss.to_string(), // stoploss - filtered_coin.target_price.to_string(), // target_price - server_epoch().await.to_string(), // registered_server_epoch - 0.0.to_string(), // profit_percent - 0.0.to_string(), // minimum_profit_percent - 0.0.to_string(), // maximum_profit_percent - registerer.to_string(), // registerer - ]; + filtered_coin.symbol.clone(), // symbol + filtered_coin.closetime.to_string(), // close_time + filtered_coin.current_price.to_string(), // suggested_price + filtered_coin.current_price.to_string(), // current_price + filtered_coin.stoploss.to_string(), // stoploss + filtered_coin.target_price.to_string(), // target_price + server_epoch().await.to_string(), // registered_server_epoch + 0.0.to_string(), // profit_percent + 0.0.to_string(), // minimum_profit_percent + 0.0.to_string(), // maximum_profit_percent + registerer.to_string(), // registerer + ]; if is_long == true { insert_values.push(1.to_string()); // is_long