diff --git a/src/strategy_team/future_strategy_long.rs b/src/strategy_team/future_strategy_long.rs index 09c9a5d..2934a9c 100644 --- a/src/strategy_team/future_strategy_long.rs +++ b/src/strategy_team/future_strategy_long.rs @@ -9,7 +9,7 @@ use super::{ FilteredDataValue, HashMap, HashSet, HeatMapLevel, HeatmapVolumeData, MacdData, Mutex, RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SuperTrendArea, SuperTrendSignal, SupertrendData, TemaData, ToPrimitive, TradeFee, WiliamsPercentR, future_duplicate_filter, insert_future_coins, get_current_price_decimal, - sma, sma_open + sma, sma_open, LrData, linear_regression }; use crate::future::{Position, FuturesExchangeInfo}; @@ -31,52 +31,21 @@ pub async fn list_up_for_buy( filtered_data.insert(symbol.clone(), FilteredDataValue::new()); } - // sma3_close(current) > sma3_open (current), sma3_close(prev) < sma3_open (prev) - let mut keys_to_remove: HashSet = HashSet::new(); - let ema10_open = ema_open(5, &alldata.rt_price_30m_vec, &filtered_data).await?; - let ema10_close = ema(5, &alldata.rt_price_30m_vec, &filtered_data).await?; - let ema200_close = ema(200, &alldata.rt_price_30m_vec, &filtered_data).await?; let server_epoch = get_server_epoch().await; - for (symbol, values) in &mut filtered_data { - let mut do_buy = false; - let price_and_closetime = get_current_price_decimal(&symbol, &alldata.rt_price_30m_vec).await; - if let (Some(ema10_open_vec), Some(ema10_close_vec), Some(ema200_close_vec), Some(current_info)) - = (ema10_open.get(symbol), ema10_close.get(symbol), ema200_close.get(symbol), price_and_closetime) { - if ema10_open_vec.len() > 20 - && ema10_close_vec.len() > 20 - && ema200_close_vec.len() > 20 - && ema10_open_vec.last().unwrap().close_time > server_epoch - && ema10_open_vec.last().unwrap().close_time == ema10_close_vec.last().unwrap().close_time - && ema10_open_vec.last().unwrap().close_time == ema200_close_vec.last().unwrap().close_time - { - if ema10_open_vec.last().unwrap().ema_value < ema10_close_vec.last().unwrap().ema_value - && current_info.0.to_f64().is_some_and(|a| a > ema200_close_vec.last().unwrap().ema_value) - { - values.current_price = current_info.0; - values.closetime = current_info.1; - do_buy = true; - } - } - } - if do_buy == false { - keys_to_remove.insert(symbol.clone()); - } - } - remove_keys(&mut filtered_data, keys_to_remove).await; - // current ADX(3, 3), current ADX > prev ADX + // current lr > prev lr, current r_squared <= 0.01 let mut keys_to_remove: HashSet = HashSet::new(); - let adx_vec = adx(3, 3, &alldata.rt_price_30m_vec, &filtered_data).await?; + let lr_map = linear_regression(10, 0, &alldata.rt_price_30m_vec, &filtered_data).await?; for (symbol, values) in &mut filtered_data { let mut do_buy = false; - if let Some(adx_vec) = adx_vec.get(symbol) { - if let Some(last_idx) = adx_vec.iter().position(|elem| elem.close_time == values.closetime) { - if adx_vec.len() > 10 - && adx_vec[last_idx].adx > adx_vec[last_idx-1].adx - { - do_buy = true; - } - } + if let (Some(lr_vec), Some(current_info)) = (lr_map.get(symbol), get_current_price_decimal(&symbol, &alldata.rt_price_30m_vec).await) { + if lr_vec.len() > 10 + && lr_vec.last().is_some_and(|x| x.close_time > server_epoch) + && lr_vec[lr_vec.len()-1].lr_value > lr_vec[lr_vec.len()-2].lr_value + && lr_vec.last().unwrap().r_squared <= 0.01 + { + do_buy = true; + } } if do_buy == false { keys_to_remove.insert(symbol.clone()); @@ -84,61 +53,114 @@ pub async fn list_up_for_buy( } remove_keys(&mut filtered_data, keys_to_remove).await; - // supertrend(ATR period 30, multiplier: 2.0, 30m close price) - let mut keys_to_remove: HashSet = HashSet::new(); - let supertrend_30m_map = - supertrend(100, 1.5, true, &alldata.rt_price_30m_vec, &filtered_data).await?; - for (symbol, values) in &mut filtered_data { - let mut do_buy = false; - if let Some(supertrend_vec) = supertrend_30m_map.get(symbol) - { - if supertrend_vec.len() > 10 - && supertrend_vec.last().is_some_and(|a| a.close_time == values.closetime) - && supertrend_vec.last().unwrap().area == SuperTrendArea::UP - && supertrend_vec[supertrend_vec.len()-2].area == SuperTrendArea::UP { - do_buy = true; - } - } + // sma3_close(current) > sma3_open (current), sma3_close(prev) < sma3_open (prev) + // let mut keys_to_remove: HashSet = HashSet::new(); + // let ema10_open = ema_open(5, &alldata.rt_price_30m_vec, &filtered_data).await?; + // let ema10_close = ema(5, &alldata.rt_price_30m_vec, &filtered_data).await?; + // let ema200_close = ema(200, &alldata.rt_price_30m_vec, &filtered_data).await?; + + // for (symbol, values) in &mut filtered_data { + // let mut do_buy = false; + // let price_and_closetime = get_current_price_decimal(&symbol, &alldata.rt_price_30m_vec).await; + // if let (Some(ema10_open_vec), Some(ema10_close_vec), Some(ema200_close_vec), Some(current_info)) + // = (ema10_open.get(symbol), ema10_close.get(symbol), ema200_close.get(symbol), price_and_closetime) { + // if ema10_open_vec.len() > 20 + // && ema10_close_vec.len() > 20 + // && ema200_close_vec.len() > 20 + // && ema10_open_vec.last().unwrap().close_time > server_epoch + // && ema10_open_vec.last().unwrap().close_time == ema10_close_vec.last().unwrap().close_time + // && ema10_open_vec.last().unwrap().close_time == ema200_close_vec.last().unwrap().close_time + // { + // if ema10_open_vec.last().unwrap().ema_value < ema10_close_vec.last().unwrap().ema_value + // && current_info.0.to_f64().is_some_and(|a| a > ema200_close_vec.last().unwrap().ema_value) + // { + // values.current_price = current_info.0; + // values.closetime = current_info.1; + // do_buy = true; + // } + // } + // } + // if do_buy == false { + // keys_to_remove.insert(symbol.clone()); + // } + // } + // remove_keys(&mut filtered_data, keys_to_remove).await; - if do_buy == false { - keys_to_remove.insert(symbol.clone()); - } - } - remove_keys(&mut filtered_data, keys_to_remove).await; + // current ADX(3, 3), current ADX > prev ADX + // let mut keys_to_remove: HashSet = HashSet::new(); + // let adx_vec = adx(3, 3, &alldata.rt_price_30m_vec, &filtered_data).await?; + // for (symbol, values) in &mut filtered_data { + // let mut do_buy = false; + // if let Some(adx_vec) = adx_vec.get(symbol) { + // if let Some(last_idx) = adx_vec.iter().position(|elem| elem.close_time == values.closetime) { + // if adx_vec.len() > 10 + // && adx_vec[last_idx].adx > adx_vec[last_idx-1].adx + // { + // do_buy = true; + // } + // } + // } + // if do_buy == false { + // keys_to_remove.insert(symbol.clone()); + // } + // } + // remove_keys(&mut filtered_data, keys_to_remove).await; + + // supertrend(ATR period 30, multiplier: 2.0, 30m close price) + // let mut keys_to_remove: HashSet = HashSet::new(); + // let supertrend_30m_map = + // supertrend(100, 1.5, true, &alldata.rt_price_30m_vec, &filtered_data).await?; + // for (symbol, values) in &mut filtered_data { + // let mut do_buy = false; + // if let Some(supertrend_vec) = supertrend_30m_map.get(symbol) + // { + // if supertrend_vec.len() > 10 + // && supertrend_vec.last().is_some_and(|a| a.close_time == values.closetime) + // && supertrend_vec.last().unwrap().area == SuperTrendArea::UP + // && supertrend_vec[supertrend_vec.len()-2].area == SuperTrendArea::UP { + // do_buy = true; + // } + // } + + // if do_buy == false { + // keys_to_remove.insert(symbol.clone()); + // } + // } + // remove_keys(&mut filtered_data, keys_to_remove).await; // set target_price and stop_loss - let mut keys_to_remove: HashSet = HashSet::new(); - for (symbol, values) in &mut filtered_data { - let mut do_buy = false; - if let Some(realtime_price_vec) = alldata.rt_price_30m_vec.get(symbol) - { - let element_number = 5; - if let Some(truncated_vec) = realtime_price_vec.get(realtime_price_vec.len()-element_number..) { - let min_price = truncated_vec - .iter() - .min_by(|x, y| x.low_price.partial_cmp(&y.low_price).unwrap()) - .unwrap().low_price; - if values.current_price.to_f64().is_some_and(|a| a < min_price) { - let mut stoploss_percent = ((values.current_price.to_f64().unwrap() - min_price) * 100.0) / values.current_price.to_f64().unwrap(); - stoploss_percent = (stoploss_percent * 100.0).floor() / 100.0; - values.stoploss = rust_decimal::prelude::FromPrimitive::from_f64(stoploss_percent).unwrap(); - let mut target_percent = stoploss_percent.abs() * 1.5; - target_percent = (target_percent * 100.0).floor() / 100.0; - values.target_price = rust_decimal::prelude::FromPrimitive::from_f64(target_percent).unwrap(); + // let mut keys_to_remove: HashSet = HashSet::new(); + // for (symbol, values) in &mut filtered_data { + // let mut do_buy = false; + // if let Some(realtime_price_vec) = alldata.rt_price_30m_vec.get(symbol) + // { + // let element_number = 5; + // if let Some(truncated_vec) = realtime_price_vec.get(realtime_price_vec.len()-element_number..) { + // let min_price = truncated_vec + // .iter() + // .min_by(|x, y| x.low_price.partial_cmp(&y.low_price).unwrap()) + // .unwrap().low_price; + // if values.current_price.to_f64().is_some_and(|a| a < min_price) { + // let mut stoploss_percent = ((values.current_price.to_f64().unwrap() - min_price) * 100.0) / values.current_price.to_f64().unwrap(); + // stoploss_percent = (stoploss_percent * 100.0).floor() / 100.0; + // values.stoploss = rust_decimal::prelude::FromPrimitive::from_f64(stoploss_percent).unwrap(); + // let mut target_percent = stoploss_percent.abs() * 1.5; + // target_percent = (target_percent * 100.0).floor() / 100.0; + // values.target_price = rust_decimal::prelude::FromPrimitive::from_f64(target_percent).unwrap(); - do_buy = true; + // do_buy = true; - } - } - } + // } + // } + // } - if do_buy == false { - keys_to_remove.insert(symbol.clone()); - } - } - remove_keys(&mut filtered_data, keys_to_remove).await; + // if do_buy == false { + // keys_to_remove.insert(symbol.clone()); + // } + // } + // remove_keys(&mut filtered_data, keys_to_remove).await; - // Wiliams -50.0 > %R(100) + // Wiliams -50 > %R(100) let mut keys_to_remove: HashSet = HashSet::new(); let mut wpr100_map = wiliams_percent_r(100, &alldata.rt_price_1m_vec, &filtered_data).await?; let server_epoch = get_server_epoch().await; @@ -147,7 +169,7 @@ pub async fn list_up_for_buy( if let Some(wpr100_vec) = wpr100_map.get(symbol) { if wpr100_vec.len() > 15 && wpr100_vec.last().unwrap().close_time > server_epoch - && wpr100_vec.last().unwrap().r_value < -40.0 { + && wpr100_vec.last().unwrap().r_value < -50.0 { do_buy = true; } } @@ -349,76 +371,77 @@ pub async fn list_up_for_sell(all_data: &AllData, futures_exchange_info_map: &Ha let server_epoch = get_server_epoch().await; - let mut supertrend_vec: Vec = Vec::new(); + // let mut supertrend_vec: Vec = Vec::new(); let mut filtered_symbols: HashMap = HashMap::new(); for element in &filled_positions { filtered_symbols.insert(element.symbol.clone(), FilteredDataValue::new()); } - let supertrend_30m_map = - supertrend(100, 1.5, true, &all_data.rt_price_30m_vec, &filtered_symbols).await?; + let lr_map = linear_regression(10, 0, &all_data.rt_price_30m_vec, &filtered_symbols).await?; + // let supertrend_30m_map = + // supertrend(100, 1.5, true, &all_data.rt_price_30m_vec, &filtered_symbols).await?; // let adx_vec = adx(15, 15, &all_data.rt_price_1m_vec, &filtered_symbols).await?; for element in filled_positions { let mut is_sell = false; - if !element.current_price.is_zero() { - if element.pure_profit_percent >= element.target_percent { - is_sell = true; - } else if element.pure_profit_percent <= element.stoploss_percent { - is_sell = true; - } else if server_epoch - element.close_time > 300_000 && supertrend_30m_map.get(&element.symbol).is_some_and(|a| a.len() > 10 && a.last().is_some_and(|b| b.close_time > server_epoch && b.area == SuperTrendArea::DOWN)) { - is_sell = true; - } - - let minimum_candles = 5; - let maximum_candles = 20; - for count_candles in minimum_candles..=maximum_candles { - if count_candles < maximum_candles - && server_epoch - element.transact_time - > (1_800_000) * count_candles - && ((element.pure_profit_percent > 0.0 - && element.target_percent - * ((maximum_candles - count_candles) as f64 - / (maximum_candles - minimum_candles + 1) as f64) - <= element.pure_profit_percent) - || - (element.pure_profit_percent < 0.0 - && element.stoploss_percent - * ((maximum_candles - count_candles) as f64 - / (maximum_candles - minimum_candles + 1) as f64) - >= element.pure_profit_percent) - ) - { + if let Some(lr_vec) = lr_map.get(&element.symbol) { + if !element.current_price.is_zero() && lr_vec.len() > 10 && lr_vec.last().is_some_and(|x| x.close_time > server_epoch) { + + if element.pure_profit_percent >= element.target_percent { is_sell = true; - break; - } else { - break; + } else if element.pure_profit_percent <= element.stoploss_percent { + is_sell = true; + } else if lr_vec.last().unwrap().r_squared >= 0.55 { + is_sell = true; + } + + let minimum_candles = 5; + let maximum_candles = 6; + // for count_candles in minimum_candles..=maximum_candles { + // if count_candles < maximum_candles + // && server_epoch - element.transact_time + // > (1_800_000) * count_candles + // && ((element.pure_profit_percent > 0.0 + // && element.target_percent + // * ((maximum_candles - count_candles) as f64 + // / (maximum_candles - minimum_candles + 1) as f64) + // <= element.pure_profit_percent) + // || + // (element.pure_profit_percent < 0.0 + // && element.stoploss_percent + // * ((maximum_candles - count_candles) as f64 + // / (maximum_candles - minimum_candles + 1) as f64) + // >= element.pure_profit_percent) + // ) + // { + // is_sell = true; + // break; + // } else { + // break; + // } + // } + + if server_epoch - element.close_time > 1_800_000 * maximum_candles { + is_sell = true; + } + + //} else if server_epoch - element.close_time > 300_000 + // && adx_vec.get(&element.symbol).is_some_and(|a| a.len() > 10 && a.last().is_some_and(|b| b.close_time > server_epoch && b.adx < 15.0)) { + // is_sell = true; + // } + + if is_sell == true { + limit_order_close( + &element, + TimeInForce::Gtc, + element.current_price, + element.base_qty_ordered, + &futures_exchange_info_map, + &client + ) + .await; } } - - if server_epoch - element.close_time > 1_800_000 * maximum_candles { - is_sell = true; - } - - //} else if server_epoch - element.close_time > 300_000 - // && adx_vec.get(&element.symbol).is_some_and(|a| a.len() > 10 && a.last().is_some_and(|b| b.close_time > server_epoch && b.adx < 15.0)) { - // is_sell = true; - // } - - if is_sell == true { - limit_order_close( - &element, - TimeInForce::Gtc, - element.current_price, - element.base_qty_ordered, - &futures_exchange_info_map, - &client - ) - .await; - } - } - - } - - + } + } Ok(()) } diff --git a/src/strategy_team/future_strategy_short.rs b/src/strategy_team/future_strategy_short.rs index 6a2b262..803dd91 100644 --- a/src/strategy_team/future_strategy_short.rs +++ b/src/strategy_team/future_strategy_short.rs @@ -33,20 +33,19 @@ pub async fn list_up_for_buy( let server_epoch = get_server_epoch().await; - // current ADX(3, 3), current ADX > prev ADX + // current lr < prev lr, current r_squared <= 0.01 let mut keys_to_remove: HashSet = HashSet::new(); - let lr_map = linear_regression(3, 0, &alldata.rt_price_30m_vec, &filtered_data).await?; + let lr_map = linear_regression(10, 0, &alldata.rt_price_30m_vec, &filtered_data).await?; for (symbol, values) in &mut filtered_data { let mut do_buy = false; - if let Some(lr_vec) = lr_map.get(symbol) { - println!("{}: {:?}", symbol, lr_vec); - // if let Some(last_idx) = lr_vec.iter().position(|elem| elem.close_time == values.closetime) { - // if lr_vec.len() > 10 - // && lr_vec[last_idx].adx > lr_vec[last_idx-1].adx - // { - // do_buy = true; - // } - // } + if let (Some(lr_vec), Some(current_info)) = (lr_map.get(symbol), get_current_price_decimal(&symbol, &alldata.rt_price_30m_vec).await) { + if lr_vec.len() > 10 + && lr_vec.last().is_some_and(|x| x.close_time > server_epoch) + && lr_vec[lr_vec.len()-1].lr_value < lr_vec[lr_vec.len()-2].lr_value + && lr_vec.last().unwrap().r_squared <= 0.01 + { + do_buy = true; + } } if do_buy == false { keys_to_remove.insert(symbol.clone()); @@ -55,109 +54,109 @@ pub async fn list_up_for_buy( remove_keys(&mut filtered_data, keys_to_remove).await; // sma3_close(current) > sma3_open (current), sma3_close(prev) < sma3_open (prev) - let mut keys_to_remove: HashSet = HashSet::new(); - let ema10_open = ema_open(5, &alldata.rt_price_30m_vec, &filtered_data).await?; - let ema10_close = ema(5, &alldata.rt_price_30m_vec, &filtered_data).await?; - let ema200_close = ema(200, &alldata.rt_price_30m_vec, &filtered_data).await?; - for (symbol, values) in &mut filtered_data { - let mut do_buy = false; - let price_and_closetime = get_current_price_decimal(&symbol, &alldata.rt_price_30m_vec).await; - if let (Some(ema10_open_vec), Some(ema10_close_vec), Some(ema200_close_vec), Some(current_info)) - = (ema10_open.get(symbol), ema10_close.get(symbol), ema200_close.get(symbol), price_and_closetime) { - if ema10_open_vec.len() > 20 - && ema10_close_vec.len() > 20 - && ema10_open_vec.last().unwrap().close_time > server_epoch - && ema10_open_vec.last().unwrap().close_time == ema10_close_vec.last().unwrap().close_time - && ema10_open_vec.last().unwrap().close_time == ema200_close_vec.last().unwrap().close_time - { - if ema10_open_vec.last().unwrap().ema_value > ema10_close_vec.last().unwrap().ema_value - && current_info.0.to_f64().is_some_and(|a| a < ema200_close_vec.last().unwrap().ema_value) - { - values.current_price = current_info.0; - values.closetime = current_info.1; - do_buy = true; - } - } - } - if do_buy == false { - keys_to_remove.insert(symbol.clone()); - } - } - remove_keys(&mut filtered_data, keys_to_remove).await; + // let mut keys_to_remove: HashSet = HashSet::new(); + // let ema10_open = ema_open(5, &alldata.rt_price_30m_vec, &filtered_data).await?; + // let ema10_close = ema(5, &alldata.rt_price_30m_vec, &filtered_data).await?; + // let ema200_close = ema(200, &alldata.rt_price_30m_vec, &filtered_data).await?; + // for (symbol, values) in &mut filtered_data { + // let mut do_buy = false; + // let price_and_closetime = get_current_price_decimal(&symbol, &alldata.rt_price_30m_vec).await; + // if let (Some(ema10_open_vec), Some(ema10_close_vec), Some(ema200_close_vec), Some(current_info)) + // = (ema10_open.get(symbol), ema10_close.get(symbol), ema200_close.get(symbol), price_and_closetime) { + // if ema10_open_vec.len() > 20 + // && ema10_close_vec.len() > 20 + // && ema10_open_vec.last().unwrap().close_time > server_epoch + // && ema10_open_vec.last().unwrap().close_time == ema10_close_vec.last().unwrap().close_time + // && ema10_open_vec.last().unwrap().close_time == ema200_close_vec.last().unwrap().close_time + // { + // if ema10_open_vec.last().unwrap().ema_value > ema10_close_vec.last().unwrap().ema_value + // && current_info.0.to_f64().is_some_and(|a| a < ema200_close_vec.last().unwrap().ema_value) + // { + // values.current_price = current_info.0; + // values.closetime = current_info.1; + // do_buy = true; + // } + // } + // } + // if do_buy == false { + // keys_to_remove.insert(symbol.clone()); + // } + // } + // remove_keys(&mut filtered_data, keys_to_remove).await; // current ADX(3, 3), current ADX > prev ADX - let mut keys_to_remove: HashSet = HashSet::new(); - let adx_vec = adx(3, 3, &alldata.rt_price_30m_vec, &filtered_data).await?; - for (symbol, values) in &mut filtered_data { - let mut do_buy = false; - if let Some(adx_vec) = adx_vec.get(symbol) { - if let Some(last_idx) = adx_vec.iter().position(|elem| elem.close_time == values.closetime) { - if adx_vec.len() > 10 - && adx_vec[last_idx].adx > adx_vec[last_idx-1].adx - { - do_buy = true; - } - } - } - if do_buy == false { - keys_to_remove.insert(symbol.clone()); - } - } - remove_keys(&mut filtered_data, keys_to_remove).await; + // let mut keys_to_remove: HashSet = HashSet::new(); + // let adx_vec = adx(3, 3, &alldata.rt_price_30m_vec, &filtered_data).await?; + // for (symbol, values) in &mut filtered_data { + // let mut do_buy = false; + // if let Some(adx_vec) = adx_vec.get(symbol) { + // if let Some(last_idx) = adx_vec.iter().position(|elem| elem.close_time == values.closetime) { + // if adx_vec.len() > 10 + // && adx_vec[last_idx].adx > adx_vec[last_idx-1].adx + // { + // do_buy = true; + // } + // } + // } + // if do_buy == false { + // keys_to_remove.insert(symbol.clone()); + // } + // } + // remove_keys(&mut filtered_data, keys_to_remove).await; // supertrend(ATR period 30, multiplier: 2.0, 30m close price) - let mut keys_to_remove: HashSet = HashSet::new(); - let supertrend_30m_map = - supertrend(100, 1.5, true, &alldata.rt_price_30m_vec, &filtered_data).await?; - for (symbol, values) in &mut filtered_data { - let mut do_buy = false; - if let Some(supertrend_vec) = supertrend_30m_map.get(symbol) - { - if supertrend_vec.len() > 10 - && supertrend_vec.last().is_some_and(|a| a.close_time == values.closetime) - && supertrend_vec.last().unwrap().area == SuperTrendArea::DOWN - && supertrend_vec[supertrend_vec.len()-2].area == SuperTrendArea::DOWN { - do_buy = true; - } - } + // let mut keys_to_remove: HashSet = HashSet::new(); + // let supertrend_30m_map = + // supertrend(100, 1.5, true, &alldata.rt_price_30m_vec, &filtered_data).await?; + // for (symbol, values) in &mut filtered_data { + // let mut do_buy = false; + // if let Some(supertrend_vec) = supertrend_30m_map.get(symbol) + // { + // if supertrend_vec.len() > 10 + // && supertrend_vec.last().is_some_and(|a| a.close_time == values.closetime) + // && supertrend_vec.last().unwrap().area == SuperTrendArea::DOWN + // && supertrend_vec[supertrend_vec.len()-2].area == SuperTrendArea::DOWN { + // do_buy = true; + // } + // } - if do_buy == false { - keys_to_remove.insert(symbol.clone()); - } - } - remove_keys(&mut filtered_data, keys_to_remove).await; + // if do_buy == false { + // keys_to_remove.insert(symbol.clone()); + // } + // } + // remove_keys(&mut filtered_data, keys_to_remove).await; // set target_price and stop_loss - let mut keys_to_remove: HashSet = HashSet::new(); - for (symbol, values) in &mut filtered_data { - let mut do_buy = false; - if let Some(realtime_price_vec) = alldata.rt_price_30m_vec.get(symbol) - { - let element_number = 5; - if let Some(truncated_vec) = realtime_price_vec.get(realtime_price_vec.len()-element_number..) { - let max_price = truncated_vec - .iter() - .max_by(|x, y| x.high_price.partial_cmp(&y.high_price).unwrap()) - .unwrap().high_price; - if values.current_price.to_f64().is_some_and(|a| a < max_price) { - let mut stoploss_percent = ((values.current_price.to_f64().unwrap() - max_price) * 100.0) / values.current_price.to_f64().unwrap(); - stoploss_percent = (stoploss_percent * 100.0).floor() / 100.0; - values.stoploss = rust_decimal::prelude::FromPrimitive::from_f64(stoploss_percent).unwrap(); - let mut target_percent = stoploss_percent.abs() * 1.5; - target_percent = (target_percent * 100.0).floor() / 100.0; - values.target_price = rust_decimal::prelude::FromPrimitive::from_f64(target_percent).unwrap(); + // let mut keys_to_remove: HashSet = HashSet::new(); + // for (symbol, values) in &mut filtered_data { + // let mut do_buy = false; + // if let Some(realtime_price_vec) = alldata.rt_price_30m_vec.get(symbol) + // { + // let element_number = 5; + // if let Some(truncated_vec) = realtime_price_vec.get(realtime_price_vec.len()-element_number..) { + // let max_price = truncated_vec + // .iter() + // .max_by(|x, y| x.high_price.partial_cmp(&y.high_price).unwrap()) + // .unwrap().high_price; + // if values.current_price.to_f64().is_some_and(|a| a < max_price) { + // let mut stoploss_percent = ((values.current_price.to_f64().unwrap() - max_price) * 100.0) / values.current_price.to_f64().unwrap(); + // stoploss_percent = (stoploss_percent * 100.0).floor() / 100.0; + // values.stoploss = rust_decimal::prelude::FromPrimitive::from_f64(stoploss_percent).unwrap(); + // let mut target_percent = stoploss_percent.abs() * 1.5; + // target_percent = (target_percent * 100.0).floor() / 100.0; + // values.target_price = rust_decimal::prelude::FromPrimitive::from_f64(target_percent).unwrap(); - do_buy = true; + // do_buy = true; - } - } - } + // } + // } + // } - if do_buy == false { - keys_to_remove.insert(symbol.clone()); - } - } - remove_keys(&mut filtered_data, keys_to_remove).await; + // if do_buy == false { + // keys_to_remove.insert(symbol.clone()); + // } + // } + // remove_keys(&mut filtered_data, keys_to_remove).await; // Wiliams -50.0 < %R(100) let mut keys_to_remove: HashSet = HashSet::new(); @@ -168,7 +167,7 @@ pub async fn list_up_for_buy( if let Some(wpr100_vec) = wpr100_map.get(symbol) { if wpr100_vec.len() > 15 && wpr100_vec.last().unwrap().close_time > server_epoch - && wpr100_vec.last().unwrap().r_value > -60.0 { + && wpr100_vec.last().unwrap().r_value > -50.0 { do_buy = true; } } @@ -369,13 +368,14 @@ pub async fn list_up_for_sell(all_data: &AllData, futures_exchange_info_map: &Ha .unwrap(); let server_epoch = get_server_epoch().await; - let mut supertrend_vec: Vec = Vec::new(); + // let mut supertrend_vec: Vec = Vec::new(); let mut filtered_symbols: HashMap = HashMap::new(); for element in &filled_positions { filtered_symbols.insert(element.symbol.clone(), FilteredDataValue::new()); } - let supertrend_30m_map = - supertrend(100, 1.5, true, &all_data.rt_price_30m_vec, &filtered_symbols).await?; + let lr_map = linear_regression(10, 0, &all_data.rt_price_30m_vec, &filtered_symbols).await?; + // let supertrend_30m_map = + // supertrend(100, 1.5, true, &all_data.rt_price_30m_vec, &filtered_symbols).await?; // let adx_vec = adx(15, 15, &all_data.rt_price_1m_vec, &filtered_symbols).await?; for element in filled_positions { let mut is_sell = false; @@ -388,66 +388,66 @@ pub async fn list_up_for_sell(all_data: &AllData, futures_exchange_info_map: &Ha // ); // TODO: BNB 코인이 없으면 - if !element.current_price.is_zero() { - if element.pure_profit_percent >= element.target_percent { - is_sell = true; - } else if element.pure_profit_percent <= element.stoploss_percent { - is_sell = true; - } else if server_epoch - element.close_time > 300_000 && supertrend_30m_map.get(&element.symbol).is_some_and(|a| a.len() > 10 && a.last().is_some_and(|b| b.close_time > server_epoch && b.area == SuperTrendArea::UP)) { - is_sell = true; - } - - let minimum_candles = 5; - let maximum_candles = 20; - for count_candles in minimum_candles..=maximum_candles { - if count_candles < maximum_candles - && server_epoch - element.transact_time - > (1_800_000) * count_candles - && ((element.pure_profit_percent > 0.0 - && element.target_percent - * ((maximum_candles - count_candles) as f64 - / (maximum_candles - minimum_candles + 1) as f64) - <= element.pure_profit_percent) - || - (element.pure_profit_percent < 0.0 - && element.stoploss_percent - * ((maximum_candles - count_candles) as f64 - / (maximum_candles - minimum_candles + 1) as f64) - >= element.pure_profit_percent) - ) - { + if let Some(lr_vec) = lr_map.get(&element.symbol) { + if !element.current_price.is_zero() && lr_vec.len() > 10 && lr_vec.last().is_some_and(|x| x.close_time > server_epoch) { + + if element.pure_profit_percent >= element.target_percent { is_sell = true; - break; - } else { - break; + } else if element.pure_profit_percent <= element.stoploss_percent { + is_sell = true; + } else if lr_vec.last().unwrap().r_squared >= 0.55 { + is_sell = true; + } + + let minimum_candles = 5; + let maximum_candles = 6; + // for count_candles in minimum_candles..=maximum_candles { + // if count_candles < maximum_candles + // && server_epoch - element.transact_time + // > (1_800_000) * count_candles + // && ((element.pure_profit_percent > 0.0 + // && element.target_percent + // * ((maximum_candles - count_candles) as f64 + // / (maximum_candles - minimum_candles + 1) as f64) + // <= element.pure_profit_percent) + // || + // (element.pure_profit_percent < 0.0 + // && element.stoploss_percent + // * ((maximum_candles - count_candles) as f64 + // / (maximum_candles - minimum_candles + 1) as f64) + // >= element.pure_profit_percent) + // ) + // { + // is_sell = true; + // break; + // } else { + // break; + // } + // } + + if server_epoch - element.close_time > 1_800_000 * maximum_candles { + is_sell = true; + } + + //} else if server_epoch - element.close_time > 300_000 + // && adx_vec.get(&element.symbol).is_some_and(|a| a.len() > 10 && a.last().is_some_and(|b| b.close_time > server_epoch && b.adx < 15.0)) { + // is_sell = true; + // } + + if is_sell == true { + limit_order_close( + &element, + TimeInForce::Gtc, + element.current_price, + element.base_qty_ordered, + &futures_exchange_info_map, + &client + ) + .await; } } - - if server_epoch - element.close_time > 1_800_000 * maximum_candles { - is_sell = true; - } - - // else if server_epoch - element.close_time > 300_000 && supertrend_1m_map.get(&element.symbol).is_some_and(|a| a.len() > 10 && a.last().is_some_and(|b| b.close_time > server_epoch && b.area == SuperTrendArea::UP)) { - // is_sell = true; - // } else if server_epoch - element.close_time > 300_000 && adx_vec.get(&element.symbol).is_some_and(|a| a.len() > 10 && a.last().is_some_and(|b| b.close_time > server_epoch && b.adx < 15.0)) { - // is_sell = true; - // } - - if is_sell == true { - limit_order_close( - &element, - TimeInForce::Gtc, - element.current_price, - element.base_qty_ordered, - &futures_exchange_info_map, - &client - ) - .await; - } - } - - } - + } + } Ok(()) }