|
@@ -2,6 +2,7 @@ use std::collections::{BTreeMap};
|
|
|
use std::str::FromStr;
|
|
use std::str::FromStr;
|
|
|
use chrono::NaiveDateTime;
|
|
use chrono::NaiveDateTime;
|
|
|
use rust_decimal::Decimal;
|
|
use rust_decimal::Decimal;
|
|
|
|
|
+use rust_decimal_macros::dec;
|
|
|
use tracing::info;
|
|
use tracing::info;
|
|
|
use crate::{export_template};
|
|
use crate::{export_template};
|
|
|
use crate::swap_gate::gate_swap_rest_utils::GateSwapRest;
|
|
use crate::swap_gate::gate_swap_rest_utils::GateSwapRest;
|
|
@@ -15,7 +16,7 @@ pub async fn export_balance(config_info: BalanceConfigInfo) {
|
|
|
let count_end_time = NaiveDateTime::parse_from_str(&config_info.count_range_time[1].clone(), "%Y-%m-%d %H:%M:%S").unwrap().timestamp() - 8 * 3600;
|
|
let count_end_time = NaiveDateTime::parse_from_str(&config_info.count_range_time[1].clone(), "%Y-%m-%d %H:%M:%S").unwrap().timestamp() - 8 * 3600;
|
|
|
|
|
|
|
|
//获取不同账号的数据
|
|
//获取不同账号的数据
|
|
|
- let mut acc_all_data: BTreeMap<String, Vec<Vec<String>>> = BTreeMap::new();
|
|
|
|
|
|
|
+ let mut all_account_balance_info: BTreeMap<String, Vec<Vec<String>>> = BTreeMap::new();
|
|
|
let mut account_name_list: Vec<String> = vec![];
|
|
let mut account_name_list: Vec<String> = vec![];
|
|
|
loop {
|
|
loop {
|
|
|
if config_info_clone.account_list.len() == 0 {
|
|
if config_info_clone.account_list.len() == 0 {
|
|
@@ -99,7 +100,7 @@ pub async fn export_balance(config_info: BalanceConfigInfo) {
|
|
|
|
|
|
|
|
name_data_all.push(name_data_array.clone());
|
|
name_data_all.push(name_data_array.clone());
|
|
|
}
|
|
}
|
|
|
- acc_all_data.insert(account_name.clone(), name_data_all.clone());
|
|
|
|
|
|
|
+ all_account_balance_info.insert(account_name.clone(), name_data_all.clone());
|
|
|
} else {
|
|
} else {
|
|
|
info!("不是数组 检查数据");
|
|
info!("不是数组 检查数据");
|
|
|
}
|
|
}
|
|
@@ -111,8 +112,8 @@ pub async fn export_balance(config_info: BalanceConfigInfo) {
|
|
|
|
|
|
|
|
// 根据账户变动填充
|
|
// 根据账户变动填充
|
|
|
let mut count_time_list = vec![];
|
|
let mut count_time_list = vec![];
|
|
|
- for (_account_name, account_info) in acc_all_data.clone() {
|
|
|
|
|
- for value in account_info {
|
|
|
|
|
|
|
+ for (_account_name, balance_info) in all_account_balance_info.clone() {
|
|
|
|
|
+ for value in balance_info {
|
|
|
let time = value[0].clone().parse::<i64>().unwrap();
|
|
let time = value[0].clone().parse::<i64>().unwrap();
|
|
|
if !count_time_list.contains(&time) && time > count_start_time && time < count_end_time {
|
|
if !count_time_list.contains(&time) && time > count_start_time && time < count_end_time {
|
|
|
count_time_list.push(time)
|
|
count_time_list.push(time)
|
|
@@ -120,15 +121,12 @@ pub async fn export_balance(config_info: BalanceConfigInfo) {
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
count_time_list.sort_by(|a, b| a.cmp(&b));
|
|
count_time_list.sort_by(|a, b| a.cmp(&b));
|
|
|
- let mut bbbbbb = supply_balance(acc_all_data.clone(), count_time_list.clone());
|
|
|
|
|
|
|
+ count_time_list.insert(0, count_start_time);
|
|
|
|
|
+ count_time_list.push(count_end_time);
|
|
|
|
|
+ let count_balance_info = supply_balance(all_account_balance_info.clone(), count_time_list.clone());
|
|
|
|
|
+ let statistic_result = statistic_balance(count_balance_info.clone(), count_start_time.clone(), count_end_time.clone());
|
|
|
|
|
|
|
|
- let aaaaa: Vec<Vec<String>> = bbbbbb.clone().into_iter().filter(|value| {
|
|
|
|
|
- let t = value[1].clone().parse::<i64>().unwrap();
|
|
|
|
|
- t >= start_time && t <= end_time
|
|
|
|
|
- }).collect();
|
|
|
|
|
- bbbbbb = aaaaa;
|
|
|
|
|
-
|
|
|
|
|
- // 按小时取时间片
|
|
|
|
|
|
|
+ // 根据小时填充
|
|
|
let mut last_timestamp: i64 = -1;
|
|
let mut last_timestamp: i64 = -1;
|
|
|
let mut export_time_list: Vec<i64> = vec![];
|
|
let mut export_time_list: Vec<i64> = vec![];
|
|
|
for item in start_time..end_time {
|
|
for item in start_time..end_time {
|
|
@@ -138,18 +136,45 @@ pub async fn export_balance(config_info: BalanceConfigInfo) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
export_time_list.push(end_time);
|
|
export_time_list.push(end_time);
|
|
|
|
|
+ let all_balance_info: Vec<Vec<String>> = supply_balance(all_account_balance_info.clone(), export_time_list.clone());
|
|
|
|
|
+
|
|
|
|
|
+ account_name_list.push("total_balance".to_string());
|
|
|
|
|
+ export_template::template_balance::export_html(config_info_clone.clone(), &account_name_list, &export_time_list, &all_balance_info, statistic_result);
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- let mut data_array_all: Vec<Vec<String>> = supply_balance(acc_all_data.clone(), export_time_list.clone());
|
|
|
|
|
- //2. 数据根据时间片 补全数据
|
|
|
|
|
- let data_array_all_array: Vec<Vec<String>> = data_array_all.clone().into_iter().filter(|value| {
|
|
|
|
|
- let t = value[1].clone().parse::<i64>().unwrap();
|
|
|
|
|
- t >= start_time && t <= end_time
|
|
|
|
|
- }).collect();
|
|
|
|
|
- data_array_all = data_array_all_array;
|
|
|
|
|
-
|
|
|
|
|
- //生成 html
|
|
|
|
|
- account_name_list.push("sum_acc".to_string());
|
|
|
|
|
- export_template::template_balance::export_html(config_info_clone.clone(), &account_name_list, &count_time_list, &bbbbbb);
|
|
|
|
|
|
|
+
|
|
|
|
|
+pub fn statistic_balance(balance_info: Vec<Vec<String>>, count_start_time: i64, end_start_time: i64) -> String {
|
|
|
|
|
+ let mut max_withdrawal = dec!(0);
|
|
|
|
|
+ let mut max_total_withdrawal = dec!(0);
|
|
|
|
|
+ let mut total_income = dec!(0);
|
|
|
|
|
+
|
|
|
|
|
+ let mut balance_info_map: BTreeMap<String, Vec<Vec<String>>> = BTreeMap::new();
|
|
|
|
|
+ for info in balance_info.clone() {
|
|
|
|
|
+ let mut default_info = balance_info_map.get(&info[0]).unwrap_or(&vec![]).clone();
|
|
|
|
|
+ default_info.push(info.clone());
|
|
|
|
|
+ balance_info_map.insert(info[0].clone(), default_info);
|
|
|
|
|
+ }
|
|
|
|
|
+ for (account_name, balance_info) in balance_info_map.clone() {
|
|
|
|
|
+ for (index, info) in balance_info.iter().enumerate() {
|
|
|
|
|
+ if index == 0 { continue; }
|
|
|
|
|
+ let present = Decimal::from_str(&info[4]).unwrap();
|
|
|
|
|
+ let past = Decimal::from_str(&balance_info[index - 1][4]).unwrap();
|
|
|
|
|
+ let withdrawal = ((Decimal::ONE - (present / past)) * dec!(100)).round_dp(2);
|
|
|
|
|
+ if account_name != "total_balance" {
|
|
|
|
|
+ if max_withdrawal < withdrawal { max_withdrawal = withdrawal }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if max_total_withdrawal < withdrawal { max_total_withdrawal = withdrawal }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if account_name == "total_balance" {
|
|
|
|
|
+ let present = Decimal::from_str(&balance_info[0][4]).unwrap();
|
|
|
|
|
+ let past = Decimal::from_str(&balance_info[balance_info.len() - 1][4]).unwrap();
|
|
|
|
|
+ total_income = (((past / present) - Decimal::ONE) * dec!(100)).round_dp(2);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ let start_time = NaiveDateTime::from_timestamp_millis((count_start_time + 8 * 3600) * 1000).unwrap().format("%Y-%m-%d日%H点").to_string();
|
|
|
|
|
+ let end_time = NaiveDateTime::from_timestamp_millis((end_start_time + 8 * 3600) * 1000).unwrap().format("%Y-%m-%d日%H点").to_string();
|
|
|
|
|
+ format!("{}到{},总收益约为{}%,最大回撤约为{}%,其中单个账号最大回撤约为{}%。", start_time, end_time, total_income, max_total_withdrawal, max_withdrawal)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
pub fn supply_balance(source_balance_info: BTreeMap<String, Vec<Vec<String>>>, time_slicer: Vec<i64>) -> Vec<Vec<String>> {
|
|
pub fn supply_balance(source_balance_info: BTreeMap<String, Vec<Vec<String>>>, time_slicer: Vec<i64>) -> Vec<Vec<String>> {
|
|
@@ -165,8 +190,18 @@ pub fn supply_balance(source_balance_info: BTreeMap<String, Vec<Vec<String>>>, t
|
|
|
for mut info in balance_info.clone() {
|
|
for mut info in balance_info.clone() {
|
|
|
let info_time = info[0].parse::<i64>().unwrap();
|
|
let info_time = info[0].parse::<i64>().unwrap();
|
|
|
if info_time == time {
|
|
if info_time == time {
|
|
|
- info.insert(0, key.clone());
|
|
|
|
|
- new_info = Option::from(info.clone());
|
|
|
|
|
|
|
+ match new_info {
|
|
|
|
|
+ None => {
|
|
|
|
|
+ info.insert(0, key.clone());
|
|
|
|
|
+ new_info = Option::from(info);//记录当前实际
|
|
|
|
|
+ }
|
|
|
|
|
+ Some(ref value) => {
|
|
|
|
|
+ if value[1] < info[1] {
|
|
|
|
|
+ info.insert(0, key.clone());
|
|
|
|
|
+ new_info = Option::from(info);//记录当前实际
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -181,69 +216,15 @@ pub fn supply_balance(source_balance_info: BTreeMap<String, Vec<Vec<String>>>, t
|
|
|
total_price += Decimal::from_str(&last_balance_info[4]).unwrap();
|
|
total_price += Decimal::from_str(&last_balance_info[4]).unwrap();
|
|
|
balance_info_list.push(last_balance_info);
|
|
balance_info_list.push(last_balance_info);
|
|
|
}
|
|
}
|
|
|
- Some(info) => {
|
|
|
|
|
|
|
+ Some(ref info) => {
|
|
|
|
|
+ total_price += Decimal::from_str(&info[4]).unwrap();
|
|
|
|
|
+ balance_info_list.push(info.clone());
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- // //如果匹配到时间片,直接使用,没有则创建
|
|
|
|
|
- // let new_d: Vec<String> = match da {
|
|
|
|
|
- // None => {
|
|
|
|
|
- // let mut row: Vec<String> = vec![];
|
|
|
|
|
- // let filter_arrya: Vec<Vec<String>> = value.clone().into_iter().filter(|s| {
|
|
|
|
|
- // // info!("读取time:{:?}",s);
|
|
|
|
|
- // let time_v = s[0].clone().parse::<i64>().unwrap();
|
|
|
|
|
- // time_v < time.clone()
|
|
|
|
|
- // }).collect();
|
|
|
|
|
- // // info!("计算filter_arrya:---{:?}",filter_arrya.clone());
|
|
|
|
|
- // let acc_name = key.clone().to_string();
|
|
|
|
|
- // let acc_time = time.to_string();
|
|
|
|
|
- // let acc_o_id = "填补数据类型".to_string();
|
|
|
|
|
- // let mut acc_change = "0".to_string();
|
|
|
|
|
- // let mut acc_balance = "0".to_string();
|
|
|
|
|
- // let acc_type = "填补数据类型".to_string();
|
|
|
|
|
- // let mut acc_contract = "填补数据类型".to_string();
|
|
|
|
|
- //
|
|
|
|
|
- // if filter_arrya.len() > 0 {
|
|
|
|
|
- // // info!("{:?}--{}--{:?}",acc_name, time, filter_arrya[filter_arrya.len() - 1].clone());
|
|
|
|
|
- // let zj_v = filter_arrya[filter_arrya.len() - 1].clone();
|
|
|
|
|
- //
|
|
|
|
|
- // acc_change = zj_v[2].clone();
|
|
|
|
|
- // acc_balance = zj_v[3].clone();
|
|
|
|
|
- // acc_contract = zj_v[5].clone();
|
|
|
|
|
- // }
|
|
|
|
|
- //
|
|
|
|
|
- // let acc_balance_round = Decimal::from_str(&acc_balance).unwrap().round_dp(2);
|
|
|
|
|
- //
|
|
|
|
|
- // row.push(acc_name);
|
|
|
|
|
- // row.push(acc_time);
|
|
|
|
|
- // row.push(acc_o_id);
|
|
|
|
|
- // row.push(acc_change);
|
|
|
|
|
- // row.push(acc_balance_round.to_string());
|
|
|
|
|
- // row.push(acc_type);
|
|
|
|
|
- // row.push(acc_contract);
|
|
|
|
|
- // row
|
|
|
|
|
- // }
|
|
|
|
|
- // Some(d) => {
|
|
|
|
|
- // let mut row: Vec<String> = vec![];
|
|
|
|
|
- // row.push(key.clone());
|
|
|
|
|
- // row.extend(d.clone());
|
|
|
|
|
- // row
|
|
|
|
|
- // }
|
|
|
|
|
- // };
|
|
|
|
|
- // total_price = total_price + Decimal::from_str(&new_d[4]).unwrap();
|
|
|
|
|
- // data_array_all.push(new_d);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- let mut sum_row: Vec<String> = vec![];
|
|
|
|
|
- sum_row.push("sum_acc".to_string());
|
|
|
|
|
- sum_row.push(time.clone().to_string());
|
|
|
|
|
- sum_row.push("".to_string());
|
|
|
|
|
- sum_row.push("0".to_string());
|
|
|
|
|
- sum_row.push(total_price.to_string());
|
|
|
|
|
- sum_row.push("".to_string());
|
|
|
|
|
- sum_row.push("".to_string());
|
|
|
|
|
- sum_row.push("".to_string());
|
|
|
|
|
|
|
+ let sum_row: Vec<String> = vec!["total_balance".to_string(), time.to_string(), "".to_string(), "0".to_string(), total_price.round_dp(2).to_string(), "".to_string(), "".to_string(), "".to_string()];
|
|
|
balance_info_list.push(sum_row.clone());
|
|
balance_info_list.push(sum_row.clone());
|
|
|
};
|
|
};
|
|
|
- println!("------------------{:?}", balance_info_list);
|
|
|
|
|
balance_info_list
|
|
balance_info_list
|
|
|
}
|
|
}
|