Refactor codes

This commit is contained in:
Sik Yoon 2023-10-04 20:12:13 +09:00
parent 9d7e001860
commit 39b8c31e30

View File

@ -90,6 +90,61 @@ pub struct SellOrderedCoinList {
pub is_long: u8, pub is_long: u8,
} }
pub trait DBlist {
fn new() -> Self;
}
impl DBlist for SellOrderedCoinList {
fn new() -> SellOrderedCoinList {
let a = SellOrderedCoinList {
id: 0,
symbol: String::new(),
buy_order_id: 0,
sell_order_id: 0,
transact_time: 0,
close_time: 0,
status: String::new(),
used_usdt: Decimal::new(0, 8),
get_usdt: Decimal::new(0, 8),
get_usdt_fee_adjusted: Decimal::new(0, 8),
buy_price: Decimal::new(0, 8),
sell_price: Decimal::new(0, 8),
base_qty_ordered: Decimal::new(0, 8),
pure_profit_percent: Decimal::new(0, 8),
maximum_profit_percent: 0.0,
registerer: 0,
is_long: 0,
};
a
}
}
impl DBlist for BuyOrderedCoinList {
fn new() -> BuyOrderedCoinList {
let a = BuyOrderedCoinList {
id: 0,
symbol: String::new(),
order_id: 0,
transact_time: 0,
close_time: 0,
status: String::new(),
used_usdt: Decimal::new(0, 8),
expected_get_usdt: 0.0,
expected_usdt_profit: 0.0,
buy_price: Decimal::new(0, 8),
current_price: Decimal::new(0, 8),
base_qty_ordered: Decimal::new(0, 8),
base_qty_fee_adjusted: Decimal::new(0, 8),
pure_profit_percent: 0.0,
minimum_profit_percent: 0.0,
maximum_profit_percent: 0.0,
registerer: 0,
is_long: 0,
};
a
}
}
#[derive(Debug, FromRow)] #[derive(Debug, FromRow)]
pub struct SignalDecisionInfo { pub struct SignalDecisionInfo {
pub decision: String, pub decision: String,
@ -258,6 +313,8 @@ pub async fn limit_order_buy(
// reflect available_usdt in [asset_manage_announcement] // reflect available_usdt in [asset_manage_announcement]
sub_available_usdt(used_usdt).await; sub_available_usdt(used_usdt).await;
println!("SIMUL buy coin: {}", element.symbol);
} else { } else {
// building URL and API-keys // building URL and API-keys
let mut url = String::new(); let mut url = String::new();
@ -436,7 +493,8 @@ pub async fn monitoring_filled_buy_order(
// let scoreboard_list = select_scoreboard().await; // let scoreboard_list = select_scoreboard().await;
// let signal_decision = select_signal_decision().await; // let signal_decision = select_signal_decision().await;
let filled_buy_orders = select_filled_buy_orders().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
@ -463,7 +521,7 @@ pub async fn monitoring_filled_buy_order(
let result = try_join_all(task_vec).await; let result = try_join_all(task_vec).await;
// sell coin if its sell condition is satisfied // sell coin if its sell condition is satisfied
let filled_buy_orders = select_filled_buy_orders().await; let filled_buy_orders = select_filled_buy_orders().await?;
let client = ClientBuilder::new() let client = ClientBuilder::new()
.timeout(tokio::time::Duration::from_millis(5000)) .timeout(tokio::time::Duration::from_millis(5000))
.build() .build()
@ -506,11 +564,15 @@ pub async fn monitoring_filled_buy_order(
let mut opclo_30m_vec = all_data.rt_price_30m_vec[opclo_30m_option.unwrap()] let mut opclo_30m_vec = all_data.rt_price_30m_vec[opclo_30m_option.unwrap()]
.1 .1
.clone(); .clone();
let opclo_sample_length: usize = 50; // 50 candle samsples
opclo_30m_vec.pop(); opclo_30m_vec.pop();
opclo_30m_vec.reverse(); 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.truncate(opclo_sample_length);
opclo_30m_vec.reverse(); 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_amplitude_candles = 0.0;
let mut sum_ratio_amp_body = 0.0; let mut sum_ratio_amp_body = 0.0;
@ -536,35 +598,42 @@ pub async fn monitoring_filled_buy_order(
// let target_profit_percent = average_amplitude + (standard_deviation_amplitude * (average_ratio_amp_body)); // let target_profit_percent = average_amplitude + (standard_deviation_amplitude * (average_ratio_amp_body));
let target_profit_percent = |multiplier: f64| -> f64 { let target_profit_percent = |multiplier: f64| -> f64 {
if multiplier < 0.0 { if multiplier < 0.0 {
((average_amplitude / 2.0) * multiplier) - (standard_deviation_amplitude * 2.0) // 2.0 sigma (recommand: 0.5 ~ 2.0(patient & greedy)) ((average_amplitude) * multiplier) - (standard_deviation_amplitude * 2.0) // 2.0 sigma (recommand: 0.5 ~ 2.0(patient & greedy))
} else { } else {
((average_amplitude / 2.0) * multiplier) + (standard_deviation_amplitude * 2.0) // 2.0 sigma (recommand: 0.5 ~ 2.0(patient & greedy)) ((average_amplitude) * multiplier) + (standard_deviation_amplitude * 2.0) // 2.0 sigma (recommand: 0.5 ~ 2.0(patient & greedy))
} }
}; };
if server_epoch - element.close_time >= (1_800_000 * 2) * 12 // (30min * 2) * 12
{
println!(
"selling {} due to time up {:.3}",
element.symbol,
element.pure_profit_percent
);
if element.is_long == 0 || element.is_long == 1 { limit_order_sell(
&element,
element.current_price,
base_qty_to_be_ordered,
&client,
&exchange_info_vec,
&trade_fee_vec,
)
.await;
} else {
if element.pure_profit_percent >= 0.0 { if element.pure_profit_percent >= 0.0 {
let mut is_sell = false; let mut is_sell = false;
if element.maximum_profit_percent >= target_profit_percent(2.0) if element.maximum_profit_percent >= target_profit_percent(2.0) + 0.2
&& element.pure_profit_percent >= target_profit_percent(2.0) && element.pure_profit_percent >= target_profit_percent(2.0) + 0.2
{ {
println!( println!(
"Selling {} 200% target_profit_percent: {:.3}", "Selling {} 200% target_profit_percent: {:.3}",
element.symbol, element.symbol,
target_profit_percent(2.0) element.pure_profit_percent
); );
is_sell = true; is_sell = true;
} else if element.maximum_profit_percent < target_profit_percent(2.0) } else if server_epoch - element.close_time >= (1_800_000 * 2) * 6 // (30min * 2) * 6
&& element.maximum_profit_percent >= target_profit_percent(1.5)
&& element.pure_profit_percent < target_profit_percent(0.2)
{
println!(
"selling {} 20% target_profit_percent: {:.3}",
element.symbol,
target_profit_percent(0.2)
);
is_sell = true;
} else if server_epoch - element.close_time > (1_800_000) * 10 // 30min * 10
{ {
println!( println!(
"selling {} due to time up {:.3}", "selling {} due to time up {:.3}",
@ -572,8 +641,14 @@ pub async fn monitoring_filled_buy_order(
element.pure_profit_percent element.pure_profit_percent
); );
is_sell = true; is_sell = true;
} else if element.pure_profit_percent >= 1.5 {
println!(
"selling {} 1.5% profit",
element.symbol
);
is_sell = true;
} }
if is_sell == true { if is_sell == true {
// let mut sell_price_ahead: Decimal = Decimal::new(14, 8); // 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); // 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);
@ -588,14 +663,26 @@ pub async fn monitoring_filled_buy_order(
.await; .await;
} }
} else { } else {
if element.pure_profit_percent < target_profit_percent(-1.333) - 0.2 // -0.2 means about total trade fees. let mut is_sell = false;
if element.pure_profit_percent <= target_profit_percent(-1.5) - 0.2 // -0.2 means about total trade fees.
{ {
println!( println!(
"selling {} due to lower limit {:.3}", "Selling {} -150% target_profit_percent: {:.3}",
element.symbol, element.symbol,
element.pure_profit_percent element.pure_profit_percent
); );
limit_order_sell( is_sell = true;
} else if element.pure_profit_percent <= -1.0 && server_epoch - element.close_time >= (1_800_000 * 2) * 2 // (30min * 2) * 2
{
println!(
"selling {} -1.0% profit",
element.symbol
);
is_sell = true;
}
if is_sell == true {
limit_order_sell(
&element, &element,
element.current_price, element.current_price,
base_qty_to_be_ordered, base_qty_to_be_ordered,
@ -607,6 +694,7 @@ pub async fn monitoring_filled_buy_order(
} }
} }
} }
} }
} }
@ -796,6 +884,7 @@ pub async fn limit_order_sell(
dec!(100), dec!(100),
); );
insert_value_container.push(pure_profit_percent.to_string()); // pure_profit_percent insert_value_container.push(pure_profit_percent.to_string()); // pure_profit_percent
insert_value_container.push(buy_ordered_coin.maximum_profit_percent.to_string()); // maximum_profit_percent
insert_value_container.push(buy_ordered_coin.registerer.to_string()); // registerer insert_value_container.push(buy_ordered_coin.registerer.to_string()); // registerer
insert_value_container.push(buy_ordered_coin.is_long.to_string()); // is_long insert_value_container.push(buy_ordered_coin.is_long.to_string()); // is_long
@ -2140,30 +2229,11 @@ async fn get_timestamp() -> String {
timestamp timestamp
} }
pub async fn select_filled_buy_orders() -> Vec<BuyOrderedCoinList> { pub async fn select_filled_buy_orders() -> 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 select_condition = Some(String::from("WHERE status = 'FILLED' or status = 'SIMUL'"));
let data_struct = BuyOrderedCoinList { let data_struct = BuyOrderedCoinList::new();
id: 0,
symbol: String::new(),
order_id: 0,
transact_time: 0,
close_time: 0,
status: String::new(),
used_usdt: Decimal::new(0, 8),
expected_get_usdt: 0.0,
expected_usdt_profit: 0.0,
buy_price: Decimal::new(0, 8),
current_price: Decimal::new(0, 8),
base_qty_ordered: Decimal::new(0, 8),
base_qty_fee_adjusted: Decimal::new(0, 8),
pure_profit_percent: 0.0,
minimum_profit_percent: 0.0,
maximum_profit_percent: 0.0,
registerer: 0,
is_long: 0,
};
let select_result = try_select_record( let select_result = try_select_record(
&select_table_name, &select_table_name,
@ -2171,10 +2241,15 @@ pub async fn select_filled_buy_orders() -> Vec<BuyOrderedCoinList> {
&select_condition, &select_condition,
&data_struct, &data_struct,
) )
.await .await;
.unwrap();
select_result if select_result.is_ok() {
Ok(select_result.unwrap())
} else {
eprint!("select_filled_buy_order() error!");
Err("error")?
}
} }
// select open buy orders (NEW, Partially Filled) // select open buy orders (NEW, Partially Filled)
@ -2184,26 +2259,7 @@ async fn select_open_buy_orders() -> Vec<BuyOrderedCoinList> {
let select_condition = Some(String::from( let select_condition = Some(String::from(
"WHERE status = 'NEW' or status = 'PARTIALLY_FILLED'", "WHERE status = 'NEW' or status = 'PARTIALLY_FILLED'",
)); ));
let data_struct = BuyOrderedCoinList { let data_struct = BuyOrderedCoinList::new();
id: 0,
symbol: String::new(),
order_id: 0,
transact_time: 0,
close_time: 0,
status: String::new(),
used_usdt: Decimal::new(0, 8),
expected_get_usdt: 0.0,
expected_usdt_profit: 0.0,
buy_price: Decimal::new(0, 8),
current_price: Decimal::new(0, 8),
base_qty_ordered: Decimal::new(0, 8),
base_qty_fee_adjusted: Decimal::new(0, 8),
pure_profit_percent: 0.0,
minimum_profit_percent: 0.0,
maximum_profit_percent: 0.0,
registerer: 0,
is_long: 0,
};
let select_result = try_select_record( let select_result = try_select_record(
&select_table_name, &select_table_name,
&select_columns, &select_columns,
@ -2220,25 +2276,7 @@ pub async fn select_filled_sell_orders() -> Vec<SellOrderedCoinList> {
let select_table_name = String::from("sell_ordered_coin_list"); let select_table_name = String::from("sell_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 select_condition = Some(String::from("WHERE status = 'FILLED' or status = 'SIMUL'"));
let data_struct = SellOrderedCoinList { let data_struct = SellOrderedCoinList::new();
id: 0,
symbol: String::new(),
buy_order_id: 0,
sell_order_id: 0,
transact_time: 0,
close_time: 0,
status: String::new(),
used_usdt: Decimal::new(0, 8),
get_usdt: Decimal::new(0, 8),
get_usdt_fee_adjusted: Decimal::new(0, 8),
buy_price: Decimal::new(0, 8),
sell_price: Decimal::new(0, 8),
base_qty_ordered: Decimal::new(0, 8),
pure_profit_percent: Decimal::new(0, 8),
maximum_profit_percent: 0.0,
registerer: 0,
is_long: 0,
};
let select_result = try_select_record( let select_result = try_select_record(
&select_table_name, &select_table_name,
@ -2259,25 +2297,7 @@ async fn select_open_sell_orders() -> Vec<SellOrderedCoinList> {
let select_condition = Some(String::from( let select_condition = Some(String::from(
"WHERE status = 'NEW' or status = 'PARTIALLY_FILLED'", "WHERE status = 'NEW' or status = 'PARTIALLY_FILLED'",
)); ));
let data_struct = SellOrderedCoinList { let data_struct = SellOrderedCoinList::new();
id: 0,
symbol: String::new(),
buy_order_id: 0,
sell_order_id: 0,
transact_time: 0,
close_time: 0,
status: String::new(),
used_usdt: Decimal::new(0, 8),
get_usdt: Decimal::new(0, 8),
get_usdt_fee_adjusted: Decimal::new(0, 8),
buy_price: Decimal::new(0, 8),
sell_price: Decimal::new(0, 8),
base_qty_ordered: Decimal::new(0, 8),
pure_profit_percent: Decimal::new(0, 8),
maximum_profit_percent: 0.0,
registerer: 0,
is_long: 0,
};
let select_result = try_select_record( let select_result = try_select_record(
&select_table_name, &select_table_name,