Refactor codes
This commit is contained in:
parent
9d7e001860
commit
39b8c31e30
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user