From 512bc46b399e4308043fe6f08f1ca2cdaadc8f51 Mon Sep 17 00:00:00 2001 From: Sik Yoon Date: Thu, 23 May 2024 00:14:30 +0900 Subject: [PATCH] Add strategy for long position --- src/strategy_team/future_strategy_long.rs | 146 ++++++++++++++++++++++ src/strategy_team/mod.rs | 1 + src/strategy_team/strategy_manager.rs | 2 + 3 files changed, 149 insertions(+) create mode 100644 src/strategy_team/future_strategy_long.rs diff --git a/src/strategy_team/future_strategy_long.rs b/src/strategy_team/future_strategy_long.rs new file mode 100644 index 0000000..f680eb0 --- /dev/null +++ b/src/strategy_team/future_strategy_long.rs @@ -0,0 +1,146 @@ +use crate::value_estimation_team::{datapoints::price_data::CandleType, indicators::wiliams_percent_r}; + +use super::{ + adx, dec, decimal_add, decimal_div, decimal_mul, decimal_sub, dema, duplicate_filter, ema, + ema_macd, exists_record, get_server_epoch, heatmap_volume, + insert_pre_suggested_coins, limit_order_sell, remove_keys, rsi, select_filled_buy_orders, + stoch_rsi, supertrend, tema, try_join_all, update_record3, wiliams_percent_r, AdxData, AllData, + Arc, BollingerBandData, Client, ClientBuilder, Decimal, DemaData, EmaData, ExchangeInfo, + FilteredDataValue, HashMap, HashSet, HeatMapLevel, HeatmapVolumeData, MacdData, Mutex, + RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SuperTrendArea, SuperTrendSignal, + SupertrendData, TemaData, ToPrimitive, TradeFee, WiliamsPercentR, future_duplicate_filter, insert_future_coins +}; + +use crate::future::{Position, FuturesExchangeInfo}; +use crate::future::table_mgmt::select_filled_positions; +use crate::future::order::{limit_order_close, TimeInForce}; + +// BUY conditions +pub async fn list_up_for_buy( + alldata: &AllData, + future_exchange_info_map: &HashMap +) -> 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()); + + // basic filtering: filtering valid trade pair + let mut filtered_data: HashMap = HashMap::new(); + for symbol in &alldata.valid_symbol_vec { + filtered_data.insert(symbol.clone(), FilteredDataValue::new()); + } + let server_epoch = get_server_epoch().await; + // current Tema(30) < current Tema(60) + let mut keys_to_remove: HashSet = HashSet::new(); + let tema_15 = tema(15, &alldata.rt_price_1m_vec, &filtered_data).await?; + let tema_60 = tema(60, &alldata.rt_price_1m_vec, &filtered_data).await?; + let server_epoch = get_server_epoch().await; + + let mut do_buy = false; + if let (Some(tema15_vec), Some(tema60_vec)) = (tema_15.get("BTCUSDT"), tema_60.get("BTCUSDT")) { + if tema15_vec.len() > 10 + && tema60_vec.len() > 10 + && tema15_vec.last().unwrap().close_time == tema60_vec.last().unwrap().close_time + && tema15_vec.last().unwrap().close_time > server_epoch + && tema60_vec.last().unwrap().close_time > server_epoch + { + if tema15_vec.last().unwrap().tema_value > tema60_vec.last().unwrap().tema_value { + do_buy = true; + } + } + } + + if do_buy == false { + return Ok(()); + } + + // Heatmap volume: filtering close price with Extra High is over the previous candle from 30 previous candles + let mut keys_to_remove: HashSet = HashSet::new(); + let heatmap_volumes = heatmap_volume( + 60, + 60, + 4.0, + 2.5, + 1.0, + -0.5, + &filtered_data, + &alldata.rt_price_1m_vec, + ) + .await?; + let server_epoch = get_server_epoch().await; + for (symbol, values) in &mut filtered_data { + let mut do_buy = false; + if let (Some(heatmap_volume_vec), Some(rt_price_vec), Some(rt_price_vec_30m)) = (heatmap_volumes.get(symbol), alldata.rt_price_1m_vec.get(symbol), alldata.rt_price_30m_vec.get(symbol)) { + if heatmap_volume_vec.len() > 100 + && heatmap_volume_vec.last().unwrap().close_time > server_epoch + && rt_price_vec.last().unwrap().close_time == heatmap_volume_vec.last().unwrap().close_time + && heatmap_volume_vec[heatmap_volume_vec.len()-2].heatmap_level == HeatMapLevel::ExtraHigh + && rt_price_vec[rt_price_vec.len()-2].candle_type == CandleType::DOWN { + let current_price: Decimal = rust_decimal::prelude::FromPrimitive::from_f64( + rt_price_vec_30m.last().unwrap().close_price, + ) + .unwrap(); + values.closetime = heatmap_volume_vec.last().unwrap().close_time; + values.current_price = current_price; + do_buy = true; + } + } + + if do_buy == false { + keys_to_remove.insert(symbol.clone()); + } + } + remove_keys(&mut filtered_data, keys_to_remove).await; + + + let final_filtered_data = future_duplicate_filter(&filtered_data, &future_exchange_info_map).await?; + insert_future_coins(Position::Long, server_epoch, &final_filtered_data).await?; + + Ok(()) +} + +pub async fn list_up_for_sell() -> Result<(), Box> { + let filled_positions = select_filled_positions().await?; + + let client = ClientBuilder::new() + .timeout(tokio::time::Duration::from_millis(5000)) + .build() + .unwrap(); + let server_epoch = get_server_epoch().await; + + for element in filled_positions { + let mut is_sell = false; + + // TODO: BNB 코인이 있으면 + // let base_qty_to_be_ordered = + // element.base_qty_ordered.round_dp_with_strategy( + // lot_step_size.normalize().scale(), + // RoundingStrategy::ToZero, + // ); + // TODO: BNB 코인이 없으면 + + if !element.current_price.is_zero() { + if element.pure_profit_percent >= 0.6 { + is_sell = true; + } else if element.pure_profit_percent <= -0.8 { + is_sell = true; + } else if server_epoch - element.transact_time >= (1_800_000) * 1 { + // time up selling + is_sell = true; + } + + if is_sell == true { + limit_order_close( + &element, + TimeInForce::Gtc, + element.current_price, + element.base_qty_ordered, + &client + ) + .await; + } + } + } + + Ok(()) +} diff --git a/src/strategy_team/mod.rs b/src/strategy_team/mod.rs index 29de453..62b66b5 100644 --- a/src/strategy_team/mod.rs +++ b/src/strategy_team/mod.rs @@ -9,6 +9,7 @@ pub mod strategy_008; pub mod strategy_009; pub mod strategy_010; pub mod future_strategy; +pub mod future_strategy_long; // pub mod strategy_test; pub mod strategy_manager; diff --git a/src/strategy_team/strategy_manager.rs b/src/strategy_team/strategy_manager.rs index 264de85..8c9340d 100644 --- a/src/strategy_team/strategy_manager.rs +++ b/src/strategy_team/strategy_manager.rs @@ -43,6 +43,7 @@ pub async fn execute_list_up_for_buy( // crate::strategy_team::strategy_007::list_up_for_buy(all_data).await; // crate::strategy_team::strategy_008::list_up_for_buy(all_data).await; // crate::strategy_team::strategy_009::list_up_for_buy(all_data).await; + crate::strategy_team::future_strategy_long::list_up_for_buy(all_data, &future_exchange_info_map).await; crate::strategy_team::future_strategy::list_up_for_buy(all_data, &future_exchange_info_map).await; Ok(()) @@ -83,6 +84,7 @@ pub async fn execute_list_up_for_sell( // &trade_fee_map, // ) // .await; + crate::strategy_team::future_strategy_long::list_up_for_sell().await; crate::strategy_team::future_strategy::list_up_for_sell().await; Ok(()) }