Merge pull request 'Separate strategy team module' (#1) from strategy-team-module into master

Reviewed-on: http://siknas.duckdns.org:3000/Sik/tradingbot/pulls/1
This commit is contained in:
Sik 2023-11-18 16:35:56 +00:00
commit 8a53e18553
23 changed files with 3019 additions and 8681 deletions

854
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -24,4 +24,3 @@ thirtyfour = { version = "0.28.1", features = ["tokio-runtime"]}
ord_subset = "3.1.1" ord_subset = "3.1.1"
rust_decimal = "1.29.1" rust_decimal = "1.29.1"
rust_decimal_macros = "1.29.1" rust_decimal_macros = "1.29.1"
plotters = "0.3.1"

View File

@ -1,6 +1,6 @@
use crate::coex::assets_managing_team::*; use crate::coex::assets_managing_team::*;
use crate::coex::order_team::*; use crate::coex::order_team::*;
use crate::coex::strategy_team::AllData; use crate::strategy_team::AllData;
use crate::coin_health_check_team::request_others::{CoinPriceData, ExchangeInfo, TradeFee}; use crate::coin_health_check_team::request_others::{CoinPriceData, ExchangeInfo, TradeFee};
use crate::database_control::*; use crate::database_control::*;
use crate::decimal_funcs::{decimal, decimal_add, decimal_div, decimal_mul, decimal_sub}; use crate::decimal_funcs::{decimal, decimal_add, decimal_div, decimal_mul, decimal_sub};
@ -576,7 +576,7 @@ pub async fn monitoring_scoreboard(
let mut update_condition: Vec<(String, String)> = Vec::new(); let mut update_condition: Vec<(String, String)> = Vec::new();
let mut update_condition2: Vec<(String, String)> = Vec::new(); let mut update_condition2: Vec<(String, String)> = Vec::new();
let filled_buy_orders = select_filled_buy_orders().await?; let filled_buy_orders = select_filled_buy_orders(0).await?;
if filled_buy_orders.is_empty() { if filled_buy_orders.is_empty() {
// initialization of table // initialization of table

View File

@ -1,4 +1,3 @@
pub mod assets_managing_team; pub mod assets_managing_team;
pub mod exchange_team; pub mod exchange_team;
pub mod order_team; pub mod order_team;
pub mod strategy_team;

View File

@ -11,8 +11,7 @@ use crate::URL_TEST;
// use crates // use crates
use crate::coex::assets_managing_team::*; use crate::coex::assets_managing_team::*;
use crate::coex::exchange_team::*; use crate::coex::exchange_team::*;
use crate::coex::strategy_team::AllData; use crate::strategy_team::{AllData, TimeData};
use crate::coex::strategy_team::TimeData;
use crate::coin_health_check_team::request_others::{CoinPriceData, ExchangeInfo, TradeFee}; use crate::coin_health_check_team::request_others::{CoinPriceData, ExchangeInfo, TradeFee};
use crate::database_control::*; use crate::database_control::*;
use crate::decimal_funcs::*; use crate::decimal_funcs::*;
@ -517,27 +516,21 @@ pub async fn monitoring_open_buy_order(
Ok(()) Ok(())
} }
pub async fn monitoring_filled_buy_order( pub async fn update_price_of_filled_buy_order(
all_data: &AllData,
coin_price_vec: &Vec<CoinPriceData>, coin_price_vec: &Vec<CoinPriceData>,
exchange_info_vec: &Vec<ExchangeInfo>, exchange_info_vec: &Vec<ExchangeInfo>,
trade_fee_vec: &Vec<TradeFee>, trade_fee_vec: &Vec<TradeFee>,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> { ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let index_list = select_marketcap().await; let filled_buy_orders = select_filled_buy_orders(0).await?;
// let scoreboard_list = select_scoreboard().await;
// let signal_decision = select_signal_decision().await;
let filled_buy_orders = select_filled_buy_orders().await?;
if !filled_buy_orders.is_empty() { if !filled_buy_orders.is_empty() {
// 심볼들을 2개씩 청스로 나누어 테스크를 생성하고 각 태스크 별로 병렬로 처리한다. // 심볼들을 2개씩 청스로 나누어 테스크를 생성하고 각 태스크 별로 병렬로 처리한다.
// update real-time current price to each record through chunks // update real-time current price to each record through chunks
let chunks: std::slice::Chunks<'_, BuyOrderedCoinList> = filled_buy_orders.chunks(2); let chunks: std::slice::Chunks<'_, BuyOrderedCoinList> = filled_buy_orders.chunks(3);
let mut task_vec = Vec::new(); let mut task_vec = Vec::new();
for chunk in chunks { for chunk in chunks {
let chunk_vec = chunk.to_vec(); let chunk_vec = chunk.to_vec();
let interval_clone = interval.clone();
let coin_price_vec_c = coin_price_vec.clone(); let coin_price_vec_c = coin_price_vec.clone();
let exchange_info_vec_c = exchange_info_vec.clone(); let exchange_info_vec_c = exchange_info_vec.clone();
let trade_fee_vec_c = trade_fee_vec.clone(); let trade_fee_vec_c = trade_fee_vec.clone();
@ -551,179 +544,7 @@ pub async fn monitoring_filled_buy_order(
.await; .await;
})); }));
} }
let result = try_join_all(task_vec).await;
// sell coin if its sell condition is satisfied
let filled_buy_orders = select_filled_buy_orders().await?;
let client = ClientBuilder::new()
.timeout(tokio::time::Duration::from_millis(5000))
.build()
.unwrap();
let instant = Instant::now();
let server_epoch = server_epoch().await;
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 lot_step_size_option = exchange_info_vec
.iter()
.find(|ExchangeInfo| ExchangeInfo.symbol == element.symbol);
let quote_commission_precision_option = exchange_info_vec
.iter()
.find(|ExchangeInfo| ExchangeInfo.symbol == element.symbol);
let opclo_30m_option = all_data
.rt_price_30m_vec
.iter()
.position(|x| *x.0 == element.symbol);
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,
);
let mut opclo_30m_vec = all_data.rt_price_30m_vec[opclo_30m_option.unwrap()]
.1
.clone();
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;
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;
} else if server_epoch - element.close_time >= (3_600_000 * 24) && element.pure_profit_percent >= 0.2 // (1hr * 24)
{
println!(
"selling {} due to time up {:.3}",
element.symbol,
element.pure_profit_percent
);
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;
}
}
}
}
}
if sell_order_count == 25 {
// to avoid Limit of order: LIMIT 50 for 10 secs
sleep(Duration::from_secs(10)).await;
sell_order_count = 0;
}
}
} }
Ok(()) Ok(())
} }
@ -833,7 +654,6 @@ async fn update_repeat_task(
update_record.push(update_record_build.clone()); update_record.push(update_record_build.clone());
} }
} }
} }
} }
@ -2268,10 +2088,17 @@ async fn get_timestamp() -> String {
timestamp timestamp
} }
pub async fn select_filled_buy_orders() -> Result<Vec<BuyOrderedCoinList>, Box<dyn std::error::Error + Send + Sync>> { // parameter 0: select all registerers
pub async fn select_filled_buy_orders(registerer: u32) -> Result<Vec<BuyOrderedCoinList>, Box<dyn std::error::Error + Send + Sync>> {
let select_table_name = String::from("buy_ordered_coin_list"); let select_table_name = String::from("buy_ordered_coin_list");
let select_columns = String::from("*"); let select_columns = String::from("*");
let select_condition = Some(String::from("WHERE status = 'FILLED' or status = 'SIMUL'")); let mut select_condition_build = String::from("WHERE (status = 'FILLED' or status = 'SIMUL')");
if registerer > 0 {
select_condition_build.push_str(" and registerer = ");
select_condition_build.push_str(registerer.to_string().as_str());
}
let select_condition = Some(select_condition_build);
let data_struct = BuyOrderedCoinList::new(); let data_struct = BuyOrderedCoinList::new();
let select_result = try_select_record( let select_result = try_select_record(

File diff suppressed because it is too large Load Diff

View File

@ -748,7 +748,7 @@ where
let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await;
//retry connection until it will be done. //retry connection until it will be done.
while conn_result.is_err() { while conn_result.is_err() {
sleep(Duration::from_millis(200)).await; sleep(Duration::from_millis(50)).await;
conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await;
} }
let mut conn = conn_result.unwrap(); let mut conn = conn_result.unwrap();

View File

@ -22,13 +22,15 @@ pub enum RunningMode {
TEST, TEST,
REAL, REAL,
} }
pub const RUNNING_MODE: RunningMode = RunningMode::REAL; pub const RUNNING_MODE: RunningMode = RunningMode::SIMUL;
mod coex; pub mod coex;
mod coin_health_check_team; pub mod coin_health_check_team;
mod database_control; pub mod database_control;
mod decimal_funcs; pub mod decimal_funcs;
mod server_health_check_team; pub mod server_health_check_team;
mod signal_association; pub mod signal_association;
mod time_checking_team; pub mod time_checking_team;
mod value_estimation_team; pub mod value_estimation_team;
pub mod strategy_team;
pub mod initialization;

View File

@ -1,18 +1,7 @@
#![allow(unused)] #![allow(unused)]
#![allow(warnings)] #![allow(warnings)]
mod coex; use crate::strategy_team::AllData;
mod coin_health_check_team;
mod database_control;
mod decimal_funcs;
mod initialization;
mod server_health_check_team;
mod signal_association;
mod time_checking_team;
mod value_estimation_team;
use crate::coex::order_team::*;
use crate::coex::strategy_team::AllData;
use crate::coin_health_check_team::*; use crate::coin_health_check_team::*;
use crate::request_candles::CandleData; use crate::request_candles::CandleData;
use crate::request_others::{CoinPriceData, ExchangeInfo, TradeFee}; use crate::request_others::{CoinPriceData, ExchangeInfo, TradeFee};
@ -69,6 +58,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let tx_task7 = tx_task1.clone(); // for Task#7 let tx_task7 = tx_task1.clone(); // for Task#7
let tx_task8 = tx_task1.clone(); // for Task#8 let tx_task8 = tx_task1.clone(); // for Task#8
let tx_task9 = tx_task1.clone(); // for Task#9 let tx_task9 = tx_task1.clone(); // for Task#9
let tx_task10 = tx_task1.clone(); // for Task#10
let tx_task11 = tx_task1.clone(); // for Task#11
let tx_task12 = tx_task1.clone(); // for Task#12 let tx_task12 = tx_task1.clone(); // for Task#12
let tx_task13 = tx_task1.clone(); // for Task#13 let tx_task13 = tx_task1.clone(); // for Task#13
let tx_task14 = tx_task1.clone(); // for Task#14 let tx_task14 = tx_task1.clone(); // for Task#14
@ -100,6 +91,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut rx2_tradefee_vec = rx_tradefee_vec.clone(); let mut rx2_tradefee_vec = rx_tradefee_vec.clone();
let mut rx3_tradefee_vec = rx_tradefee_vec.clone(); let mut rx3_tradefee_vec = rx_tradefee_vec.clone();
let mut rx4_tradefee_vec = rx_tradefee_vec.clone(); let mut rx4_tradefee_vec = rx_tradefee_vec.clone();
let mut rx5_tradefee_vec = rx_tradefee_vec.clone();
// valid usdt trade data // valid usdt trade data
let mut valid_usdt_trade_vec: Vec<String> = Vec::new(); // symbol let mut valid_usdt_trade_vec: Vec<String> = Vec::new(); // symbol
@ -107,6 +99,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
watch::channel(valid_usdt_trade_vec); watch::channel(valid_usdt_trade_vec);
let mut rx2_valid_usdt_trade_vec = rx_valid_usdt_trade_vec.clone(); let mut rx2_valid_usdt_trade_vec = rx_valid_usdt_trade_vec.clone();
let mut rx3_valid_usdt_trade_vec = rx_valid_usdt_trade_vec.clone(); let mut rx3_valid_usdt_trade_vec = rx_valid_usdt_trade_vec.clone();
let mut rx4_valid_usdt_trade_vec = rx_valid_usdt_trade_vec.clone();
// price per second data and channels // price per second data and channels
let mut price_vec: Vec<CoinPriceData> = Vec::new(); // (symbol, price) let mut price_vec: Vec<CoinPriceData> = Vec::new(); // (symbol, price)
@ -136,27 +129,32 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut rx2_rt_price_1m_vec = rx_rt_price_1m_vec.clone(); let mut rx2_rt_price_1m_vec = rx_rt_price_1m_vec.clone();
let mut rx3_rt_price_1m_vec = rx_rt_price_1m_vec.clone(); let mut rx3_rt_price_1m_vec = rx_rt_price_1m_vec.clone();
let mut rx4_rt_price_1m_vec = rx_rt_price_1m_vec.clone(); let mut rx4_rt_price_1m_vec = rx_rt_price_1m_vec.clone();
let mut rx5_rt_price_1m_vec = rx_rt_price_1m_vec.clone();
let mut rt_price_30m_vec: Vec<(String, Vec<RealtimePriceData>)> = Vec::new(); let mut rt_price_30m_vec: Vec<(String, Vec<RealtimePriceData>)> = Vec::new();
let (tx_rt_price_30m_vec, mut rx_rt_price_30m_vec) = watch::channel(rt_price_30m_vec); let (tx_rt_price_30m_vec, mut rx_rt_price_30m_vec) = watch::channel(rt_price_30m_vec);
let mut rx2_rt_price_30m_vec = rx_rt_price_30m_vec.clone(); let mut rx2_rt_price_30m_vec = rx_rt_price_30m_vec.clone();
let mut rx3_rt_price_30m_vec = rx_rt_price_30m_vec.clone(); let mut rx3_rt_price_30m_vec = rx_rt_price_30m_vec.clone();
let mut rx4_rt_price_30m_vec = rx_rt_price_30m_vec.clone(); let mut rx4_rt_price_30m_vec = rx_rt_price_30m_vec.clone();
let mut rx5_rt_price_30m_vec = rx_rt_price_30m_vec.clone();
let mut rt_price_1d_vec: Vec<(String, Vec<RealtimePriceData>)> = Vec::new(); let mut rt_price_1d_vec: Vec<(String, Vec<RealtimePriceData>)> = Vec::new();
let (tx_rt_price_1d_vec, mut rx_rt_price_1d_vec) = watch::channel(rt_price_1d_vec); let (tx_rt_price_1d_vec, mut rx_rt_price_1d_vec) = watch::channel(rt_price_1d_vec);
let mut rx2_rt_price_1d_vec = rx_rt_price_1d_vec.clone(); let mut rx2_rt_price_1d_vec = rx_rt_price_1d_vec.clone();
let mut rx3_rt_price_1d_vec = rx_rt_price_1d_vec.clone(); let mut rx3_rt_price_1d_vec = rx_rt_price_1d_vec.clone();
let mut rx4_rt_price_1d_vec = rx_rt_price_1d_vec.clone();
let mut rt_price_1w_vec: Vec<(String, Vec<RealtimePriceData>)> = Vec::new(); let mut rt_price_1w_vec: Vec<(String, Vec<RealtimePriceData>)> = Vec::new();
let (tx_rt_price_1w_vec, mut rx_rt_price_1w_vec) = watch::channel(rt_price_1w_vec); let (tx_rt_price_1w_vec, mut rx_rt_price_1w_vec) = watch::channel(rt_price_1w_vec);
let mut rx2_rt_price_1w_vec = rx_rt_price_1w_vec.clone(); let mut rx2_rt_price_1w_vec = rx_rt_price_1w_vec.clone();
let mut rx3_rt_price_1w_vec = rx_rt_price_1w_vec.clone(); let mut rx3_rt_price_1w_vec = rx_rt_price_1w_vec.clone();
let mut rx4_rt_price_1w_vec = rx_rt_price_1w_vec.clone();
let mut rt_price_1mon_vec: Vec<(String, Vec<RealtimePriceData>)> = Vec::new(); let mut rt_price_1mon_vec: Vec<(String, Vec<RealtimePriceData>)> = Vec::new();
let (tx_rt_price_1mon_vec, mut rx_rt_price_1mon_vec) = watch::channel(rt_price_1mon_vec); let (tx_rt_price_1mon_vec, mut rx_rt_price_1mon_vec) = watch::channel(rt_price_1mon_vec);
let mut rx2_rt_price_1mon_vec = rx_rt_price_1mon_vec.clone(); let mut rx2_rt_price_1mon_vec = rx_rt_price_1mon_vec.clone();
let mut rx3_rt_price_1mon_vec = rx_rt_price_1mon_vec.clone(); let mut rx3_rt_price_1mon_vec = rx_rt_price_1mon_vec.clone();
let mut rx4_rt_price_1mon_vec = rx_rt_price_1mon_vec.clone();
// TEMA data // TEMA data
// let mut tema3_1m_data: Vec<(String, Vec<(f64, i64)>)> = Vec::new(); // Vec<(symbol, Vec<(price, closetime)>)> // let mut tema3_1m_data: Vec<(String, Vec<(f64, i64)>)> = Vec::new(); // Vec<(symbol, Vec<(price, closetime)>)>
@ -198,6 +196,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut rx2_exchange_info_data = rx_exchange_info_data.clone(); let mut rx2_exchange_info_data = rx_exchange_info_data.clone();
let mut rx3_exchange_info_data = rx_exchange_info_data.clone(); let mut rx3_exchange_info_data = rx_exchange_info_data.clone();
let mut rx4_exchange_info_data = rx_exchange_info_data.clone(); let mut rx4_exchange_info_data = rx_exchange_info_data.clone();
let mut rx5_exchange_info_data = rx_exchange_info_data.clone();
let mut rx6_exchange_info_data = rx_exchange_info_data.clone();
{ {
if RUNNING_MODE == RunningMode::REAL { if RUNNING_MODE == RunningMode::REAL {
@ -529,8 +529,51 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
}); });
// Task#3: request 24h price changes, pick valid USDT Trades, monitor total_24h_change_profit_index, usdt_24h_change_profit_index, total_price_down_dist_index // Task#3: request lot stepsize and ticksize
tokio::task::spawn(async move { tokio::task::spawn(async move {
let client = ClientBuilder::new()
.timeout(tokio::time::Duration::from_millis(3000))
.build()
.unwrap();
loop {
let mut exchange_info_data_temp: Vec<ExchangeInfo> = Vec::new();
let mut result;
loop {
result = coin_health_check_team::request_others::request_exchange_infomation(
&client,
&mut exchange_info_data_temp,
)
.await;
// retry
if exchange_info_data_temp.len() == 0 {
sleep(Duration::from_secs(3)).await;
} else {
break;
}
}
match result {
Ok(T) => {
tx_exchange_info_data.send_modify(|vec| *vec = exchange_info_data_temp);
tx_task3
.send(3)
.expect("The mpsc channel has been closed.");
}
Err(E) => {}
}
sleep(Duration::from_secs(300)).await; // sleep for 5 mins
}
});
// Task#4: request 24h price changes,
// pick valid USDT Trades,
// filtering stop USDT Trades,
// monitor total_24h_change_profit_index,
// usdt_24h_change_profit_index,
// total_price_down_dist_index
tokio::task::spawn(async move {
sleep(Duration::from_secs(10)).await;
let client = ClientBuilder::new() let client = ClientBuilder::new()
.timeout(tokio::time::Duration::from_millis(3000)) .timeout(tokio::time::Duration::from_millis(3000))
.build() .build()
@ -541,15 +584,16 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let result = request_others::request_24hr_ticker_price_change_statistics(&client).await; let result = request_others::request_24hr_ticker_price_change_statistics(&client).await;
match result { match result {
Ok(T) => { Ok(T) => {
let exchange_info_vec = rx5_exchange_info_data.borrow().clone();
let mut valid_usdt_trade_vec_temp: Vec<String> = Vec::new(); let mut valid_usdt_trade_vec_temp: Vec<String> = Vec::new();
let result = let result =
monitors::collect_valid_usde_trade(&mut valid_usdt_trade_vec_temp).await; monitors::collect_valid_usde_trade(&mut valid_usdt_trade_vec_temp, &exchange_info_vec).await;
match result { match result {
Ok(T) => { Ok(T) => {
tx_valid_usdt_trade_vec tx_valid_usdt_trade_vec
.send_modify(|vec| *vec = valid_usdt_trade_vec_temp); .send_modify(|vec| *vec = valid_usdt_trade_vec_temp);
tx_task3.send(3).expect("The mpsc channel has been closed."); tx_task4.send(4).expect("The mpsc channel has been closed.");
} }
Err(E) => {} Err(E) => {}
} }
@ -597,7 +641,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
}); });
// Task#4: price per second // Task#5: price per second
tokio::task::spawn(async move { tokio::task::spawn(async move {
sleep(Duration::from_secs(20)).await; sleep(Duration::from_secs(20)).await;
let client = ClientBuilder::new() let client = ClientBuilder::new()
@ -616,7 +660,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
Ok(T) => { Ok(T) => {
price_vec_temp_c = price_vec_temp.clone(); price_vec_temp_c = price_vec_temp.clone();
tx_price_vec.send_modify(|vec| *vec = price_vec_temp); tx_price_vec.send_modify(|vec| *vec = price_vec_temp);
tx_task4.send(4).expect("The mpsc channel has been closed."); tx_task5.send(5).expect("The mpsc channel has been closed.");
} }
Err(E) => {} Err(E) => {}
} }
@ -749,7 +793,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
}); });
// Task#5: fetch candle 1m // Task#6: fetch candle 1m
tokio::task::spawn(async move { tokio::task::spawn(async move {
let mut elapsed_time = 0; let mut elapsed_time = 0;
let interval = String::from("1m"); let interval = String::from("1m");
@ -762,7 +806,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
match result { match result {
Ok(T) => { Ok(T) => {
tx_candle_1m_vec.send_modify(|vec| *vec = candle_1m_vec_temp); tx_candle_1m_vec.send_modify(|vec| *vec = candle_1m_vec_temp);
tx_task5.send(5).expect("The mpsc channel has been closed."); tx_task6.send(6).expect("The mpsc channel has been closed.");
} }
Err(E) => {} Err(E) => {}
} }
@ -775,7 +819,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
}); });
// Task#6: fetch candle 30m // Task#7: fetch candle 30m
tokio::task::spawn(async move { tokio::task::spawn(async move {
let mut elapsed_time = 0; let mut elapsed_time = 0;
let interval = String::from("30m"); let interval = String::from("30m");
@ -790,7 +834,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
match result { match result {
Ok(T) => { Ok(T) => {
tx_candle_30m_vec.send_modify(|vec| *vec = candle_30m_vec_temp); tx_candle_30m_vec.send_modify(|vec| *vec = candle_30m_vec_temp);
tx_task6.send(6).expect("The mpsc channel has been closed."); tx_task7.send(7).expect("The mpsc channel has been closed.");
} }
Err(E) => {} Err(E) => {}
} }
@ -802,7 +846,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
}); });
// Task#7: fetch candle 1d // Task#8: fetch candle 1d
tokio::task::spawn(async move { tokio::task::spawn(async move {
let mut elapsed_time = 0; let mut elapsed_time = 0;
let interval = String::from("1d"); let interval = String::from("1d");
@ -816,7 +860,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
match result { match result {
Ok(T) => { Ok(T) => {
tx_candle_1d_vec.send_modify(|vec| *vec = candle_1d_vec_temp); tx_candle_1d_vec.send_modify(|vec| *vec = candle_1d_vec_temp);
tx_task7.send(7).expect("The mpsc channel has been closed."); tx_task8.send(8).expect("The mpsc channel has been closed.");
} }
Err(E) => {} Err(E) => {}
} }
@ -828,7 +872,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
}); });
// // Task#8: fetch candle 1w // // Task#9: fetch candle 1w
// tokio::task::spawn(async move{ // tokio::task::spawn(async move{
// let interval = String::from("1w"); // let interval = String::from("1w");
// sleep(Duration::from_secs(600)).await; // sleep(Duration::from_secs(600)).await;
@ -839,14 +883,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// match result { // match result {
// Ok(T) => { // Ok(T) => {
// tx_candle_1w_vec.send_modify(|vec| *vec = candle_1w_vec_temp); // tx_candle_1w_vec.send_modify(|vec| *vec = candle_1w_vec_temp);
// tx_task8.send(8).expect("The mpsc channel has been closed."); // tx_task9.send(9).expect("The mpsc channel has been closed.");
// } // }
// Err(E) => {} // Err(E) => {}
// } // }
// } // }
// }); // });
// // Task#9: fetch candle 1mon // // Task#10: fetch candle 1mon
// tokio::task::spawn(async move{ // tokio::task::spawn(async move{
// let interval = String::from("1mon"); // let interval = String::from("1mon");
// sleep(Duration::from_secs(600)).await; // sleep(Duration::from_secs(600)).await;
@ -857,22 +901,22 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// match result { // match result {
// Ok(T) => { // Ok(T) => {
// tx_candle_1mon_vec.send_modify(|vec| *vec = candle_1mon_vec_temp); // tx_candle_1mon_vec.send_modify(|vec| *vec = candle_1mon_vec_temp);
// tx_task9.send(9).expect("The mpsc channel has been closed."); // tx_task10.send(10).expect("The mpsc channel has been closed.");
// } // }
// Err(E) => {} // Err(E) => {}
// } // }
// } // }
// }); // });
// Task#12: monitoring total market cap // Task#11: monitoring total market cap
if RUNNING_MODE == REAL || RUNNING_MODE == SIMUL || RUNNING_MODE == TEST { if RUNNING_MODE == REAL || RUNNING_MODE == SIMUL || RUNNING_MODE == TEST {
tokio::task::spawn(async move { tokio::task::spawn(async move {
loop { loop {
let result = signal_association::coinmarketcap::market_cap_index().await; let result = signal_association::coinmarketcap::market_cap_index().await;
match result { match result {
Ok(T) => { Ok(T) => {
tx_task12 tx_task11
.send(12) .send(11)
.expect("The mpsc channel has been closed."); .expect("The mpsc channel has been closed.");
} }
Err(E) => {} Err(E) => {}
@ -881,52 +925,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}); });
} }
// Task#13: request lot stepsize and ticksize // Task#12: monitoring foreign exchange rate
tokio::task::spawn(async move {
let client = ClientBuilder::new()
.timeout(tokio::time::Duration::from_millis(3000))
.build()
.unwrap();
loop {
let mut exchange_info_data_temp: Vec<ExchangeInfo> = Vec::new();
let mut result;
loop {
result = coin_health_check_team::request_others::request_exchange_infomation(
&client,
&mut exchange_info_data_temp,
)
.await;
// retry
if exchange_info_data_temp.len() == 0 {
sleep(Duration::from_secs(3)).await;
} else {
break;
}
}
match result {
Ok(T) => {
tx_exchange_info_data.send_modify(|vec| *vec = exchange_info_data_temp);
tx_task13
.send(13)
.expect("The mpsc channel has been closed.");
}
Err(E) => {}
}
sleep(Duration::from_secs(1200)).await; // sleep for 20mins
}
});
// Task#14: monitoring foreign exchange rate
if RUNNING_MODE == REAL || RUNNING_MODE == SIMUL { if RUNNING_MODE == REAL || RUNNING_MODE == SIMUL {
tokio::task::spawn(async move { tokio::task::spawn(async move {
loop { loop {
let result = signal_association::exchange_rate::monitoring_fx_rate_index().await; let result = signal_association::exchange_rate::monitoring_fx_rate_index().await;
match result { match result {
Ok(T) => { Ok(T) => {
tx_task14 tx_task12
.send(14) .send(12)
.expect("The mpsc channel has been closed."); .expect("The mpsc channel has been closed.");
} }
Err(E) => {} Err(E) => {}
@ -936,14 +943,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}); });
} }
// // // Task#15: monitoring dollar index // // // Task#13: monitoring dollar index
// // tokio::task::spawn(async move { // // tokio::task::spawn(async move {
// // loop // // loop
// // { // // {
// // let result = signal_association::dollar_index::monitoring_dollar_index().await; // // let result = signal_association::dollar_index::monitoring_dollar_index().await;
// // match result { // // match result {
// // Ok(T) => { // // Ok(T) => {
// // tx_task15.send(15).expect("The mpsc channel has been closed."); // // tx_task13.send(13).expect("The mpsc channel has been closed.");
// // } // // }
// // Err(E) => {} // // Err(E) => {}
// // } // // }
@ -951,7 +958,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// // } // // }
// // }); // // });
// Task#16: monitoring signal decision // Task#14: monitoring signal decision
if RUNNING_MODE == REAL || RUNNING_MODE == SIMUL || RUNNING_MODE == TEST { if RUNNING_MODE == REAL || RUNNING_MODE == SIMUL || RUNNING_MODE == TEST {
tokio::task::spawn(async move { tokio::task::spawn(async move {
loop { loop {
@ -959,8 +966,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
signal_association::signal_decision::monitoring_signal_decision().await; signal_association::signal_decision::monitoring_signal_decision().await;
match result { match result {
Ok(T) => { Ok(T) => {
tx_task16 tx_task14
.send(16) .send(14)
.expect("The mpsc channel has been closed."); .expect("The mpsc channel has been closed.");
} }
Err(E) => {} Err(E) => {}
@ -971,15 +978,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}); });
} }
// Task#17: monitoring future ratio // Task#15: monitoring future ratio
if RUNNING_MODE == REAL || RUNNING_MODE == SIMUL || RUNNING_MODE == TEST { if RUNNING_MODE == REAL || RUNNING_MODE == SIMUL || RUNNING_MODE == TEST {
tokio::task::spawn(async move { tokio::task::spawn(async move {
loop { loop {
let result = signal_association::future_ratio::monitoring_future_ratio().await; let result = signal_association::future_ratio::monitoring_future_ratio().await;
match result { match result {
Ok(T) => { Ok(T) => {
tx_task17 tx_task15
.send(17) .send(15)
.expect("The mpsc channel has been closed."); .expect("The mpsc channel has been closed.");
} }
Err(E) => {} Err(E) => {}
@ -991,7 +998,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
// COEX part // COEX part
// Task#18: strategists // Task#16: execute strategis for buy
if RUNNING_MODE == REAL || RUNNING_MODE == SIMUL { if RUNNING_MODE == REAL || RUNNING_MODE == SIMUL {
tokio::task::spawn(async move { tokio::task::spawn(async move {
sleep(Duration::from_secs(40)).await; sleep(Duration::from_secs(40)).await;
@ -1005,19 +1012,19 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
all_data.rt_price_1m_vec = rx3_rt_price_1m_vec.borrow().clone(); all_data.rt_price_1m_vec = rx3_rt_price_1m_vec.borrow().clone();
all_data.rt_price_30m_vec = rx3_rt_price_30m_vec.borrow().clone(); all_data.rt_price_30m_vec = rx3_rt_price_30m_vec.borrow().clone();
all_data.rt_price_1d_vec = rx3_rt_price_1d_vec.borrow().clone(); all_data.rt_price_1d_vec = rx3_rt_price_1d_vec.borrow().clone();
// all_data.rt_price_1w_vec = rx3_rt_price_1w_vec.borrow().clone(); all_data.rt_price_1w_vec = rx3_rt_price_1w_vec.borrow().clone();
// all_data.rt_price_1mon_vec = rx3_rt_price_1mon_vec.borrow().clone(); all_data.rt_price_1mon_vec = rx3_rt_price_1mon_vec.borrow().clone();
let result = coex::strategy_team::execute_strategists(&all_data).await; let result = strategy_team::strategy_manager::execute_list_up_for_buy(&all_data).await;
match result { match result {
Ok(T) => { Ok(T) => {
tx_task18 tx_task16
.send(18) .send(16)
.expect("The mpsc channel has been closed."); .expect("The mpsc channel has been closed.");
} }
Err(E) => { Err(E) => {
eprintln!("Couldn't execute strategists."); // eprintln!("Couldn't execute strategists.");
} }
} }
@ -1047,8 +1054,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// match result { // match result {
// Ok(T) => { // Ok(T) => {
// tx_task18 // tx_task16
// .send(18) // .send(16)
// .expect("The mpsc channel has been closed."); // .expect("The mpsc channel has been closed.");
// } // }
// Err(E) => {} // Err(E) => {}
@ -1063,7 +1070,49 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}); });
} }
// Task#19: monitoring pre-suggested coins // Task#17: execute strategis for sell
if RUNNING_MODE == REAL || RUNNING_MODE == SIMUL {
tokio::task::spawn(async move {
sleep(Duration::from_secs(40)).await;
let mut all_data = AllData::new();
let mut exchange_info_vec: Vec<ExchangeInfo> = Vec::new();
let mut trade_fee_vec: Vec<TradeFee> = Vec::new();
let mut elapsed_time = 0;
loop {
let instant = Instant::now();
all_data.valid_symbol_vec = rx4_valid_usdt_trade_vec.borrow().clone();
exchange_info_vec = rx6_exchange_info_data.borrow().clone();
trade_fee_vec = rx5_tradefee_vec.borrow().clone();
// realtime price data
all_data.rt_price_1m_vec = rx5_rt_price_1m_vec.borrow().clone();
all_data.rt_price_30m_vec = rx5_rt_price_30m_vec.borrow().clone();
all_data.rt_price_1d_vec = rx4_rt_price_1d_vec.borrow().clone();
all_data.rt_price_1w_vec = rx4_rt_price_1w_vec.borrow().clone();
all_data.rt_price_1mon_vec = rx4_rt_price_1mon_vec.borrow().clone();
let result = strategy_team::strategy_manager::execute_list_up_for_sell(&all_data, &exchange_info_vec, &trade_fee_vec).await;
match result {
Ok(T) => {
tx_task17
.send(17)
.expect("The mpsc channel has been closed.");
}
Err(E) => {
// eprintln!("Couldn't execute strategists.");
}
}
// sleep as much as the loop recurs per 1 second if all operation finished within 1 second.
elapsed_time = instant.elapsed().as_millis();
if 250 > elapsed_time {
sleep(Duration::from_millis((250 - elapsed_time) as u64)).await;
}
}
});
}
// Task#18: monitoring pre-suggested coins
tokio::task::spawn(async move { tokio::task::spawn(async move {
sleep(Duration::from_secs(30)).await; sleep(Duration::from_secs(30)).await;
let mut elapsed_time = 0; let mut elapsed_time = 0;
@ -1075,8 +1124,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// send Task#0 a message to notify running on // send Task#0 a message to notify running on
match result { match result {
Ok(T) => { Ok(T) => {
tx_task19 tx_task18
.send(19) .send(18)
.expect("The mpsc channel has been closed."); .expect("The mpsc channel has been closed.");
} }
Err(E) => {} Err(E) => {}
@ -1090,7 +1139,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
}); });
// Task#20: buy_coin // Task#19: buy_coin
if RUNNING_MODE == REAL || RUNNING_MODE == SIMUL || RUNNING_MODE == TEST { if RUNNING_MODE == REAL || RUNNING_MODE == SIMUL || RUNNING_MODE == TEST {
tokio::task::spawn(async move { tokio::task::spawn(async move {
sleep(Duration::from_secs(30)).await; sleep(Duration::from_secs(30)).await;
@ -1109,8 +1158,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// send Task#0 a message to notify running on // send Task#0 a message to notify running on
match result { match result {
Ok(T) => { Ok(T) => {
tx_task20 tx_task19
.send(20) .send(19)
.expect("The mpsc channel has been closed."); .expect("The mpsc channel has been closed.");
} }
Err(E) => { Err(E) => {
@ -1143,8 +1192,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// send Task#0 a message to notify running on // send Task#0 a message to notify running on
match result { match result {
Ok(T) => { Ok(T) => {
tx_task20 tx_task19
.send(20) .send(19)
.expect("The mpsc channel has been closed."); .expect("The mpsc channel has been closed.");
} }
Err(E) => {} Err(E) => {}
@ -1158,7 +1207,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}); });
} }
// Task#21: monitoring_open_buy_order // Task#20: monitoring_open_buy_order
if RUNNING_MODE == REAL || RUNNING_MODE == TEST { if RUNNING_MODE == REAL || RUNNING_MODE == TEST {
tokio::task::spawn(async move { tokio::task::spawn(async move {
if RUNNING_MODE == REAL { if RUNNING_MODE == REAL {
@ -1185,8 +1234,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// send Task#0 a message to notify running on // send Task#0 a message to notify running on
match result { match result {
Ok(T) => { Ok(T) => {
tx_task21 tx_task20
.send(21) .send(20)
.expect("The mpsc channel has been closed."); .expect("The mpsc channel has been closed.");
} }
Err(E) => {} Err(E) => {}
@ -1201,7 +1250,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}); });
} }
// Task#22: monitoring_filled_buy_order // Task#21: update_price_of_filled_buy_order
tokio::task::spawn(async move { tokio::task::spawn(async move {
if RUNNING_MODE == TEST { if RUNNING_MODE == TEST {
sleep(Duration::from_secs(10)).await; sleep(Duration::from_secs(10)).await;
@ -1209,18 +1258,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
sleep(Duration::from_secs(30)).await; sleep(Duration::from_secs(30)).await;
} }
let mut elapsed_time = 0; let mut elapsed_time = 0;
let mut all_data = AllData::new();
loop { loop {
let instant = Instant::now(); let instant = Instant::now();
let coin_price_vec = rx5_price_vec.borrow().clone(); let coin_price_vec = rx5_price_vec.borrow().clone();
let exchange_info_vec = rx2_exchange_info_data.borrow().clone(); let exchange_info_vec = rx2_exchange_info_data.borrow().clone();
let trade_fee_vec = rx3_tradefee_vec.borrow().clone(); let trade_fee_vec = rx3_tradefee_vec.borrow().clone();
// realtime price data let result = coex::order_team::update_price_of_filled_buy_order(
all_data.rt_price_30m_vec = rx4_rt_price_30m_vec.borrow().clone();
let result = coex::order_team::monitoring_filled_buy_order(
&all_data,
&coin_price_vec, &coin_price_vec,
&exchange_info_vec, &exchange_info_vec,
&trade_fee_vec, &trade_fee_vec,
@ -1230,8 +1274,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// send Task#0 a message to notify running on // send Task#0 a message to notify running on
match result { match result {
Ok(T) => { Ok(T) => {
tx_task22 tx_task21
.send(22) .send(21)
.expect("The mpsc channel has been closed."); .expect("The mpsc channel has been closed.");
} }
Err(E) => {} Err(E) => {}
@ -1246,7 +1290,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
}); });
// Task#23: monitoring_open_sell_order // Task#22: monitoring_open_sell_order
if RUNNING_MODE == REAL || RUNNING_MODE == TEST { if RUNNING_MODE == REAL || RUNNING_MODE == TEST {
tokio::task::spawn(async move { tokio::task::spawn(async move {
if RUNNING_MODE == REAL { if RUNNING_MODE == REAL {
@ -1273,8 +1317,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// send Task#0 a message to notify running on // send Task#0 a message to notify running on
match result { match result {
Ok(T) => { Ok(T) => {
tx_task23 tx_task22
.send(23) .send(22)
.expect("The mpsc channel has been closed."); .expect("The mpsc channel has been closed.");
} }
Err(E) => {} Err(E) => {}
@ -1289,7 +1333,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}); });
} }
// Task#24: monitoring_filled_sell_order // Task#23: monitoring_filled_sell_order
tokio::task::spawn(async move { tokio::task::spawn(async move {
let client = ClientBuilder::new() let client = ClientBuilder::new()
.timeout(tokio::time::Duration::from_millis(3000)) .timeout(tokio::time::Duration::from_millis(3000))
@ -1300,6 +1344,36 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let instant = Instant::now(); let instant = Instant::now();
let result = coex::order_team::monitoring_filled_sell_order(&client).await; let result = coex::order_team::monitoring_filled_sell_order(&client).await;
// send Task#0 a message to notify running on
match result {
Ok(T) => {
tx_task23
.send(23)
.expect("The mpsc channel has been closed.");
}
Err(E) => {}
}
// sleep as much as the loop recurs per 1 second if all operation finished within 1 second.
elapsed_time = instant.elapsed().as_millis();
if 200 > elapsed_time {
sleep(Duration::from_millis((200 - elapsed_time) as u64)).await;
}
}
});
// Task#24: monitoring_scoreboard
tokio::task::spawn(async move {
let mut elapsed_time = 0;
let mut all_data = AllData::new();
loop {
let instant = Instant::now();
// realtime price data
all_data.rt_price_1m_vec = rx4_rt_price_1m_vec.borrow().clone();
let result = coex::exchange_team::monitoring_scoreboard(&all_data).await;
// send Task#0 a message to notify running on // send Task#0 a message to notify running on
match result { match result {
Ok(T) => { Ok(T) => {
@ -1318,37 +1392,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
}); });
// Task#25: monitoring_scoreboard // Task#25: update current_total_usdt and available_usdt
tokio::task::spawn(async move {
let mut elapsed_time = 0;
let mut all_data = AllData::new();
loop {
let instant = Instant::now();
// realtime price data
all_data.rt_price_1m_vec = rx4_rt_price_1m_vec.borrow().clone();
let result = coex::exchange_team::monitoring_scoreboard(&all_data).await;
// send Task#0 a message to notify running on
match result {
Ok(T) => {
tx_task25
.send(25)
.expect("The mpsc channel has been closed.");
}
Err(E) => {}
}
// sleep as much as the loop recurs per 1 second if all operation finished within 1 second.
elapsed_time = instant.elapsed().as_millis();
if 200 > elapsed_time {
sleep(Duration::from_millis((200 - elapsed_time) as u64)).await;
}
}
});
// Task#26: update current_total_usdt and available_usdt
tokio::task::spawn(async move { tokio::task::spawn(async move {
let client = ClientBuilder::new() let client = ClientBuilder::new()
.timeout(tokio::time::Duration::from_millis(3000)) .timeout(tokio::time::Duration::from_millis(3000))
@ -1365,8 +1409,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// send Task#0 a message to notify running on // send Task#0 a message to notify running on
match result { match result {
Ok(T) => { Ok(T) => {
tx_task26 tx_task25
.send(26) .send(25)
.expect("The mpsc channel has been closed."); .expect("The mpsc channel has been closed.");
} }
Err(E) => { Err(E) => {
@ -1382,6 +1426,34 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
}); });
// Task#26: update kelly_criterion
tokio::task::spawn(async move {
let mut elapsed_time = 0;
loop {
let instant = Instant::now();
let result =
coex::assets_managing_team::update_kelly_criterion().await;
// send Task#0 a message to notify running on
match result {
Ok(T) => {
tx_task26
.send(26)
.expect("The mpsc channel has been closed.");
}
Err(E) => {
println!("{}", E);
}
}
// sleep as much as the loop recurs per 1 minutes
elapsed_time = instant.elapsed().as_secs();
if 60 > elapsed_time {
sleep(Duration::from_secs((60 - elapsed_time) as u64)).await;
}
}
});
loop { loop {
// println!("test limit order 실행"); // println!("test limit order 실행");
// let client = ClientBuilder::new().timeout(Duration::from_millis(1000)).build().unwrap(); // let client = ClientBuilder::new().timeout(Duration::from_millis(1000)).build().unwrap();

63
src/strategy_team/mod.rs Normal file
View File

@ -0,0 +1,63 @@
pub mod strategy_manager;
pub mod strategy_001;
pub mod strategy_002;
pub mod strategy_003;
pub mod strategy_004;
pub mod strategy_005;
pub mod strategy_006;
use std::{sync::Arc};
use crate::database_control::*;
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
use crate::value_estimation_team::indicators::macd::{ema_macd, EmaMacd};
use crate::value_estimation_team::indicators::rsi::{rsi, RsiData};
use crate::value_estimation_team::indicators::sma::{sma, SmaData};
use crate::value_estimation_team::indicators::ema::{ema, EmaData};
use crate::value_estimation_team::indicators::bollingerband::{bollingerband, BollingerBandData};
use crate::value_estimation_team::indicators::stoch_rsi::{stoch_rsi, StochRsiData};
use crate::value_estimation_team::indicators::supertrend::{supertrend, SupertrendData};
use crate::value_estimation_team::indicators::heatmap_volume::{
heatmap_volume, HeatMapLevel, HeatmapVolumeData,
};
use crate::coex::order_team::{limit_order_sell, select_filled_buy_orders};
use crate::coin_health_check_team::request_others::{ExchangeInfo, TradeFee};
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 sqlx::FromRow;
use tokio::sync::Mutex;
#[derive(Debug)]
pub struct AllData {
pub valid_symbol_vec: Vec<String>,
pub rt_price_1m_vec: Vec<(String, Vec<RealtimePriceData>)>,
pub rt_price_30m_vec: Vec<(String, Vec<RealtimePriceData>)>,
pub rt_price_1d_vec: Vec<(String, Vec<RealtimePriceData>)>,
pub rt_price_1w_vec: Vec<(String, Vec<RealtimePriceData>)>,
pub rt_price_1mon_vec: Vec<(String, Vec<RealtimePriceData>)>,
}
impl AllData {
pub fn new() -> AllData {
let a = AllData {
valid_symbol_vec: Vec::new(),
rt_price_1m_vec: Vec::new(),
rt_price_30m_vec: Vec::new(),
rt_price_1d_vec: Vec::new(),
rt_price_1w_vec: Vec::new(),
rt_price_1mon_vec: Vec::new(),
};
a
}
}
#[derive(Debug, FromRow)]
pub struct TimeData {
pub server_epoch: u64,
pub local_epoch: u64,
pub epoch_difference: i64,
pub server_ymdhs: String,
pub local_ymdhs: String,
pub last_server_epoch: u64,
pub last_server_ymdhs: String,
}

View File

@ -0,0 +1,424 @@
// pub async fn strategist_001(
// alldata: &AllData,
// ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// // 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 10, multiplier: 1.3, 30m close price), the area should be in SELL area.
// // let mut filtered_2nd_symbols: Vec<(String, i64)> = Vec::new();
// // let mut filtered_2nd_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
// // 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<RealtimePriceData> = Vec::new();
// // let mut supertrend_vec: Vec<SupertrendData> = 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, 10, 1.3, true).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();
// // 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("DOWN")
// // {
// // 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?;
// // 1st filtering: making basic form
// let mut filtered_2nd_symbols: Vec<(String, i64)> = Vec::new();
// let mut filtered_2nd_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
// 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<RealtimePriceData> = 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);
// if opclo_30m_option.is_some() {
// opclo_30m_vec = rt_price_30m_vec_c[opclo_30m_option.unwrap()].1.clone();
// if opclo_30m_vec.len() >= 3 {
// 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?;
// // 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");
// let mut filtered_3rd_symbols: Vec<(String, i64)> = Vec::new();
// let mut filtered_3rd_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
// Arc::new(Mutex::new(filtered_3rd_symbols)); // (symbol, closetime)
// let mut task_vec = Vec::new();
// 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(1.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 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?;
// // 3rd filtering: BollingerBand (length 10, stddev: 2.5, 30m close price) the current price should be under the lowerband of BB.
// let filtered_3rd_symbols_c = filtered_3rd_symbols_arc.lock().await.clone();
// let sma10_30m_data: Vec<(String, Vec<SmaData>)> = sma(
// 10,
// &alldata.rt_price_30m_vec,
// &filtered_3rd_symbols_c,
// )
// .await?;
// let bb10_30m_data: Vec<(String, Vec<BollingerBandData>)> =
// bollingerband(
// 10,
// 3.0,
// &sma10_30m_data,
// &alldata.rt_price_30m_vec,
// &filtered_3rd_symbols_c,
// )
// .await?;
// let mut task_vec = Vec::new();
// let mut filtered_4th_symbols: Vec<(String, i64)> = Vec::new();
// let mut filtered_4th_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
// Arc::new(Mutex::new(filtered_4th_symbols)); // (symbol, closetime)
// for element in filtered_3rd_symbols_c {
// let mut bb10_30m_vec: Vec<BollingerBandData> = Vec::new();
// let bb10_30m_option = bb10_30m_data.iter().position(|x| *x.0 == element.0);
// let bb10_30m_option_c = bb10_30m_option.clone();
// let element_c = element.clone();
// let filtered_4th_symbols_arc_c = Arc::clone(&filtered_4th_symbols_arc);
// if bb10_30m_option_c.is_some() {
// bb10_30m_vec = bb10_30m_data[bb10_30m_option_c.unwrap()].1.clone();
// if bb10_30m_vec.len() >= 3 {
// let bb10_30m_vec_c = bb10_30m_vec.clone();
// let current_price = get_current_price(&element_c.0, &alldata.rt_price_30m_vec)
// .await
// .unwrap();
// task_vec.push(tokio::spawn(async move {
// let bb_search_result = bb10_30m_vec_c.binary_search_by_key(
// &element_c.1,
// |&BollingerBandData {
// sma,
// upperband,
// lowerband,
// close_time,
// }| close_time,
// );
// if bb_search_result.is_ok() {
// if bb10_30m_vec_c[bb_search_result.unwrap()].lowerband > current_price {
// 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?;
// // 4th filtering: the current price should be lower than lowest price from the latest 20 candles.
// let mut task_vec = Vec::new();
// let filtered_4th_symbols_c = filtered_4th_symbols_arc.lock().await.clone();
// let mut filtered_5th_symbols: Vec<(String, i64)> = Vec::new();
// let mut filtered_5th_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
// Arc::new(Mutex::new(filtered_5th_symbols)); // (symbol, closetime)
// for element in filtered_4th_symbols_c {
// let rt_price_30m_option = alldata.rt_price_30m_vec.iter().position(|x| *x.0 == element.0);
// let element_c = element.clone();
// let filtered_5th_symbols_arc_c = Arc::clone(&filtered_5th_symbols_arc);
// if rt_price_30m_option.is_some() {
// let mut rt_price_30m_vec_c = alldata.rt_price_30m_vec[rt_price_30m_option.unwrap()].1.clone();
// let current_price = get_current_price(&element_c.0, &alldata.rt_price_30m_vec)
// .await
// .unwrap();
// task_vec.push(tokio::spawn(async move {
// if rt_price_30m_vec_c.len() >= 21 {
// rt_price_30m_vec_c.pop();
// rt_price_30m_vec_c.reverse();
// rt_price_30m_vec_c.truncate(20);
// let lowest_price_option = rt_price_30m_vec_c.iter()
// .enumerate()
// .min_by(|(_, a), (_, b)| {
// a.low_price
// .partial_cmp(&b.low_price)
// .expect("Nan was forbidden.")
// })
// .map(|(index, _)| index);
// if lowest_price_option.is_some() {
// let lowest_price = rt_price_30m_vec_c[lowest_price_option.unwrap()].low_price;
// if lowest_price > current_price {
// let mut filtered_5th_symbols_lock =
// filtered_5th_symbols_arc_c.lock().await;
// filtered_5th_symbols_lock.push(element_c);
// }
// }
// }
// }));
// }
// }
// try_join_all(task_vec).await?;
// // 5th filtering: RSI (length: 10, 30m close price) the current index should be lower than 30.
// let filtered_5th_symbol_c = filtered_5th_symbols_arc.lock().await.clone();
// let mut rsi10_30m_data: Vec<(String, Vec<RsiData>)> = rsi(
// 10,
// &alldata.rt_price_30m_vec,
// &filtered_5th_symbol_c,
// )
// .await?;
// let mut task_vec = Vec::new();
// let mut filtered_6th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
// let mut filtered_6th_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
// Arc::new(Mutex::new(filtered_6th_symbols)); // (symbol, closetime)
// for element in filtered_5th_symbol_c {
// let rsi10_30m_option = rsi10_30m_data.iter().position(|x| *x.0 == element.0);
// let filtered_6th_symbols_arc_c = Arc::clone(&filtered_6th_symbols_arc);
// if rsi10_30m_option.is_some() {
// let mut rsi10_30m_vec = rsi10_30m_data[rsi10_30m_option.unwrap()].1.clone();
// if rsi10_30m_vec.len() >= 3 {
// let element_c = element.clone();
// task_vec.push(tokio::spawn(async move {
// let rsi_search_result = rsi10_30m_vec.binary_search_by_key(
// &element.1,
// |&RsiData {
// rsi_value,
// close_time,
// }| close_time,
// );
// if rsi_search_result.is_ok() {
// if rsi10_30m_vec[rsi_search_result.unwrap()].rsi_value <= 20.0 {
// let mut filtered_6th_symbols_lock =
// filtered_6th_symbols_arc_c.lock().await;
// filtered_6th_symbols_lock.push(element_c);
// }
// }
// }));
// }
// }
// }
// try_join_all(task_vec).await?;
// // 6th filtering: StochRSI (RSI length: 14, Stoch length: 14, smooth k: 3, smooth d: 3) smooth kn <= 10, kn-1 <= 25.0
// let filtered_6th_symbol_c = filtered_6th_symbols_arc.lock().await.clone();
// let mut rsi14_30m_data: Vec<(String, Vec<RsiData>)> = rsi(
// 14,
// &alldata.rt_price_30m_vec,
// &filtered_6th_symbol_c,
// )
// .await?;
// let stoch_rsi_data = stoch_rsi(&rsi14_30m_data, 14, 3, 3).await?;
// let mut stoch_rsi14_30m_vec: Vec<StochRsiData> = Vec::new();
// let mut filtered_7th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
// for element in filtered_6th_symbol_c {
// let stoch_rsi14_30m_option = stoch_rsi_data.iter().position(|x| *x.0 == element.0);
// if stoch_rsi14_30m_option.is_some() {
// stoch_rsi14_30m_vec = stoch_rsi_data[stoch_rsi14_30m_option.unwrap()].1.clone();
// if stoch_rsi14_30m_vec.len() >= 3 {
// let stoch_rsi_search_result = stoch_rsi14_30m_vec.binary_search_by_key(
// &element.1,
// |&StochRsiData {
// k,
// d,
// close_time,
// }| close_time,
// );
// if stoch_rsi_search_result.is_ok() {
// if stoch_rsi14_30m_vec[stoch_rsi_search_result.unwrap()].k <= 10.0 && stoch_rsi14_30m_vec[stoch_rsi_search_result.unwrap()-1].k <= 25.0 {
// filtered_7th_symbols.push(element);
// }
// }
// }
// }
// }
// // 7th filtering: heatmap volume(MA length 10, std length 10, 30m close price), the current candle should be over than high at least.
// let mut filtered_8th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
// for element in filtered_7th_symbols {
// let rt_price_30m_vec_c = alldata.rt_price_30m_vec.clone();
// let opclo_30m_option = rt_price_30m_vec_c.iter().position(|x| *x.0 == element.0);
// if opclo_30m_option.is_some() {
// let opclo_30m_vec = rt_price_30m_vec_c[opclo_30m_option.unwrap()].1.clone();
// if opclo_30m_vec.len() >= 3 {
// let heatmap_volume_option =
// heatmap_volume(&element.0, &rt_price_30m_vec_c, 10, 10, 4.0, 2.5, 1.0, -0.5)
// .await;
// if heatmap_volume_option.is_some() {
// let heatmap_volume_vec = heatmap_volume_option.unwrap();
// let heatmap_search_result = heatmap_volume_vec.binary_search_by_key(
// &element.1,
// |HeatmapVolumeData {
// heatmap_value,
// heatmap_level,
// close_time,
// }| *close_time,
// );
// if heatmap_search_result.is_ok() {
// if heatmap_volume_vec[heatmap_search_result.unwrap()].heatmap_level
// == HeatMapLevel::Medium
// ||
// heatmap_volume_vec[heatmap_search_result.unwrap()].heatmap_level
// == HeatMapLevel::High
// || heatmap_volume_vec[heatmap_search_result.unwrap()].heatmap_level
// == HeatMapLevel::ExtraHigh
// {
// filtered_8th_symbols.push(element);
// }
// }
// }
// }
// }
// }
// // 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_8th_symbols {
// let mut filtered_symbols_arc_c = Arc::clone(&filtered_symbols_arc);
// let rt_price_30m_vec_c = alldata.rt_price_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,
// ));
// }
// }
// }));
// }
// try_join_all(task_vec).await?;
// // 6th filtering condition: MACD
// // let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
// // let mut ema3_1d_vec: &Vec<EmaData> = &Vec::new();
// // let mut ema10_1d_vec: &Vec<EmaData> = &Vec::new();
// // 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 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;
// // 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);
// // // 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(1, false, &a, alldata).await;
// Ok(())
// }

View File

@ -0,0 +1,277 @@
// pub async fn strategist_002(
// alldata: &AllData,
// ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// // 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: making basic form
// let mut filtered_2nd_symbols: Vec<(String, i64)> = Vec::new();
// let mut filtered_2nd_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
// 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<RealtimePriceData> = 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);
// if opclo_30m_option.is_some() {
// opclo_30m_vec = rt_price_30m_vec_c[opclo_30m_option.unwrap()].1.clone();
// if opclo_30m_vec.len() >= 3 {
// 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?;
// // 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");
// let mut filtered_3rd_symbols: Vec<(String, i64)> = Vec::new();
// let mut filtered_3rd_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
// Arc::new(Mutex::new(filtered_3rd_symbols)); // (symbol, closetime)
// let mut task_vec = Vec::new();
// 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(2.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 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?;
// // 3rd filtering: EMA30 > EMA 150
// let filtered_3rd_symbols_c = filtered_3rd_symbols_arc.lock().await.clone();
// let ema30_30m_data: Vec<(String, Vec<EmaData>)> = ema(
// 30,
// &alldata.rt_price_30m_vec,
// &filtered_3rd_symbols_c,
// )
// .await?;
// let ema150_30m_data: Vec<(String, Vec<EmaData>)> = ema(
// 150,
// &alldata.rt_price_30m_vec,
// &filtered_3rd_symbols_c,
// )
// .await?;
// let mut task_vec = Vec::new();
// let mut filtered_4th_symbols: Vec<(String, i64)> = Vec::new();
// let mut filtered_4th_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
// Arc::new(Mutex::new(filtered_4th_symbols)); // (symbol, closetime)
// for element in filtered_3rd_symbols_c {
// let mut ema30_30m_vec: Vec<EmaData> = Vec::new();
// let mut ema150_30m_vec: Vec<EmaData> = 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 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();
// 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();
// 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,
// );
// 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?;
// // 6th filtering: StochRSI (RSI length: 10, Stoch length: 10, smooth k: 3, smooth d: 3) smooth dn == 0, kn == 0, kn-1 < 5
// let filtered_4th_symbol_c = filtered_4th_symbols_arc.lock().await.clone();
// let mut rsi10_30m_data: Vec<(String, Vec<RsiData>)> = 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<StochRsiData> = 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);
// if stoch_rsi10_30m_option.is_some() {
// stoch_rsi10_30m_vec = stoch_rsi_data[stoch_rsi10_30m_option.unwrap()].1.clone();
// 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 stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap()].k <= 5.0 &&
// stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap()].d <= 5.0 &&
// stoch_rsi10_30m_vec[stoch_rsi_search_result.unwrap()-1].k <= 5.0 {
// filtered_5th_symbols.push(element);
// }
// }
// }
// }
// }
// // 7th filtering: heatmap volume(MA length 10, std length 10, 30m close price), the current candle should be over than high at least.
// let mut filtered_6th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
// for element in filtered_5th_symbols {
// let rt_price_30m_vec_c = alldata.rt_price_30m_vec.clone();
// let opclo_30m_option = rt_price_30m_vec_c.iter().position(|x| *x.0 == element.0);
// if opclo_30m_option.is_some() {
// let opclo_30m_vec = rt_price_30m_vec_c[opclo_30m_option.unwrap()].1.clone();
// if opclo_30m_vec.len() >= 3 {
// let heatmap_volume_option =
// heatmap_volume(&element.0, &rt_price_30m_vec_c, 10, 10, 4.0, 2.5, 1.0, -0.5)
// .await;
// if heatmap_volume_option.is_some() {
// let heatmap_volume_vec = heatmap_volume_option.unwrap();
// let heatmap_search_result = heatmap_volume_vec.binary_search_by_key(
// &element.1,
// |HeatmapVolumeData {
// heatmap_value,
// heatmap_level,
// close_time,
// }| *close_time,
// );
// if heatmap_search_result.is_ok() {
// if
// // heatmap_volume_vec[heatmap_search_result.unwrap()].heatmap_level
// // == HeatMapLevel::Medium
// // ||
// heatmap_volume_vec[heatmap_search_result.unwrap()].heatmap_level
// == HeatMapLevel::High
// || heatmap_volume_vec[heatmap_search_result.unwrap()].heatmap_level
// == HeatMapLevel::ExtraHigh
// {
// filtered_6th_symbols.push(element);
// }
// }
// }
// }
// }
// }
// // 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_6th_symbols {
// let mut filtered_symbols_arc_c = Arc::clone(&filtered_symbols_arc);
// let rt_price_30m_vec_c = alldata.rt_price_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,
// ));
// }
// }
// }));
// }
// try_join_all(task_vec).await?;
// let a = filtered_symbols_arc.lock().await.clone();
// insert_pre_suggested_coins(2, false, &a, alldata).await;
// Ok(())
// }

View File

@ -0,0 +1,449 @@
use super::{limit_order_sell, AllData, RealtimePriceData, Mutex, Arc, try_join_all, exists_record, StochRsiData, EmaData, SupertrendData, RsiData, stoch_rsi, ema, rsi, supertrend, select_filled_buy_orders, ExchangeInfo, TradeFee, Client, ClientBuilder, dec, RoundingStrategy};
pub async fn list_up_for_buy(
alldata: &AllData,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// 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<Mutex<Vec<(String, i64)>>> =
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<RealtimePriceData> = Vec::new();
let mut supertrend_vec: Vec<SupertrendData> = 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;
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();
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?;
// 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");
let mut filtered_3rd_symbols: Vec<(String, i64)> = Vec::new();
let mut filtered_3rd_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
Arc::new(Mutex::new(filtered_3rd_symbols)); // (symbol, closetime)
let mut task_vec = Vec::new();
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 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?;
// 3rd filtering: EMA30 > EMA 150
let filtered_3rd_symbols_c = filtered_3rd_symbols_arc.lock().await.clone();
let ema30_30m_data: Vec<(String, Vec<EmaData>)> = ema(
30,
&alldata.rt_price_30m_vec,
&filtered_3rd_symbols_c,
)
.await?;
let ema150_30m_data: Vec<(String, Vec<EmaData>)> = ema(
150,
&alldata.rt_price_30m_vec,
&filtered_3rd_symbols_c,
)
.await?;
let mut task_vec = Vec::new();
let mut filtered_4th_symbols: Vec<(String, i64)> = Vec::new();
let mut filtered_4th_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
Arc::new(Mutex::new(filtered_4th_symbols)); // (symbol, closetime)
for element in filtered_3rd_symbols_c {
let mut ema30_30m_vec: Vec<EmaData> = Vec::new();
let mut ema150_30m_vec: Vec<EmaData> = 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 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();
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();
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,
);
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?;
// 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<RsiData>)> = 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<StochRsiData> = 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);
if stoch_rsi10_30m_option.is_some() {
stoch_rsi10_30m_vec = stoch_rsi_data[stoch_rsi10_30m_option.unwrap()].1.clone();
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);
}
}
}
}
}
// 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();
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,
));
}
}
}));
}
try_join_all(task_vec).await?;
// TODO: abnormal price filtering (too high current price)
// 6th filtering condition: MACD
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
// let mut ema3_1d_vec: &Vec<EmaData> = &Vec::new();
// let mut ema10_1d_vec: &Vec<EmaData> = &Vec::new();
// 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 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;
// 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);
// // 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).await;
Ok(())
}
pub async fn list_up_for_sell(
all_data: &AllData,
exchange_info_vec: &Vec<ExchangeInfo>,
trade_fee_vec: &Vec<TradeFee>,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let filled_buy_orders = select_filled_buy_orders(3).await?;
if !filled_buy_orders.is_empty() {
let client = ClientBuilder::new()
.timeout(tokio::time::Duration::from_millis(5000))
.build()
.unwrap();
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 lot_step_size_option = exchange_info_vec
.iter()
.find(|ExchangeInfo| ExchangeInfo.symbol == element.symbol);
let quote_commission_precision_option = exchange_info_vec
.iter()
.find(|ExchangeInfo| ExchangeInfo.symbol == element.symbol);
let opclo_30m_option = all_data
.rt_price_30m_vec
.iter()
.position(|x| *x.0 == element.symbol);
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,
);
let mut opclo_30m_vec = all_data.rt_price_30m_vec[opclo_30m_option.unwrap()]
.1
.clone();
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;
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(())
}

View File

@ -0,0 +1,268 @@
// pub async fn strategist_004(
// alldata: &AllData,
// ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// // 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 10, multiplier: 2.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<Mutex<Vec<(String, i64)>>> =
// 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<RealtimePriceData> = Vec::new();
// let mut supertrend_vec: Vec<SupertrendData> = 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, 10, 2.0, true).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();
// 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?;
// // 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");
// let mut filtered_3rd_symbols: Vec<(String, i64)> = Vec::new();
// let mut filtered_3rd_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
// Arc::new(Mutex::new(filtered_3rd_symbols)); // (symbol, closetime)
// let mut task_vec = Vec::new();
// 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(4.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 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?;
// // 3rd filtering: EMA30 >= EMA 150
// let filtered_3rd_symbols_c = filtered_3rd_symbols_arc.lock().await.clone();
// let ema30_30m_data: Vec<(String, Vec<EmaData>)> = ema(
// 30,
// &alldata.rt_price_30m_vec,
// &filtered_3rd_symbols_c,
// )
// .await?;
// let ema150_30m_data: Vec<(String, Vec<EmaData>)> = ema(
// 150,
// &alldata.rt_price_30m_vec,
// &filtered_3rd_symbols_c,
// )
// .await?;
// let mut task_vec = Vec::new();
// let mut filtered_4th_symbols: Vec<(String, i64)> = Vec::new();
// let mut filtered_4th_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
// Arc::new(Mutex::new(filtered_4th_symbols)); // (symbol, closetime)
// for element in filtered_3rd_symbols_c {
// let mut ema30_30m_vec: Vec<EmaData> = Vec::new();
// let mut ema150_30m_vec: Vec<EmaData> = 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 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();
// 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();
// 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,
// );
// if ema30_search_result.is_ok() && ema150_search_result.is_ok() {
// if ema30_30m_vec_c[ema30_search_result.unwrap()-9].ema_value < ema150_30m_vec_c[ema150_search_result.unwrap()-9].ema_value &&
// ema30_30m_vec_c[ema30_search_result.unwrap()-8].ema_value < ema150_30m_vec_c[ema150_search_result.unwrap()-8].ema_value &&
// ema30_30m_vec_c[ema30_search_result.unwrap()-7].ema_value < ema150_30m_vec_c[ema150_search_result.unwrap()-7].ema_value &&
// ema30_30m_vec_c[ema30_search_result.unwrap()-6].ema_value < ema150_30m_vec_c[ema150_search_result.unwrap()-6].ema_value &&
// ema30_30m_vec_c[ema30_search_result.unwrap()-5].ema_value < ema150_30m_vec_c[ema150_search_result.unwrap()-5].ema_value &&
// ema30_30m_vec_c[ema30_search_result.unwrap()-4].ema_value < ema150_30m_vec_c[ema150_search_result.unwrap()-4].ema_value &&
// 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?;
// // 4th filtering: heatmap volume(MA length 10, std length 10, 30m close price), the current candle should be Normal or Low.
// let filtered_4th_symbols_c = filtered_4th_symbols_arc.lock().await.clone();
// let mut filtered_5th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
// for element in filtered_4th_symbols_c {
// let rt_price_30m_vec_c = alldata.rt_price_30m_vec.clone();
// let opclo_30m_option = rt_price_30m_vec_c.iter().position(|x| *x.0 == element.0);
// if opclo_30m_option.is_some() {
// let opclo_30m_vec = rt_price_30m_vec_c[opclo_30m_option.unwrap()].1.clone();
// if opclo_30m_vec.len() >= 3 {
// let heatmap_volume_option =
// heatmap_volume(&element.0, &rt_price_30m_vec_c, 10, 10, 4.0, 2.5, 1.0, -0.5)
// .await;
// if heatmap_volume_option.is_some() {
// let heatmap_volume_vec = heatmap_volume_option.unwrap();
// let heatmap_search_result = heatmap_volume_vec.binary_search_by_key(
// &element.1,
// |HeatmapVolumeData {
// heatmap_value,
// heatmap_level,
// close_time,
// }| *close_time,
// );
// if heatmap_search_result.is_ok() {
// if (heatmap_volume_vec[heatmap_search_result.unwrap()].heatmap_level
// == HeatMapLevel::Low
// ||
// heatmap_volume_vec[heatmap_search_result.unwrap()].heatmap_level
// == HeatMapLevel::Normal) &&
// (heatmap_volume_vec[heatmap_search_result.unwrap()-1].heatmap_level
// == HeatMapLevel::Low
// ||
// heatmap_volume_vec[heatmap_search_result.unwrap()-1].heatmap_level
// == HeatMapLevel::Normal
// )
// {
// filtered_5th_symbols.push(element);
// }
// }
// }
// }
// }
// }
// // 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();
// 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,
// ));
// }
// }
// }));
// }
// try_join_all(task_vec).await?;
// let a = filtered_symbols_arc.lock().await.clone();
// insert_pre_suggested_coins(4, false, &a, alldata).await;
// Ok(())
// }

View File

@ -0,0 +1,192 @@
// pub async fn strategist_005(
// alldata: &AllData,
// ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// // 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 30, 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<Mutex<Vec<(String, i64)>>> =
// 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<RealtimePriceData> = Vec::new();
// let mut supertrend_vec: Vec<SupertrendData> = 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, 30, 6.0, true).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();
// 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()]
// .signal.as_ref().is_some_and(|signal| signal.contains("BUY"))
// {
// 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?;
// // 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");
// let mut filtered_3rd_symbols: Vec<(String, i64)> = Vec::new();
// let mut filtered_3rd_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
// Arc::new(Mutex::new(filtered_3rd_symbols)); // (symbol, closetime)
// let mut task_vec = Vec::new();
// 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(5.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 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?;
// // 3rd filtering: heatmap volume(MA length 10, std length 10, 30m close price), the current candle should be Normal or Low.
// let filtered_3rd_symbols_c = filtered_3rd_symbols_arc.lock().await.clone();
// let mut filtered_4th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
// for element in filtered_3rd_symbols_c {
// let rt_price_30m_vec_c = alldata.rt_price_30m_vec.clone();
// let opclo_30m_option = rt_price_30m_vec_c.iter().position(|x| *x.0 == element.0);
// if opclo_30m_option.is_some() {
// let opclo_30m_vec = rt_price_30m_vec_c[opclo_30m_option.unwrap()].1.clone();
// if opclo_30m_vec.len() >= 3 {
// let heatmap_volume_option =
// heatmap_volume(&element.0, &rt_price_30m_vec_c, 10, 10, 4.0, 2.5, 1.0, -0.5)
// .await;
// if heatmap_volume_option.is_some() {
// let heatmap_volume_vec = heatmap_volume_option.unwrap();
// let heatmap_search_result = heatmap_volume_vec.binary_search_by_key(
// &element.1,
// |HeatmapVolumeData {
// heatmap_value,
// heatmap_level,
// close_time,
// }| *close_time,
// );
// if heatmap_search_result.is_ok() {
// if (heatmap_volume_vec[heatmap_search_result.unwrap()].heatmap_level
// == HeatMapLevel::Low
// ||
// heatmap_volume_vec[heatmap_search_result.unwrap()].heatmap_level
// == HeatMapLevel::Normal) &&
// (heatmap_volume_vec[heatmap_search_result.unwrap()-1].heatmap_level
// == HeatMapLevel::Low
// ||
// heatmap_volume_vec[heatmap_search_result.unwrap()-1].heatmap_level
// == HeatMapLevel::Normal) &&
// (heatmap_volume_vec[heatmap_search_result.unwrap()-2].heatmap_level
// == HeatMapLevel::Low
// ||
// heatmap_volume_vec[heatmap_search_result.unwrap()-2].heatmap_level
// == HeatMapLevel::Normal)
// {
// filtered_4th_symbols.push(element);
// }
// }
// }
// }
// }
// }
// // 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_4th_symbols {
// let mut filtered_symbols_arc_c = Arc::clone(&filtered_symbols_arc);
// let rt_price_30m_vec_c = alldata.rt_price_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,
// ));
// }
// }
// }));
// }
// try_join_all(task_vec).await?;
// let a = filtered_symbols_arc.lock().await.clone();
// insert_pre_suggested_coins(5, false, &a, alldata).await;
// Ok(())
// }

View File

@ -0,0 +1,203 @@
// pub async fn strategist_006(
// alldata: &AllData,
// ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// // 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: making basic form
// let mut filtered_2nd_symbols: Vec<(String, i64)> = Vec::new();
// let mut filtered_2nd_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
// 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<RealtimePriceData> = 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);
// if opclo_30m_option.is_some() {
// opclo_30m_vec = rt_price_30m_vec_c[opclo_30m_option.unwrap()].1.clone();
// if opclo_30m_vec.len() >= 3 {
// 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?;
// // 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");
// let mut filtered_3rd_symbols: Vec<(String, i64)> = Vec::new();
// let mut filtered_3rd_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
// Arc::new(Mutex::new(filtered_3rd_symbols)); // (symbol, closetime)
// let mut task_vec = Vec::new();
// 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(6.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 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?;
// // 6th filtering: StochRSI (RSI length: 10, Stoch length: 10, smooth k: 3, smooth d: 3) smooth kn > kn-1
// let filtered_3rd_symbol_c = filtered_3rd_symbols_arc.lock().await.clone();
// let mut rsi10_1d_data: Vec<(String, Vec<RsiData>)> = rsi(
// 10,
// &alldata.rt_price_1d_vec,
// &filtered_3rd_symbol_c,
// )
// .await?;
// let stoch_rsi_data = stoch_rsi(&rsi10_1d_data, 10, 3, 3).await?;
// let mut stoch_rsi10_1d_vec: Vec<StochRsiData> = Vec::new();
// let mut filtered_4th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
// for element in filtered_3rd_symbol_c {
// let stoch_rsi10_1d_option = stoch_rsi_data.iter().position(|x| *x.0 == element.0);
// if stoch_rsi10_1d_option.is_some() {
// stoch_rsi10_1d_vec = stoch_rsi_data[stoch_rsi10_1d_option.unwrap()].1.clone();
// if stoch_rsi10_1d_vec.len() >= 3 {
// let stoch_rsi_search_result = stoch_rsi10_1d_vec.binary_search_by_key(
// &element.1,
// |&StochRsiData {
// k,
// d,
// close_time,
// }| close_time,
// );
// if stoch_rsi_search_result.is_ok() {
// if stoch_rsi10_1d_vec[stoch_rsi_search_result.unwrap()].k > stoch_rsi10_1d_vec[stoch_rsi_search_result.unwrap()-1].k &&
// stoch_rsi10_1d_vec[stoch_rsi_search_result.unwrap()].k < 90.0 &&
// stoch_rsi10_1d_vec[stoch_rsi_search_result.unwrap()-1].k > 10.0 {
// filtered_4th_symbols.push(element);
// }
// }
// }
// }
// }
// // 6th filtering condition: MACD
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
// let mut ema3_1d_vec: &Vec<EmaData> = &Vec::new();
// let mut ema10_1d_vec: &Vec<EmaData> = &Vec::new();
// let ema3_1d_data: Vec<(String, Vec<EmaData>)> = ema(
// 3,
// &alldata.rt_price_1d_vec,
// &filtered_4th_symbols,
// )
// .await?;
// let ema10_1d_data: Vec<(String, Vec<EmaData>)> = ema(
// 10,
// &alldata.rt_price_1d_vec,
// &filtered_4th_symbols,
// )
// .await?;
// let mut filtered_5th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
// for element in filtered_4th_symbols {
// let ema3_1d_option = ema3_1d_data.iter().position(|x| *x.0 == *element.0);
// let ema10_1d_option = ema10_1d_data.iter().position(|x| *x.0 == *element.0);
// if ema3_1d_option.is_some() && ema10_1d_option.is_some() {
// ema3_1d_vec = &ema3_1d_data[ema3_1d_option.unwrap()].1;
// ema10_1d_vec = &ema10_1d_data[ema10_1d_option.unwrap()].1;
// 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);
// // if macd_search_result.is_ok() {
// if macd_vec.last().unwrap().macd_value > macd_vec[macd_vec.len() -1].macd_value {
// filtered_5th_symbols.push(element);
// }
// // }
// }
// }
// }
// // 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();
// 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,
// ));
// }
// }
// }));
// }
// try_join_all(task_vec).await?;
// let a = filtered_symbols_arc.lock().await.clone();
// insert_pre_suggested_coins(6, true, &a, alldata).await;
// Ok(())
// }

View File

@ -0,0 +1,652 @@
use crate::coex::exchange_team::*;
use crate::coex::order_team::*;
use crate::coin_health_check_team::request_others::CoinPriceData;
use csv::{DeserializeRecordsIter, StringRecord};
use rust_decimal::prelude::ToPrimitive;
use rust_decimal::Decimal;
use serde::Deserialize;
use tokio::time::{sleep, Duration, Instant};
use crate::signal_association::signal_decision::*;
use super::{AllData, RealtimePriceData, exists_record, try_select_record, insert_one_record, FromRow, ExchangeInfo, TradeFee};
#[derive(Debug, FromRow)]
struct ServerEpoch {
server_epoch: u64,
}
#[derive(Debug, FromRow)]
struct Record {
symbol: String,
suggested_price: Decimal,
close_time: u64,
registered_server_epoch: u64,
registerer: u16,
is_long: u8,
}
pub async fn execute_list_up_for_buy(
all_data: &AllData,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// strategist_001(all_data).await?;
// strategist_002(all_data).await?;
crate::strategy_team::strategy_003::list_up_for_buy(all_data).await?;
// strategist_004(all_data).await?;
// strategist_005(all_data).await?;
// strategist_006(all_data).await?;
Ok(())
}
pub async fn execute_list_up_for_sell(
all_data: &AllData,
exchange_info_vec: &Vec<ExchangeInfo>,
trade_fee_vec: &Vec<TradeFee>
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
crate::strategy_team::strategy_003::list_up_for_sell(all_data, exchange_info_vec, trade_fee_vec).await?;
Ok(())
}
// useful functions for strategists
pub async fn get_current_price(
symbol: &String,
rt_price_vec: &Vec<(String, Vec<RealtimePriceData>)>,
) -> Option<f64> {
let index_result = rt_price_vec.iter().position(|x| *x.0 == *symbol);
match index_result {
Some(T) => {
if rt_price_vec[T].1.last().is_some() {
Some(rt_price_vec[T].1.last().unwrap().close_price)
} else {
None
}
}
None => None,
}
}
pub async fn insert_pre_suggested_coins(
registerer: i32,
is_long: bool,
filtered_symbols: &Vec<(String, i64, f64)>,
alldata: &AllData,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// Check the existance of record that is registered by this strategist
let mut dest_table_name = String::from("suggested_coin_list");
let mut dest2_table_name = String::from("buy_ordered_coin_list");
let mut dest3_table_name = String::from("pre_suggested_coin_list");
let mut insert_table_name = String::from("pre_suggested_coin_list");
let mut exists_condition_build = String::from("registerer=");
exists_condition_build.push_str(registerer.to_string().as_str());
let mut exists_condition = Some(exists_condition_build);
let exists_result1 = exists_record(&dest_table_name, &exists_condition).await;
let exists_result2 = exists_record(&dest2_table_name, &exists_condition).await;
let exists_result3 = exists_record(&dest3_table_name, &exists_condition).await;
let insert_columns = vec![
"symbol",
"close_time",
"suggested_price",
"current_price",
"registered_server_epoch",
"profit_percent",
"minimum_profit_percent",
"maximum_profit_percent",
"registerer",
"is_long",
];
if exists_result1 == true && exists_result2 == true && exists_result3 == true {
// Bring the current list of pre-suggested coins from [pre_suggested_coin_list] and [ordered_coin_list]
#[derive(FromRow)]
struct SelectData {
symbol: String,
close_time: i64,
}
#[derive(FromRow)]
struct SelectData2 {
symbol: String,
close_time: i64,
}
let mut select_columns = String::from("symbol, close_time");
let mut condition_build = String::from("WHERE registerer=");
condition_build.push_str(registerer.to_string().as_str());
let select_condition = Some(condition_build);
let select_data_structure = SelectData {
symbol: String::new(),
close_time: 0,
};
let mut select_columns2 = String::from("symbol, close_time");
let select_data_structure2 = SelectData2 {
symbol: String::new(),
close_time: 0,
};
let suggested_coin_list = try_select_record(
&dest_table_name,
&select_columns,
&select_condition,
&select_data_structure,
)
.await?;
let ordered_coin_list = try_select_record(
&dest2_table_name,
&select_columns2,
&select_condition,
&select_data_structure2,
)
.await?;
let pre_suggested_coin_list = try_select_record(
&dest3_table_name,
&select_columns,
&select_condition,
&select_data_structure,
)
.await?;
// insert record without duplicate(registerer, closetime, symbol) into [pre_suggested_coin_list]
for filtered_element in filtered_symbols {
let mut is_dupe = false; // initialize
for list_element in &suggested_coin_list {
if (filtered_element.0 == list_element.symbol)
&& (filtered_element.1 == list_element.close_time)
{
is_dupe = true;
break;
}
}
for list_element in &ordered_coin_list {
if (filtered_element.0 == list_element.symbol)
&& (filtered_element.1 == list_element.close_time)
{
is_dupe = true;
break;
}
}
for list_element in &pre_suggested_coin_list {
if (filtered_element.0 == list_element.symbol)
&& (filtered_element.1 == list_element.close_time)
{
is_dupe = true;
break;
}
}
if is_dupe == false {
let mut insert_values = vec![
filtered_element.0.clone(), // symbol
filtered_element.1.to_string(), // close_time
filtered_element.2.to_string(), // suggested_price
filtered_element.2.to_string(), // current_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
} else {
insert_values.push(0.to_string()); // is_long
}
insert_one_record(&insert_table_name, &insert_columns, &insert_values).await;
}
}
} else if exists_result1 == true && exists_result2 == true && exists_result3 == false {
// Bring the current list of pre-suggested coins from [pre_suggested_coin_list] and [ordered_coin_list]
#[derive(FromRow)]
struct SelectData {
symbol: String,
close_time: i64,
}
#[derive(FromRow)]
struct SelectData2 {
symbol: String,
close_time: i64,
}
let mut select_columns = String::from("symbol, close_time");
let mut condition_build = String::from("WHERE registerer=");
condition_build.push_str(registerer.to_string().as_str());
let select_condition = Some(condition_build);
let select_data_structure = SelectData {
symbol: String::new(),
close_time: 0,
};
let mut select_columns2 = String::from("symbol, close_time");
let select_data_structure2 = SelectData2 {
symbol: String::new(),
close_time: 0,
};
let suggested_coin_list = try_select_record(
&dest_table_name,
&select_columns,
&select_condition,
&select_data_structure,
)
.await?;
let ordered_coin_list = try_select_record(
&dest2_table_name,
&select_columns2,
&select_condition,
&select_data_structure2,
)
.await?;
// insert record without duplicate(registerer, closetime, symbol) into [pre_suggested_coin_list]
for filtered_element in filtered_symbols {
let mut is_dupe = false; // initialize
for list_element in &suggested_coin_list {
if (filtered_element.0 == list_element.symbol)
&& (filtered_element.1 == list_element.close_time)
{
is_dupe = true;
break;
}
}
for list_element in &ordered_coin_list {
if (filtered_element.0 == list_element.symbol)
&& (filtered_element.1 == list_element.close_time)
{
is_dupe = true;
break;
}
}
if is_dupe == false {
let mut insert_values = vec![
filtered_element.0.clone(), // symbol
filtered_element.1.to_string(), // close_time
filtered_element.2.to_string(), // suggested_price
filtered_element.2.to_string(), // current_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
} else {
insert_values.push(0.to_string()); // is_long
}
insert_one_record(&insert_table_name, &insert_columns, &insert_values).await;
}
}
} else if exists_result1 == true && exists_result2 == false && exists_result3 == true {
// Bring the current list of pre-suggested coins from [pre_suggested_coin_list] and [ordered_coin_list]
#[derive(FromRow)]
struct SelectData {
symbol: String,
close_time: i64,
}
let mut select_columns = String::from("symbol, close_time");
let mut condition_build = String::from("WHERE registerer=");
condition_build.push_str(registerer.to_string().as_str());
let select_condition = Some(condition_build);
let select_data_structure = SelectData {
symbol: String::new(),
close_time: 0,
};
let suggested_coin_list = try_select_record(
&dest_table_name,
&select_columns,
&select_condition,
&select_data_structure,
)
.await?;
let pre_suggested_coin_list = try_select_record(
&dest3_table_name,
&select_columns,
&select_condition,
&select_data_structure,
)
.await?;
// insert record without duplicate(registerer, closetime, symbol) into [pre_suggested_coin_list]
for filtered_element in filtered_symbols {
let mut is_dupe = false; // initialize
for list_element in &suggested_coin_list {
if (filtered_element.0 == list_element.symbol)
&& (filtered_element.1 == list_element.close_time)
{
is_dupe = true;
break;
}
}
for list_element in &pre_suggested_coin_list {
if (filtered_element.0 == list_element.symbol)
&& (filtered_element.1 == list_element.close_time)
{
is_dupe = true;
break;
}
}
if is_dupe == false {
let mut insert_values = vec![
filtered_element.0.clone(), // symbol
filtered_element.1.to_string(), // close_time
filtered_element.2.to_string(), // suggested_price
filtered_element.2.to_string(), // current_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
} else {
insert_values.push(0.to_string()); // is_long
}
insert_one_record(&insert_table_name, &insert_columns, &insert_values).await;
}
}
} else if exists_result1 == true && exists_result2 == false && exists_result3 == false {
// Bring the current list of pre-suggested coins from [pre_suggested_coin_list] and [ordered_coin_list]
#[derive(FromRow)]
struct SelectData {
symbol: String,
close_time: i64,
}
let mut select_columns = String::from("symbol, close_time");
let mut condition_build = String::from("WHERE registerer=");
condition_build.push_str(registerer.to_string().as_str());
let select_condition = Some(condition_build);
let select_data_structure = SelectData {
symbol: String::new(),
close_time: 0,
};
let suggested_coin_list = try_select_record(
&dest_table_name,
&select_columns,
&select_condition,
&select_data_structure,
)
.await?;
// insert record without duplicate(registerer, closetime, symbol) into [pre_suggested_coin_list]
for filtered_element in filtered_symbols {
let mut is_dupe = false; // initialize
for list_element in &suggested_coin_list {
if (filtered_element.0 == list_element.symbol)
&& (filtered_element.1 == list_element.close_time)
{
is_dupe = true;
break;
}
}
if is_dupe == false {
let mut insert_values = vec![
filtered_element.0.clone(), // symbol
filtered_element.1.to_string(), // close_time
filtered_element.2.to_string(), // suggested_price
filtered_element.2.to_string(), // current_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
} else {
insert_values.push(0.to_string()); // is_long
}
insert_one_record(&insert_table_name, &insert_columns, &insert_values).await;
}
}
} else if exists_result1 == false && exists_result2 == true && exists_result3 == true {
// Bring the current list of pre-suggested coins from [pre_suggested_coin_list] and [ordered_coin_list]
#[derive(FromRow)]
struct SelectData {
symbol: String,
close_time: i64,
}
#[derive(FromRow)]
struct SelectData2 {
symbol: String,
close_time: i64,
}
let mut select_columns = String::from("symbol, close_time");
let mut condition_build = String::from("WHERE registerer=");
condition_build.push_str(registerer.to_string().as_str());
let select_condition = Some(condition_build);
let select_data_structure = SelectData {
symbol: String::new(),
close_time: 0,
};
let mut select_columns2 = String::from("symbol, close_time");
let select_data_structure2 = SelectData2 {
symbol: String::new(),
close_time: 0,
};
let ordered_coin_list = try_select_record(
&dest2_table_name,
&select_columns2,
&select_condition,
&select_data_structure2,
)
.await?;
let pre_suggested_coin_list = try_select_record(
&dest3_table_name,
&select_columns,
&select_condition,
&select_data_structure,
)
.await?;
// insert record without duplicate(registerer, close_time, symbol) into [pre_suggested_coin_list]
for filtered_element in filtered_symbols {
let mut is_dupe = false; // initialize
for list_element in &ordered_coin_list {
if (filtered_element.0 == list_element.symbol)
&& (filtered_element.1 == list_element.close_time)
{
is_dupe = true;
break;
}
}
for list_element in &pre_suggested_coin_list {
if (filtered_element.0 == list_element.symbol)
&& (filtered_element.1 == list_element.close_time)
{
is_dupe = true;
break;
}
}
if is_dupe == false {
let mut insert_values = vec![
filtered_element.0.clone(), // symbol
filtered_element.1.to_string(), // close_time
filtered_element.2.to_string(), // suggested_price
filtered_element.2.to_string(), // current_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
} else {
insert_values.push(0.to_string()); // is_long
}
insert_one_record(&insert_table_name, &insert_columns, &insert_values).await;
}
}
} else if exists_result1 == false && exists_result2 == true && exists_result3 == false {
// Bring the current list of pre-suggested coins from [pre_suggested_coin_list] and [ordered_coin_list]
#[derive(FromRow)]
struct SelectData {
symbol: String,
close_time: i64,
}
#[derive(FromRow)]
struct SelectData2 {
symbol: String,
close_time: i64,
}
let mut select_columns = String::from("symbol, close_time");
let mut condition_build = String::from("WHERE registerer=");
condition_build.push_str(registerer.to_string().as_str());
let select_condition = Some(condition_build);
let select_data_structure = SelectData {
symbol: String::new(),
close_time: 0,
};
let mut select_columns2 = String::from("symbol, close_time");
let select_data_structure2 = SelectData2 {
symbol: String::new(),
close_time: 0,
};
let ordered_coin_list = try_select_record(
&dest2_table_name,
&select_columns2,
&select_condition,
&select_data_structure2,
)
.await?;
// insert record without duplicate(registerer, closetime, symbol) into [pre_suggested_coin_list]
for filtered_element in filtered_symbols {
let mut is_dupe = false; // initialize
for list_element in &ordered_coin_list {
if (filtered_element.0 == list_element.symbol)
&& (filtered_element.1 == list_element.close_time)
{
is_dupe = true;
break;
}
}
if is_dupe == false {
let mut insert_values = vec![
filtered_element.0.clone(), // symbol
filtered_element.1.to_string(), // close_time
filtered_element.2.to_string(), // suggested_price
filtered_element.2.to_string(), // current_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
} else {
insert_values.push(0.to_string()); // is_long
}
insert_one_record(&insert_table_name, &insert_columns, &insert_values).await;
}
}
} else if exists_result1 == false && exists_result2 == false && exists_result3 == true {
// Bring the current list of pre-suggested coins from [pre_suggested_coin_list] and [ordered_coin_list]
#[derive(FromRow)]
struct SelectData {
symbol: String,
close_time: i64,
}
let mut select_columns = String::from("symbol, close_time");
let mut condition_build = String::from("WHERE registerer=");
condition_build.push_str(registerer.to_string().as_str());
let select_condition = Some(condition_build);
let select_data_structure = SelectData {
symbol: String::new(),
close_time: 0,
};
let pre_suggested_coin_list = try_select_record(
&dest3_table_name,
&select_columns,
&select_condition,
&select_data_structure,
)
.await?;
// insert record without duplicate(registerer, closetime, symbol) into [pre_suggested_coin_list]
for filtered_element in filtered_symbols {
let mut is_dupe = false; // initialize
for list_element in &pre_suggested_coin_list {
if (filtered_element.0 == list_element.symbol)
&& (filtered_element.1 == list_element.close_time)
{
is_dupe = true;
break;
}
}
if is_dupe == false {
let mut insert_values = vec![
filtered_element.0.clone(), // symbol
filtered_element.1.to_string(), // close_time
filtered_element.2.to_string(), // suggested_price
filtered_element.2.to_string(), // current_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
} else {
insert_values.push(0.to_string()); // is_long
}
insert_one_record(&insert_table_name, &insert_columns, &insert_values).await;
}
}
} else {
for filtered_element in filtered_symbols {
let mut insert_values = vec![
filtered_element.0.clone(), // symbol
filtered_element.1.to_string(), // close_time
filtered_element.2.to_string(), // suggested_price
filtered_element.2.to_string(), // current_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
} else {
insert_values.push(0.to_string()); // is_long
}
insert_one_record(&insert_table_name, &insert_columns, &insert_values).await;
}
}
Ok(())
}

View File

@ -1 +0,0 @@
pub mod price_data;

View File

@ -0,0 +1 @@
pub mod price_data;