phemex_swap_handle.rs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. use std::str::FromStr;
  2. use rust_decimal::Decimal;
  3. use rust_decimal::prelude::FromPrimitive;
  4. use rust_decimal_macros::dec;
  5. use serde_json::Value;
  6. use tokio::time::Instant;
  7. use tracing::{error};
  8. use exchanges::response_base::ResponseData;
  9. use global::trace_stack::TraceStack;
  10. use crate::{Account, MarketOrder, Order, Position, PositionModeEnum, SpecialDepth, SpecialOrder, SpecialTicker};
  11. // 处理账号信息
  12. pub fn handle_account_info(res_data: &ResponseData, symbol: &String) -> Account {
  13. let res_data_json = res_data.data.as_array().unwrap();
  14. format_account_info(res_data_json, symbol)
  15. }
  16. pub fn format_account_info(accounts: &Vec<Value>, symbol: &String) -> Account {
  17. let symbol_upper = symbol.to_uppercase();
  18. let symbol_array: Vec<&str> = symbol_upper.split("_").collect();
  19. let balance_info = accounts.iter().find(|&item| item["currency"].as_str().unwrap().contains(symbol_array[1]));
  20. match balance_info {
  21. None => {
  22. error!("Phemex:格式化账号信息错误!\nformat_account_info: accounts={:?}", accounts);
  23. panic!("Phemex:格式化账号信息错误!\nformat_account_info: accounts={:?}", accounts)
  24. }
  25. Some(value) => {
  26. let coin = value["currency"].as_str().unwrap().to_string();
  27. let balance = Decimal::from_str(value["accountBalanceRv"].as_str().unwrap()).unwrap();
  28. let frozen_balance = Decimal::from_str(value["totalUsedBalanceRv"].as_str().unwrap()).unwrap();
  29. let available_balance = balance - frozen_balance;
  30. Account {
  31. coin,
  32. balance,
  33. available_balance,
  34. frozen_balance,
  35. stocks: Decimal::ZERO,
  36. available_stocks: Decimal::ZERO,
  37. frozen_stocks: Decimal::ZERO,
  38. }
  39. }
  40. }
  41. }
  42. // 处理position信息
  43. pub fn handle_position(res_data: &ResponseData, ct_val: &Decimal) -> Vec<Position> {
  44. let res_data_json = res_data.data.as_array().unwrap();
  45. return res_data_json.iter().filter_map(|item| {
  46. let position = format_position_item(item, ct_val);
  47. if position.amount == Decimal::ZERO {
  48. None
  49. } else {
  50. Some(position)
  51. }
  52. }).collect();
  53. }
  54. pub fn format_position_item(position: &Value, ct_val: &Decimal) -> Position {
  55. let symbol = position["symbol"].as_str().unwrap().to_string();
  56. let margin_level = Decimal::from_str(position["leverageRr"].as_str().unwrap()).unwrap();
  57. let price = Decimal::from_str(position["avgEntryPriceRp"].as_str().unwrap()).unwrap();
  58. let profit = Decimal::from_str(position["curTermRealisedPnlRv"].as_str().unwrap()).unwrap();
  59. let margin = Decimal::from_str(position["positionMarginRv"].as_str().unwrap()).unwrap();
  60. let position_mode = match position["posSide"].as_str().unwrap_or("") {
  61. "Long" => PositionModeEnum::Long,
  62. "Short" => PositionModeEnum::Short,
  63. _ => {
  64. error!("phemex_swap:格式化持仓模式错误!\nformat_position_item:position={:?}", position);
  65. panic!("phemex_swap:格式化持仓模式错误!\nformat_position_item:position={:?}", position)
  66. }
  67. };
  68. let size = Decimal::from_str(&position["size"].as_str().unwrap()).unwrap();
  69. let amount = size * ct_val;
  70. Position {
  71. symbol,
  72. margin_level,
  73. amount,
  74. frozen_amount: Decimal::ZERO,
  75. price,
  76. profit,
  77. position_mode,
  78. margin,
  79. }
  80. }
  81. // 处理order信息
  82. pub fn handle_order(res_data: ResponseData, ct_val: Decimal) -> SpecialOrder {
  83. let orders = res_data.data.as_array().unwrap();
  84. let order_info = orders.iter().map(|item| format_order_item(item, ct_val)).collect();
  85. SpecialOrder {
  86. name: res_data.label,
  87. order: order_info,
  88. }
  89. }
  90. pub fn format_order_item(order: &Value, ct_val: Decimal) -> Order {
  91. let id = order["orderID"].as_str().unwrap().to_string();
  92. let custom_id = order["clOrdID"].as_str().unwrap().to_string();
  93. let price = Decimal::from_str(order["priceRp"].as_str().unwrap()).unwrap();
  94. let amount = Decimal::from_str(order["orderQty"].as_str().unwrap()).unwrap() * ct_val;
  95. let deal_amount = Decimal::from_str(order["cumQty"].as_str().unwrap()).unwrap() * ct_val;
  96. let avg_price = Decimal::from_str(order["cumValueRv"].as_str().unwrap()).unwrap();
  97. let status = order["ordStatus"].as_str().unwrap();
  98. let custom_status;
  99. if vec!["Rejected", "Filled", "Canceled"].contains(&status) {
  100. custom_status = "REMOVE".to_string()
  101. } else if vec!["New", "Init", "Created"].contains(&status) {
  102. custom_status = "NEW".to_string()
  103. } else {
  104. error!("gate_swap:格式化订单状态错误!\nformat_order_item:order={:?}", order);
  105. panic!("gate_swap:格式化订单状态错误!\nformat_order_item:order={:?}", order)
  106. };
  107. let result = Order {
  108. id,
  109. custom_id,
  110. price,
  111. amount,
  112. deal_amount,
  113. avg_price,
  114. status: custom_status,
  115. order_type: "limit".to_string(),
  116. trace_stack: TraceStack::new(0, Instant::now()).on_special("120 trace_stack".to_string()),
  117. };
  118. return result;
  119. }
  120. // 处理特殊Ticket信息
  121. pub fn handle_ticker(res_data: &ResponseData) -> SpecialDepth {
  122. let depth = &res_data.data;
  123. let bp = Decimal::from_str(depth["orderbook_p"]["bids"][0][0].as_str().unwrap()).unwrap();
  124. let bq = Decimal::from_str(depth["orderbook_p"]["bids"][0][1].as_str().unwrap()).unwrap();
  125. let ap = Decimal::from_str(depth["orderbook_p"]["asks"][0][0].as_str().unwrap()).unwrap();
  126. let aq = Decimal::from_str(depth["orderbook_p"]["asks"][0][1].as_str().unwrap()).unwrap();
  127. let mp = (bp + ap) * dec!(0.5);
  128. let t = Decimal::from_i64(depth["timestamp"].as_i64().unwrap() / 1_000_000).unwrap();
  129. let create_at = depth["timestamp"].as_i64().unwrap() / 1_000_000;
  130. let ticker_info = SpecialTicker { sell: ap, buy: bp, mid_price: mp, t, create_at };
  131. let depth_info = vec![bp, bq, ap, aq];
  132. SpecialDepth {
  133. name: (*res_data).label.clone(),
  134. depth: depth_info,
  135. ticker: ticker_info,
  136. t,
  137. create_at,
  138. }
  139. }
  140. pub fn format_depth_items(depth: Value) -> Vec<MarketOrder> {
  141. if depth.is_null() {
  142. return vec![];
  143. }
  144. let mut depth_items: Vec<MarketOrder> = vec![];
  145. for values in depth.as_array().unwrap() {
  146. let value = values.as_array().unwrap();
  147. depth_items.push(MarketOrder {
  148. price: Decimal::from_str(value[0].as_str().unwrap()).unwrap(),
  149. amount: Decimal::from_str(value[1].as_str().unwrap()).unwrap(),
  150. })
  151. }
  152. return depth_items;
  153. }