export_balance.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. use std::collections::{BTreeMap};
  2. use std::str::FromStr;
  3. use chrono::NaiveDateTime;
  4. use rust_decimal::Decimal;
  5. use rust_decimal_macros::dec;
  6. use tracing::info;
  7. use crate::{export_template};
  8. use crate::swap_gate::gate_swap_rest_utils::GateSwapRest;
  9. use crate::utils::utils::BalanceConfigInfo;
  10. pub async fn export_balance(config_info: BalanceConfigInfo) {
  11. let config_info_clone = config_info.clone();
  12. let start_time = NaiveDateTime::parse_from_str(&config_info.range_time[0].clone(), "%Y-%m-%d %H:%M:%S").unwrap().timestamp() - 8 * 3600;
  13. let end_time = NaiveDateTime::parse_from_str(&config_info.range_time[1].clone(), "%Y-%m-%d %H:%M:%S").unwrap().timestamp() - 8 * 3600;
  14. let count_start_time = NaiveDateTime::parse_from_str(&config_info.count_range_time[0].clone(), "%Y-%m-%d %H:%M:%S").unwrap().timestamp() - 8 * 3600;
  15. 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;
  16. //获取不同账号的数据
  17. let mut all_account_balance_info: BTreeMap<String, Vec<Vec<String>>> = BTreeMap::new();
  18. let mut account_name_list: Vec<String> = vec![];
  19. loop {
  20. if config_info_clone.account_list.len() == 0 {
  21. info!("没有账号信息");
  22. return;
  23. }
  24. for account in config_info_clone.account_list.clone() {
  25. let mut account_info: BTreeMap<String, String> = BTreeMap::new();
  26. account_info.insert("account_name".to_string(), account[0].clone());
  27. account_info.insert("access_key".to_string(), account[1].clone());
  28. account_info.insert("secret_key".to_string(), account[2].clone());
  29. let mut gate_exc = GateSwapRest::new(false, account_info.clone());
  30. let data = gate_exc.account_book("usdt".to_string()).await;
  31. // info!("请求完成{:?}",data.clone());
  32. if data.code.as_str() == "200" {
  33. let account_name = account_info.get("account_name").unwrap();
  34. account_name_list.push(account_name.clone());
  35. //账号
  36. let json_value: serde_json::Value = serde_json::from_str(&data.data).unwrap();
  37. if let serde_json::Value::Array(array) = json_value {
  38. let mut name_data_all: Vec<Vec<String>> = vec![];
  39. let mut times = 0;
  40. for item in array {
  41. let time = item["time"].as_i64().unwrap();//秒级
  42. if time == times { continue; }
  43. times = time;
  44. let change = item["change"].as_str().unwrap();
  45. let balance = item["balance"].as_str().unwrap();
  46. let type_str = match item["type"].as_str().unwrap() {
  47. "dnw" => { "转入转出" }
  48. "pnl" => { "减仓盈亏" }
  49. "fee" => {
  50. "交易手续费";
  51. continue;
  52. }
  53. "refr" => {
  54. "推荐人返佣";
  55. continue;
  56. }
  57. "fund" => {
  58. "资金费用";
  59. continue;
  60. }
  61. "point_dnw" => {
  62. "点卡转入转出";
  63. continue;
  64. }
  65. "point_fee" => {
  66. "点卡交易手续费";
  67. continue;
  68. }
  69. "point_refr" => {
  70. "点卡推荐人返佣";
  71. continue;
  72. }
  73. _ => {
  74. "未知-变更类型";
  75. continue;
  76. }
  77. };
  78. let text = item["text"].as_str().unwrap();
  79. let contract = item["contract"].as_str().unwrap();
  80. let trade_id = item["trade_id"].as_str().unwrap();
  81. let mut name_data_array: Vec<String> = vec![];
  82. name_data_array.push(time.to_string());
  83. name_data_array.push(trade_id.to_string());
  84. name_data_array.push(change.to_string());
  85. name_data_array.push(balance.to_string());
  86. name_data_array.push(type_str.to_string());
  87. name_data_array.push(contract.to_string());
  88. name_data_array.push(text.to_string());
  89. name_data_all.push(name_data_array.clone());
  90. }
  91. all_account_balance_info.insert(account_name.clone(), name_data_all.clone());
  92. } else {
  93. info!("不是数组 检查数据");
  94. }
  95. }
  96. // break;
  97. }
  98. break;//这里是为了 代码收纳,用了loop来放置代码
  99. }
  100. // 根据账户变动填充
  101. let mut count_time_list = vec![];
  102. for (_account_name, balance_info) in all_account_balance_info.clone() {
  103. for value in balance_info {
  104. let time = value[0].clone().parse::<i64>().unwrap();
  105. if !count_time_list.contains(&time) && time > count_start_time && time < count_end_time {
  106. count_time_list.push(time)
  107. }
  108. }
  109. };
  110. count_time_list.sort_by(|a, b| a.cmp(&b));
  111. count_time_list.insert(0, count_start_time);
  112. count_time_list.push(count_end_time);
  113. let count_balance_info = supply_balance(all_account_balance_info.clone(), count_time_list.clone());
  114. let statistic_result = statistic_balance(count_balance_info.clone(), count_start_time.clone(), count_end_time.clone());
  115. // 根据小时填充
  116. let mut last_timestamp: i64 = -1;
  117. let mut export_time_list: Vec<i64> = vec![];
  118. for item in start_time..end_time {
  119. if item / 3600 != last_timestamp / 3600 {
  120. last_timestamp = item;
  121. export_time_list.push(last_timestamp);
  122. }
  123. }
  124. export_time_list.push(end_time);
  125. let all_balance_info: Vec<Vec<String>> = supply_balance(all_account_balance_info.clone(), export_time_list.clone());
  126. account_name_list.push("total_balance".to_string());
  127. export_template::template_balance::export_html(config_info_clone.clone(), &account_name_list, &export_time_list, &all_balance_info, statistic_result);
  128. }
  129. pub fn statistic_balance(balance_info: Vec<Vec<String>>, count_start_time: i64, end_start_time: i64) -> String {
  130. let mut max_withdrawal = dec!(0);
  131. let mut max_total_withdrawal = dec!(0);
  132. let mut total_income = dec!(0);
  133. let mut balance_info_map: BTreeMap<String, Vec<Vec<String>>> = BTreeMap::new();
  134. for info in balance_info.clone() {
  135. let mut default_info = balance_info_map.get(&info[0]).unwrap_or(&vec![]).clone();
  136. default_info.push(info.clone());
  137. balance_info_map.insert(info[0].clone(), default_info);
  138. }
  139. for (account_name, balance_info) in balance_info_map.clone() {
  140. for (index, info) in balance_info.iter().enumerate() {
  141. if index == 0 { continue; }
  142. let present = Decimal::from_str(&info[4]).unwrap();
  143. let past = Decimal::from_str(&balance_info[index - 1][4]).unwrap();
  144. let withdrawal = ((Decimal::ONE - (present / past)) * dec!(100)).round_dp(2);
  145. if account_name != "total_balance" {
  146. if max_withdrawal < withdrawal { max_withdrawal = withdrawal }
  147. } else {
  148. if max_total_withdrawal < withdrawal { max_total_withdrawal = withdrawal }
  149. }
  150. }
  151. if account_name == "total_balance" {
  152. let present = Decimal::from_str(&balance_info[0][4]).unwrap();
  153. let past = Decimal::from_str(&balance_info[balance_info.len() - 1][4]).unwrap();
  154. total_income = (((past / present) - Decimal::ONE) * dec!(100)).round_dp(2);
  155. }
  156. }
  157. let start_time = NaiveDateTime::from_timestamp_millis((count_start_time + 8 * 3600) * 1000).unwrap().format("%Y-%m-%d日%H点").to_string();
  158. let end_time = NaiveDateTime::from_timestamp_millis((end_start_time + 8 * 3600) * 1000).unwrap().format("%Y-%m-%d日%H点").to_string();
  159. format!("{}到{},总收益约为{}%,最大回撤约为{}%,其中单个账号最大回撤约为{}%。", start_time, end_time, total_income, max_total_withdrawal, max_withdrawal)
  160. }
  161. pub fn supply_balance(source_balance_info: BTreeMap<String, Vec<Vec<String>>>, time_slicer: Vec<i64>) -> Vec<Vec<String>> {
  162. let mut balance_info_list: Vec<Vec<String>> = vec![];
  163. for time in time_slicer.clone() {
  164. // 根据时间片去拿数据 ,如果有添加没有,手动添加
  165. let mut total_price = Decimal::ZERO;
  166. for (key, value) in source_balance_info.clone() {
  167. let mut balance_info = value.clone();
  168. balance_info.sort_by(|a, b| a[0].cmp(&b[0]));
  169. let mut new_info: Option<Vec<String>> = None;
  170. for mut info in balance_info.clone() {
  171. let info_time = info[0].parse::<i64>().unwrap();
  172. if info_time == time {
  173. match new_info {
  174. None => {
  175. info.insert(0, key.clone());
  176. new_info = Option::from(info);//记录当前实际
  177. }
  178. Some(ref value) => {
  179. if value[1] < info[1] {
  180. info.insert(0, key.clone());
  181. new_info = Option::from(info);//记录当前实际
  182. }
  183. }
  184. }
  185. break;
  186. }
  187. }
  188. match new_info {
  189. None => {
  190. let balance_info_filter: Vec<Vec<String>> = balance_info.iter().filter(|item| {
  191. item[0].parse::<i64>().unwrap() < time
  192. }).cloned().collect();
  193. let mut last_balance_info = balance_info_filter[balance_info_filter.len() - 1].clone();
  194. last_balance_info.insert(0, key.clone());
  195. total_price += Decimal::from_str(&last_balance_info[4]).unwrap();
  196. balance_info_list.push(last_balance_info);
  197. }
  198. Some(ref info) => {
  199. total_price += Decimal::from_str(&info[4]).unwrap();
  200. balance_info_list.push(info.clone());
  201. }
  202. }
  203. }
  204. 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()];
  205. balance_info_list.push(sum_row.clone());
  206. };
  207. balance_info_list
  208. }