bybit_swap_handle.rs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. use std::str::FromStr;
  2. use std::time::SystemTime;
  3. use rust_decimal::Decimal;
  4. use serde_json::{from_value, Value};
  5. use tracing::{error};
  6. use exchanges::response_base::ResponseData;
  7. use rust_decimal::prelude::FromPrimitive;
  8. use crate::{Account, OrderBook, Order, Position, PositionModeEnum, SpecialOrder, Record, Trade};
  9. // 处理账号信息
  10. pub fn handle_account_info(res_data: &ResponseData, symbol: &String) -> Account {
  11. format_account_info(res_data.data.as_array().unwrap().clone(), symbol)
  12. }
  13. pub fn format_account_info(data: Vec<Value>, symbol: &String) -> Account {
  14. let account = data.iter().find(|&item| item["accountType"] == "UNIFIED");
  15. match account {
  16. None => {
  17. error!("Bybit:格式化统一账户信息错误!\nformat_account_info: data={:?}", data);
  18. panic!("Bybit:格式化统一账户信息错误!\nformat_account_info: data={:?}", data)
  19. }
  20. Some(val) => {
  21. let arr: Vec<Value> = from_value(val["coin"].clone()).unwrap();
  22. let upper_str = symbol.to_uppercase();
  23. let symbol_array: Vec<&str> = upper_str.split("_").collect();
  24. let balance_info = arr.iter().find(|&item| item["coin"].as_str().unwrap() == symbol_array[1]);
  25. match balance_info {
  26. None => {
  27. error!("Bybit:格式化usdt余额信息错误!\nformat_account_info: data={:?}", balance_info);
  28. panic!("Bybit:格式化usdt余额信息错误!\nformat_account_info: data={:?}", balance_info)
  29. }
  30. Some(value) => {
  31. let balance = Decimal::from_str(&value["walletBalance"].as_str().unwrap().to_string()).unwrap();
  32. Account {
  33. coin: symbol_array[1].to_string(),
  34. balance,
  35. available_balance: Decimal::ZERO,
  36. frozen_balance: Decimal::ZERO,
  37. stocks: Decimal::ZERO,
  38. available_stocks: Decimal::ZERO,
  39. frozen_stocks: Decimal::ZERO,
  40. }
  41. }
  42. }
  43. }
  44. }
  45. }
  46. // 处理position信息
  47. pub fn handle_position(res_data: &ResponseData, ct_val: &Decimal) -> Vec<Position> {
  48. res_data.data.as_array().unwrap().iter().map(|item| { format_position_item(item, ct_val) }).collect()
  49. }
  50. pub fn format_position_item(position: &Value, ct_val: &Decimal) -> Position {
  51. let position_idx: String = position["positionIdx"].to_string();
  52. let mut position_mode = match position_idx.as_str() {
  53. "0" => PositionModeEnum::Both,
  54. "1" => PositionModeEnum::Long,
  55. "2" => PositionModeEnum::Short,
  56. _ => {
  57. error!("bybit_swap:格式化持仓模式错误!\nformat_position_item:position={:?}", position);
  58. panic!("bybit_swap:格式化持仓模式错误!\nformat_position_item:position={:?}", position)
  59. }
  60. };
  61. let symbol_mapper = position["symbol"].as_str().unwrap().to_string();
  62. let currency = "USDT";
  63. let coin = &symbol_mapper[..symbol_mapper.find(currency).unwrap_or(0)];
  64. let size_str: String = from_value(position["size"].clone()).unwrap();
  65. let size = Decimal::from_str(size_str.as_str()).unwrap();
  66. let amount = size * ct_val;
  67. match position_mode {
  68. PositionModeEnum::Both => {
  69. position_mode = match amount {
  70. amount if amount > Decimal::ZERO => PositionModeEnum::Long,
  71. amount if amount < Decimal::ZERO => PositionModeEnum::Short,
  72. _ => { PositionModeEnum::Both }
  73. }
  74. }
  75. _ => {}
  76. }
  77. Position {
  78. symbol: format! {"{}_{}", coin, currency},
  79. margin_level: Decimal::from_str(position["leverage"].as_str().unwrap()).unwrap(),
  80. amount,
  81. frozen_amount: Decimal::ZERO,
  82. price: Decimal::from_str(position["entryPrice"].as_str().unwrap()).unwrap(),
  83. profit: Decimal::from_str(position["unrealisedPnl"].as_str().unwrap()).unwrap(),
  84. position_mode,
  85. margin: Decimal::from_str(position["positionBalance"].as_str().unwrap()).unwrap(),
  86. }
  87. }
  88. // 处理order信息
  89. pub fn handle_order(res_data: &ResponseData, ct_val: Decimal) -> SpecialOrder {
  90. let res_data_json: Vec<Value> = res_data.data.as_array().unwrap().clone();
  91. let mut order_info = Vec::new();
  92. for item in res_data_json.iter() {
  93. order_info.push(format_order_item(item.clone(), ct_val));
  94. };
  95. SpecialOrder {
  96. name: res_data.tag.clone(),
  97. order: order_info,
  98. }
  99. }
  100. pub fn format_order_item(order: Value, ct_val: Decimal) -> Order {
  101. let status = order["orderStatus"].as_str().unwrap_or("");
  102. let text = order["orderLinkId"].as_str().unwrap_or("");
  103. let size = Decimal::from_str(order["qty"].as_str().unwrap()).unwrap();
  104. let right = Decimal::from_str(order["cumExecQty"].as_str().unwrap()).unwrap();
  105. let right_val = Decimal::from_str(order["cumExecValue"].as_str().unwrap()).unwrap();
  106. let price = Decimal::from_str(order["price"].as_str().unwrap()).unwrap();
  107. let amount = size * ct_val;
  108. let mut avg_price = Decimal::ZERO;
  109. if right != Decimal::ZERO {
  110. avg_price = right_val / right;
  111. }
  112. let deal_amount = right * ct_val;
  113. let custom_status = if status == "Filled" || status == "Cancelled" { "REMOVE".to_string() } else if status == "New" { "NEW".to_string() } else {
  114. "NULL".to_string()
  115. };
  116. let rst_order = Order {
  117. id: format!("{}", order["orderId"].as_str().unwrap()),
  118. custom_id: text.replace("t-my-custom-id_", "").replace("t-", ""),
  119. price,
  120. amount,
  121. deal_amount,
  122. avg_price,
  123. status: custom_status,
  124. order_type: "limit".to_string(),
  125. };
  126. return rst_order;
  127. }
  128. // 处理特殊Ticket信息
  129. // pub fn handle_ticker(res_data: &ResponseData) -> SpecialDepth {
  130. // let ap = Decimal::from_str(res_data.data["ask1Price"].as_str().unwrap()).unwrap();
  131. // let bp = Decimal::from_str(res_data.data["bid1Price"].as_str().unwrap()).unwrap();
  132. // let aq = Decimal::from_str(res_data.data["ask1Size"].as_str().unwrap()).unwrap();
  133. // let bq = Decimal::from_str(res_data.data["bid1Size"].as_str().unwrap()).unwrap();
  134. // let mp = (bp + ap) * dec!(0.5);
  135. //
  136. // let t = Decimal::from_i64(res_data.data["ts"].as_i64().unwrap()).unwrap();
  137. // let create_at = t.to_i64().unwrap();
  138. //
  139. // let ticker_info = SpecialTicker { sell: ap, buy: bp, mid_price: mp, t, create_at: 0 };
  140. // let depth_info = vec![bp, bq, ap, aq];
  141. // SpecialDepth {
  142. // name: res_data.tag.clone(),
  143. // depth: depth_info,
  144. // ticker: ticker_info,
  145. // t,
  146. // create_at,
  147. // }
  148. // }
  149. pub fn format_depth_items(value: serde_json::Value) -> Vec<OrderBook> {
  150. let mut depth_items: Vec<OrderBook> = vec![];
  151. for val in value.as_array().unwrap() {
  152. let arr = val.as_array().unwrap();
  153. depth_items.push(OrderBook {
  154. price: Decimal::from_str(arr[0].as_str().unwrap()).unwrap(),
  155. amount: Decimal::from_str(arr[1].as_str().unwrap()).unwrap(),
  156. })
  157. }
  158. return depth_items;
  159. }
  160. pub fn handle_records(value: &Value) -> Vec<Record> {
  161. let mut records = vec![];
  162. let s = value["topic"].as_str().unwrap().to_string();
  163. let s_split: Vec<String> = s.split(".").map(|s| s.to_string()).collect();
  164. let symbol = s_split[2].replace("USDT", "_USDT");
  165. let data = value["data"].clone();
  166. for record_value in data.as_array().unwrap() {
  167. records.push(Record {
  168. time: Decimal::from_i64(record_value["timestamp"].as_i64().unwrap()).unwrap(),
  169. open: Decimal::from_str(record_value["open"].as_str().unwrap()).unwrap(),
  170. high: Decimal::from_str(record_value["high"].as_str().unwrap()).unwrap(),
  171. low: Decimal::from_str(record_value["low"].as_str().unwrap()).unwrap(),
  172. close: Decimal::from_str(record_value["close"].as_str().unwrap()).unwrap(),
  173. volume: Decimal::from_str(record_value["volume"].as_str().unwrap()).unwrap(),
  174. symbol: symbol.clone(),
  175. });
  176. }
  177. return records;
  178. }
  179. pub fn format_trade_items(res_data: &ResponseData) -> Vec<Trade> {
  180. let result = res_data.data["data"].as_array().unwrap();
  181. let mut trades = vec![];
  182. for item in result {
  183. let side = item["S"].as_str().unwrap();
  184. let size = Decimal::from_str(item["v"].as_str().unwrap()).unwrap();
  185. let id = SystemTime::now().duration_since(std::time::UNIX_EPOCH).expect("Time went backwards").as_nanos().to_string();
  186. trades.push(Trade {
  187. id: id.clone(),
  188. time: Decimal::from_i64(item["T"].as_i64().unwrap()).unwrap(),
  189. size: if side == "Buy" { size } else { -size },
  190. price: Decimal::from_str(item["p"].as_str().unwrap()).unwrap(),
  191. symbol: item["s"].as_str().unwrap().replace("USDT", "_USDT"),
  192. })
  193. }
  194. return trades;
  195. }