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:
commit
8a53e18553
854
Cargo.lock
generated
854
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
|
|
@ -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"
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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
|
|
@ -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();
|
||||||
|
|
|
||||||
20
src/lib.rs
20
src/lib.rs
|
|
@ -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;
|
||||||
|
|
|
||||||
360
src/main.rs
360
src/main.rs
|
|
@ -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
63
src/strategy_team/mod.rs
Normal 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,
|
||||||
|
}
|
||||||
424
src/strategy_team/strategy_001.rs
Normal file
424
src/strategy_team/strategy_001.rs
Normal 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(())
|
||||||
|
// }
|
||||||
277
src/strategy_team/strategy_002.rs
Normal file
277
src/strategy_team/strategy_002.rs
Normal 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(())
|
||||||
|
// }
|
||||||
449
src/strategy_team/strategy_003.rs
Normal file
449
src/strategy_team/strategy_003.rs
Normal 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(())
|
||||||
|
}
|
||||||
268
src/strategy_team/strategy_004.rs
Normal file
268
src/strategy_team/strategy_004.rs
Normal 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(())
|
||||||
|
// }
|
||||||
192
src/strategy_team/strategy_005.rs
Normal file
192
src/strategy_team/strategy_005.rs
Normal 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(())
|
||||||
|
// }
|
||||||
203
src/strategy_team/strategy_006.rs
Normal file
203
src/strategy_team/strategy_006.rs
Normal 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(())
|
||||||
|
// }
|
||||||
652
src/strategy_team/strategy_manager.rs
Normal file
652
src/strategy_team/strategy_manager.rs
Normal 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(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
pub mod price_data;
|
|
||||||
1
src/value_estimation_team/datapoints/mod.rs
Normal file
1
src/value_estimation_team/datapoints/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod price_data;
|
||||||
Loading…
Reference in New Issue
Block a user