bitget_swap_handle.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. use std::str::FromStr;
  2. use rust_decimal::Decimal;
  3. use rust_decimal::prelude::FromPrimitive;
  4. use serde_json::Value;
  5. use tokio::time::Instant;
  6. use tracing::error;
  7. use exchanges::response_base::ResponseData;
  8. use global::trace_stack::TraceStack;
  9. use crate::{Account, OrderBook, Order, Position, PositionModeEnum, SpecialOrder, Depth, Trade, Record};
  10. // 处理账号信息
  11. pub fn handle_account_info(response: &ResponseData, _symbol: &String) -> Account {
  12. let mut rst = Account::new();
  13. let data_info = response.data["data"].clone();
  14. for data in data_info.as_array().unwrap() {
  15. if data["marginCoin"].as_str().unwrap() != "USDT" {
  16. continue;
  17. }
  18. // 格式化account信息
  19. let mut account = Account {
  20. coin: data["marginCoin"].to_string(),
  21. balance: Decimal::from_str(data["usdtEquity"].as_str().unwrap()).unwrap(),
  22. available_balance: Decimal::from_str(data["available"].as_str().unwrap()).unwrap(),
  23. frozen_balance: Decimal::from_str(data["frozen"].as_str().unwrap()).unwrap(),
  24. stocks: Default::default(),
  25. available_stocks: Default::default(),
  26. frozen_stocks: Default::default(),
  27. };
  28. account.frozen_balance = account.balance - account.available_balance;
  29. rst = account
  30. }
  31. return rst;
  32. }
  33. // 处理order信息
  34. pub fn handle_order(res_data: &ResponseData, multiplier: &Decimal) -> SpecialOrder {
  35. let data_info = res_data.data["data"].clone();
  36. let res_data_json = data_info.as_array().unwrap();
  37. let mut order_info = Vec::new();
  38. for item in res_data_json.iter() {
  39. order_info.push(format_order_item(item.clone(), multiplier.clone()));
  40. }
  41. SpecialOrder {
  42. name: res_data.label.clone(),
  43. order: order_info,
  44. }
  45. }
  46. // 处理订单信息
  47. pub fn format_order_item(order: Value, _multiplier: Decimal) -> Order {
  48. let price = Decimal::from_str(order["price"].as_str().unwrap().to_string().as_str()).unwrap();
  49. let size = Decimal::from_str(order["size"].as_str().unwrap().to_string().as_str()).unwrap();
  50. let binding = order["status"].clone().as_str().unwrap().to_string();
  51. let status = binding.as_str();
  52. let acc_base_volume = Decimal::from_str(order["accBaseVolume"].as_str().unwrap().to_string().as_str()).unwrap();
  53. let avg_price = if order["priceAvg"].is_null() || order["priceAvg"].as_str().unwrap().is_empty() {
  54. Decimal::ZERO
  55. } else {
  56. Decimal::from_str(order["priceAvg"].as_str().unwrap().to_string().as_str()).unwrap()
  57. };
  58. let c_id = if order["clientOid"].is_null() {
  59. ""
  60. } else {
  61. order["clientOid"].as_str().unwrap()
  62. };
  63. let amount = size;
  64. let deal_amount = acc_base_volume;
  65. let custom_status = if ["filled", "canceled"].contains(&status) {
  66. "REMOVE".to_string()
  67. } else if ["init", "live", "new", "partially_filled"].contains(&status) {
  68. "NEW".to_string()
  69. } else {
  70. "NULL".to_string()
  71. };
  72. Order {
  73. id: order["orderId"].as_str().unwrap().to_string(),
  74. custom_id: c_id.to_string(),
  75. price,
  76. amount,
  77. deal_amount,
  78. avg_price,
  79. status: custom_status,
  80. order_type: order["orderType"].as_str().unwrap().to_string(),
  81. trace_stack: TraceStack::new(0, Instant::now()).on_special("86 bitget_swap_handle".to_string()),
  82. }
  83. }
  84. // 格式化深度信息
  85. pub fn format_depth_items(value: Value, mul: &Decimal) -> Vec<OrderBook> {
  86. let mut depth_items: Vec<OrderBook> = vec![];
  87. for value in value.as_array().unwrap() {
  88. let price = Decimal::from_str(value[0].as_str().unwrap()).unwrap();
  89. let size = Decimal::from_str(value[1].as_str().unwrap()).unwrap();
  90. depth_items.push(OrderBook {
  91. price,
  92. size,
  93. value: price * size * mul,
  94. })
  95. }
  96. return depth_items;
  97. }
  98. // 处理position信息
  99. pub fn handle_position(res_data: &ResponseData, multiplier: &Decimal) -> Vec<Position> {
  100. let data_info = res_data.data["data"].clone();
  101. let data_info_json = data_info.as_array().unwrap();
  102. data_info_json.iter().map(|item| { format_position_item(item, multiplier) }).collect()
  103. }
  104. pub fn format_position_item(position_json: &Value, _multiplier: &Decimal) -> Position {
  105. let symbol = position_json["instId"].as_str().unwrap().to_string();
  106. let margin_level = Decimal::from_i64(position_json["leverage"].as_i64().unwrap()).unwrap();
  107. let amount = Decimal::from_str(position_json["total"].as_str().unwrap()).unwrap();
  108. let frozen_amount = Decimal::from_str(position_json["frozen"].as_str().unwrap()).unwrap();
  109. let price = Decimal::from_str(position_json["openPriceAvg"].as_str().unwrap()).unwrap();
  110. let profit = Decimal::from_str(position_json["unrealizedPL"].as_str().unwrap()).unwrap();
  111. let mut position_mode = match position_json["posMode"].as_str().unwrap() {
  112. "hedge_mode" => {
  113. match position_json["holdSide"].as_str().unwrap() {
  114. "short" => {
  115. PositionModeEnum::Short
  116. }
  117. "long" => {
  118. PositionModeEnum::Long
  119. }
  120. _ => {
  121. panic!("bitget_usdt_swap: 未知的持仓模式与持仓方向: {}, {}",
  122. position_json["posMode"].as_str().unwrap(), position_json["holdSide"].as_str().unwrap())
  123. }
  124. }
  125. }
  126. "one_way_mode" => {
  127. PositionModeEnum::Both
  128. }
  129. _ => {
  130. panic!("bitget_usdt_swap: 未知的持仓模式: {}", position_json["posMode"].as_str().unwrap())
  131. }
  132. };
  133. let margin = Decimal::from_str(position_json["marginSize"].as_str().unwrap()).unwrap();
  134. let side = position_json["holdSide"].as_str().unwrap();
  135. match position_mode {
  136. PositionModeEnum::Both => {
  137. position_mode = match side {
  138. "long" => PositionModeEnum::Long,
  139. "short" => PositionModeEnum::Short,
  140. _ => { PositionModeEnum::Both }
  141. }
  142. }
  143. _ => {}
  144. }
  145. Position {
  146. symbol,
  147. margin_level,
  148. amount,
  149. frozen_amount,
  150. price,
  151. profit,
  152. position_mode,
  153. margin,
  154. }
  155. }
  156. pub fn format_trade_items(response: &ResponseData) -> Vec<Trade> {
  157. let data_info = response.data["data"].clone();
  158. let result = data_info.as_array().unwrap();
  159. let mut trades = vec![];
  160. for item in result {
  161. // 因为gate的量都是张数,所以要进行真实交易量处理
  162. let mut size = Decimal::from_str(item["size"].as_str().unwrap()).unwrap();
  163. let price = Decimal::from_str(item["price"].as_str().unwrap().to_string().as_str()).unwrap();
  164. let side = item["side"].as_str().unwrap().to_string();
  165. size = match side.as_str() {
  166. "buy" => {
  167. size
  168. }
  169. "sell" => {
  170. -size
  171. }
  172. _ => {
  173. error!("{}", item.to_string());
  174. panic!("Bitget trade error side(bitget_swap_handle_156)")
  175. }
  176. };
  177. let value = (size * price).abs();
  178. trades.push(Trade {
  179. id: item["tradeId"].as_str().unwrap().to_string(),
  180. time: Decimal::from_str(item["ts"].as_str().unwrap()).unwrap(),
  181. size,
  182. price,
  183. value,
  184. symbol: response.data["arg"]["instId"].as_str().unwrap().replace("USDT", "_USDT"),
  185. })
  186. }
  187. return trades;
  188. }
  189. pub fn handle_book_ticker(res_data: &ResponseData, mul: &Decimal) -> Depth {
  190. let data_info = res_data.data["data"].clone();
  191. let asks = format_depth_items(data_info[0]["asks"].clone(), mul);
  192. let bids = format_depth_items(data_info[0]["bids"].clone(), mul);
  193. let t = Decimal::from_i64(res_data.reach_time).unwrap();
  194. let s = res_data.data["arg"]["instId"].as_str().unwrap().replace("USDT", "_USDT");
  195. Depth {
  196. time: t,
  197. symbol: s.to_string(),
  198. asks,
  199. bids,
  200. }
  201. }
  202. pub fn handle_records(value: &Value) -> Vec<Record> {
  203. let data_info = value["data"].clone();
  204. let mut records = vec![];
  205. for record_value in data_info.as_array().unwrap() {
  206. records.push(Record {
  207. time: Decimal::from_str(record_value[0].as_str().unwrap()).unwrap(),
  208. open: Decimal::from_str(record_value[1].as_str().unwrap()).unwrap(),
  209. high: Decimal::from_str(record_value[2].as_str().unwrap()).unwrap(),
  210. low: Decimal::from_str(record_value[3].as_str().unwrap()).unwrap(),
  211. close: Decimal::from_str(record_value[4].as_str().unwrap()).unwrap(),
  212. volume: Decimal::from_str(record_value[5].as_str().unwrap()).unwrap(),
  213. symbol: value["arg"]["instId"].as_str().unwrap().replace("USDT", "_USDT"),
  214. });
  215. }
  216. return records;
  217. }
  218. // 处理特殊深度数据
  219. // pub fn handle_special_depth(res_data: ResponseData) -> SpecialDepth {
  220. // HandleSwapInfo::handle_special_depth(ExchangeEnum::BitgetSwap, res_data)
  221. // }
  222. // // 处理特殊Ticker信息
  223. // pub fn handle_special_ticker(res_data: ResponseData) -> SpecialDepth {
  224. // let res_data_str = res_data.data;
  225. // let res_data_json: Vec<serde_json::Value> = serde_json::from_str(&*res_data_str).unwrap();
  226. // format_special_ticker(res_data_json[0].clone(), res_data.label)
  227. // }
  228. //
  229. // pub fn format_special_ticker(data: serde_json::Value, label: String) -> SpecialDepth {
  230. // let bp = Decimal::from_str(data["bidPr"].as_str().unwrap()).unwrap();
  231. // let bq = Decimal::from_str(data["bidSz"].as_str().unwrap()).unwrap();
  232. // let ap = Decimal::from_str(data["askPr"].as_str().unwrap()).unwrap();
  233. // let aq = Decimal::from_str(data["askSz"].as_str().unwrap()).unwrap();
  234. // let mp = (bp + ap) * dec!(0.5);
  235. // let t = Decimal::from_str(data["ts"].as_str().unwrap()).unwrap();
  236. // let create_at = data["ts"].as_str().unwrap().parse::<i64>().unwrap() * 1000;
  237. //
  238. // let ticker_info = SpecialTicker { sell: ap, buy: bp, mid_price: mp, t, create_at };
  239. // let depth_info = vec![bp, bq, ap, aq];
  240. // SpecialDepth {
  241. // name: label,
  242. // depth: depth_info,
  243. // ticker: ticker_info,
  244. // t,
  245. // create_at,
  246. // }
  247. // }