bybit_swap.rs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. use std::collections::{BTreeMap};
  2. use std::io::{Error, ErrorKind};
  3. use std::str::FromStr;
  4. use tokio::sync::mpsc::Sender;
  5. use async_trait::async_trait;
  6. use rust_decimal::Decimal;
  7. use serde_json::{from_value, json, Value};
  8. use rust_decimal::prelude::FromPrimitive;
  9. use serde::{Deserialize, Serialize};
  10. use tracing::{error, trace};
  11. use exchanges::bybit_swap_rest::BybitSwapRest;
  12. use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, PositionModeEnum};
  13. #[derive(Debug, Clone, Deserialize, Serialize)]
  14. #[serde(rename_all = "camelCase")]
  15. struct SwapTicker {
  16. symbol: String,
  17. high_price24h: Decimal,
  18. low_price24h: Decimal,
  19. bid1_price: Decimal,
  20. ask1_price: Decimal,
  21. last_price: Decimal,
  22. volume24h: Decimal
  23. }
  24. #[allow(dead_code)]
  25. #[derive(Clone)]
  26. pub struct BybitSwap {
  27. exchange: ExchangeEnum,
  28. symbol: String,
  29. symbol_uppercase: String,
  30. is_colo: bool,
  31. params: BTreeMap<String, String>,
  32. request: BybitSwapRest,
  33. market: Market,
  34. order_sender: Sender<Order>,
  35. error_sender: Sender<Error>,
  36. }
  37. impl BybitSwap {
  38. pub async fn new(symbol: String, is_colo: bool, params: BTreeMap<String, String>, order_sender: Sender<Order>, error_sender: Sender<Error>) -> BybitSwap {
  39. let market = Market::new();
  40. let mut bybit_swap = BybitSwap {
  41. exchange: ExchangeEnum::BybitSwap,
  42. symbol: symbol.to_uppercase(),
  43. symbol_uppercase: symbol.replace("_", "").to_uppercase(),
  44. is_colo,
  45. params: params.clone(),
  46. request: BybitSwapRest::new(is_colo, params.clone()),
  47. market,
  48. order_sender,
  49. error_sender,
  50. };
  51. // 修改持仓模式
  52. let symbol_array: Vec<&str> = symbol.split("_").collect();
  53. let mode_result = bybit_swap.set_dual_mode(symbol_array[1], true).await;
  54. match mode_result {
  55. Ok(_) => {
  56. trace!("Bybit:设置持仓模式成功!")
  57. }
  58. Err(error) => {
  59. error!("Bybit:设置持仓模式失败!mode_result={}", error)
  60. }
  61. }
  62. // 获取市场信息
  63. bybit_swap.market = BybitSwap::get_market(&mut bybit_swap).await.unwrap_or(bybit_swap.market);
  64. return bybit_swap;
  65. }
  66. }
  67. #[async_trait]
  68. impl Platform for BybitSwap {
  69. // 克隆方法
  70. fn clone_box(&self) -> Box<dyn Platform + Send + Sync> { Box::new(self.clone()) }
  71. // 获取交易所模式
  72. fn get_self_exchange(&self) -> ExchangeEnum {
  73. ExchangeEnum::GateSwap
  74. }
  75. // 获取交易对
  76. fn get_self_symbol(&self) -> String { self.symbol.clone() }
  77. // 获取是否使用高速通道
  78. fn get_self_is_colo(&self) -> bool {
  79. self.is_colo
  80. }
  81. // 获取params信息
  82. fn get_self_params(&self) -> BTreeMap<String, String> {
  83. self.params.clone()
  84. }
  85. // 获取market信息
  86. fn get_self_market(&self) -> Market { self.market.clone() }
  87. // 获取请求时间
  88. fn get_request_delays(&self) -> Vec<i64> { self.request.get_delays() }
  89. // 获取请求平均时间
  90. fn get_request_avg_delay(&self) -> Decimal { self.request.get_avg_delay() }
  91. // 获取请求最大时间
  92. fn get_request_max_delay(&self) -> i64 { self.request.get_max_delay() }
  93. // 获取服务器时间
  94. async fn get_server_time(&mut self) -> Result<String, Error> {
  95. let res_data = self.request.get_server_time().await;
  96. if res_data.code == 200 {
  97. let result = res_data.data["server_time"].to_string();
  98. Ok(result)
  99. } else {
  100. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  101. }
  102. }
  103. // 获取账号信息
  104. async fn get_account(&mut self) -> Result<Account, Error> {
  105. let symbol_array: Vec<&str> = self.symbol.split("_").collect();
  106. let res_data = self.request.get_account_balance(symbol_array[1].parse().unwrap()).await;
  107. if res_data.code == 200 {
  108. let arr_infos: Vec<Value> = from_value(res_data.data["list"].clone()).unwrap();
  109. if arr_infos.len() < 1usize{
  110. return Err(Error::new(ErrorKind::NotFound, format!("{} 无账户信息", symbol_array[1])));
  111. }
  112. let coin_infos: Vec<Value> = from_value(arr_infos[0]["coin"].clone()).unwrap();
  113. if coin_infos.len() < 1usize{
  114. return Err(Error::new(ErrorKind::NotFound, format!("{} 无账户信息", symbol_array[1])));
  115. }
  116. let balance = Decimal::from_str(coin_infos[0]["equity"].as_str().unwrap()).unwrap();
  117. let available_balance = Decimal::from_str(coin_infos[0]["walletBalance"].as_str().unwrap()).unwrap();
  118. let frozen_balance = balance - available_balance;
  119. let result = Account {
  120. coin: symbol_array[1].to_string(),
  121. balance,
  122. available_balance,
  123. frozen_balance,
  124. stocks: Decimal::ZERO,
  125. available_stocks: Decimal::ZERO,
  126. frozen_stocks: Decimal::ZERO,
  127. };
  128. Ok(result)
  129. } else {
  130. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  131. }
  132. }
  133. async fn get_spot_account(&mut self) -> Result<Vec<Account>, Error> {
  134. Err(Error::new(ErrorKind::NotFound, "bybit_swap:该交易所方法未实现".to_string()))
  135. }
  136. // 获取持仓信息
  137. async fn get_position(&mut self) -> Result<Vec<Position>, Error> {
  138. let symbol = self.symbol_uppercase.clone();
  139. let ct_val = self.market.ct_val;
  140. let res_data = self.request.get_positions(symbol, "".to_string()).await;
  141. if res_data.code == 200 {
  142. let result = res_data.data["list"].as_array().unwrap().iter().map(|item| { format_position_item(item, ct_val) }).collect();
  143. Ok(result)
  144. } else {
  145. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  146. }
  147. }
  148. // 获取所有持仓
  149. async fn get_positions(&mut self) -> Result<Vec<Position>, Error> {
  150. let symbol_array: Vec<&str> = self.symbol.split("_").collect();
  151. let ct_val = self.market.ct_val;
  152. let res_data = self.request.get_positions("".to_string(), symbol_array[1].to_string().to_uppercase()).await;
  153. if res_data.code == 200 {
  154. let result = res_data.data["list"].as_array().unwrap().iter().map(|item| { format_position_item(item, ct_val) }).collect();
  155. Ok(result)
  156. } else {
  157. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  158. }
  159. }
  160. // 获取市场行情
  161. async fn get_ticker(&mut self) -> Result<Ticker, Error> {
  162. let symbol = self.symbol_uppercase.clone();
  163. let res_data = self.request.get_tickers(symbol).await;
  164. if res_data.code == 200 {
  165. let list :Vec<SwapTicker> = from_value(res_data.data["list"].clone()).unwrap_or(Vec::new());
  166. if list.len() < 1usize {
  167. error!("bybit_swap:获取Ticker信息错误!\nget_ticker:res_data={:?}", res_data);
  168. return Err(Error::new(ErrorKind::Other, res_data.to_string()));
  169. }
  170. let value = list[0].clone();
  171. Ok(Ticker{
  172. time: chrono::Utc::now().timestamp_millis(),
  173. high: value.high_price24h,
  174. low: value.low_price24h,
  175. sell: value.ask1_price,
  176. buy: value.bid1_price,
  177. last: value.last_price,
  178. volume: value.volume24h
  179. })
  180. } else {
  181. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  182. }
  183. }
  184. async fn get_ticker_symbol(&mut self, symbol: String) -> Result<Ticker, Error> {
  185. let symbol_upper = symbol.replace("_", "").to_uppercase();
  186. let res_data = self.request.get_tickers(symbol_upper.clone()).await;
  187. if res_data.code == 200 {
  188. let list: Vec<SwapTicker> = from_value(res_data.data["list"].clone()).unwrap();
  189. let ticker_info = list.iter().find(|&item| item.symbol == symbol_upper);
  190. match ticker_info {
  191. None => {
  192. error!("bybit_swap:获取Ticker信息错误!\nget_ticker:res_data={:?}", res_data);
  193. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  194. }
  195. Some(value) => {
  196. let result = Ticker {
  197. time: chrono::Utc::now().timestamp_millis(),
  198. high: value.high_price24h,
  199. low: value.low_price24h,
  200. sell: value.ask1_price,
  201. buy: value.bid1_price,
  202. last: value.last_price,
  203. volume: value.volume24h
  204. };
  205. Ok(result)
  206. }
  207. }
  208. } else {
  209. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  210. }
  211. }
  212. async fn get_market(&mut self) -> Result<Market, Error> {
  213. let symbol = self.symbol_uppercase.clone();
  214. let res_data = self.request.get_instruments_info(symbol.clone()).await;
  215. if res_data.code == 200 {
  216. let arr_data: Vec<Value> = from_value(res_data.data["list"].clone()).unwrap();
  217. let market_info = arr_data.iter().find(|&item| item["symbol"].as_str().unwrap() == symbol);
  218. match market_info {
  219. None => {
  220. error!("bybit_swap:获取Market信息错误!\nget_market:res_data={:?}", res_data);
  221. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  222. }
  223. Some(value) => {
  224. let base_coin = value["baseCoin"].as_str().unwrap();
  225. let quote_coin = value["quoteCoin"].as_str().unwrap();
  226. let name = format!("{}_{}",base_coin, quote_coin);
  227. let tick_size = Decimal::from_str(value["priceFilter"]["minPrice"].as_str().unwrap().trim()).unwrap();
  228. let min_qty = Decimal::from_str(value["lotSizeFilter"]["minOrderQty"].as_str().unwrap().trim()).unwrap();
  229. let max_qty = Decimal::from_str(value["lotSizeFilter"]["maxOrderQty"].as_str().unwrap().trim()).unwrap();
  230. let ct_val = Decimal::ONE;
  231. let amount_size = min_qty * ct_val;
  232. let price_precision = Decimal::from_u32(tick_size.scale()).unwrap();
  233. let amount_precision = Decimal::from_u32(amount_size.scale()).unwrap();
  234. let min_notional = min_qty * ct_val;
  235. let max_notional = max_qty * ct_val;
  236. let result = Market {
  237. symbol: name,
  238. base_asset: base_coin.to_string(),
  239. quote_asset: quote_coin.to_string(),
  240. tick_size,
  241. amount_size,
  242. price_precision,
  243. amount_precision,
  244. min_qty,
  245. max_qty,
  246. min_notional,
  247. max_notional,
  248. ct_val,
  249. };
  250. Ok(result)
  251. }
  252. }
  253. } else {
  254. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  255. }
  256. }
  257. async fn get_market_symbol(&mut self, symbol: String) -> Result<Market, Error> {
  258. let symbol = symbol.replace("_", "").to_uppercase();
  259. let res_data = self.request.get_instruments_info(symbol.clone()).await;
  260. if res_data.code == 200 {
  261. let arr_data: Vec<Value> = from_value(res_data.data["list"].clone()).unwrap();
  262. let market_info = arr_data.iter().find(|item| item["symbol"].as_str().unwrap() == symbol);
  263. match market_info {
  264. None => {
  265. error!("bybit_swap:获取Market信息错误!\nget_market:res_data={:?}", res_data);
  266. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  267. }
  268. Some(value) => {
  269. let base_coin = value["baseCoin"].as_str().unwrap();
  270. let quote_coin = value["quoteCoin"].as_str().unwrap();
  271. let name = format!("{}_{}",base_coin, quote_coin);
  272. let tick_size = Decimal::from_str(value["priceFilter"]["minPrice"].as_str().unwrap().trim()).unwrap();
  273. let min_qty = Decimal::from_str(value["lotSizeFilter"]["minOrderQty"].as_str().unwrap().trim()).unwrap();
  274. let max_qty = Decimal::from_str(value["lotSizeFilter"]["maxOrderQty"].as_str().unwrap().trim()).unwrap();
  275. let ct_val = Decimal::ONE;
  276. let amount_size = min_qty * ct_val;
  277. let price_precision = Decimal::from_u32(tick_size.scale()).unwrap();
  278. let amount_precision = Decimal::from_u32(amount_size.scale()).unwrap();
  279. let min_notional = min_qty * ct_val;
  280. let max_notional = max_qty * ct_val;
  281. let result = Market {
  282. symbol: name,
  283. base_asset: base_coin.to_string(),
  284. quote_asset: quote_coin.to_string(),
  285. tick_size,
  286. amount_size,
  287. price_precision,
  288. amount_precision,
  289. min_qty,
  290. max_qty,
  291. min_notional,
  292. max_notional,
  293. ct_val,
  294. };
  295. Ok(result)
  296. }
  297. }
  298. } else {
  299. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  300. }
  301. }
  302. // 获取订单详情
  303. async fn get_order_detail(&mut self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
  304. let symbol = self.symbol_uppercase.clone();
  305. let ct_val = self.market.ct_val;
  306. let id = if !custom_id.trim().eq("") { format!("t-{}", custom_id) } else { String::new() };
  307. let res_data = self.request.get_order(symbol, order_id.parse().unwrap(), id).await;
  308. if res_data.code == 200 {
  309. let res_data_json: Value = res_data.data["list"].clone();
  310. if res_data_json.is_array() && res_data_json.as_array().unwrap().len() == 0 {
  311. return Err(Error::new(ErrorKind::Other, "没有该订单!"));
  312. }
  313. let result = format_order_item(res_data_json.as_array().unwrap()[0].clone(), ct_val);
  314. Ok(result)
  315. } else {
  316. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  317. }
  318. }
  319. // 获取订单列表
  320. async fn get_orders_list(&mut self, _status: &str) -> Result<Vec<Order>, Error> {
  321. Err(Error::new(ErrorKind::Other, "bybit获取订单列表暂未实现".to_string()))
  322. }
  323. // 下单接口
  324. async fn take_order(&mut self, custom_id: &str, origin_side: &str, price: Decimal, amount: Decimal) -> Result<Order, Error> {
  325. let symbol = self.symbol_uppercase.clone();
  326. let ct_val = self.market.ct_val;
  327. let size = amount / ct_val;
  328. let mut params = json!({
  329. "orderLinkId": format!("t-{}", custom_id),
  330. "symbol": symbol.to_string(),
  331. "price": price.to_string(),
  332. "category": "linear",
  333. "orderType":"Limit",
  334. "qty": json!(size),
  335. // 0.單向持倉 1.買側雙向持倉 2.賣側雙向持倉
  336. "positionIdx": json!(1),
  337. "reduceOnly": json!(false)
  338. });
  339. if price.eq(&Decimal::ZERO) {
  340. params["timeInForce"] = json!("IOC".to_string());
  341. }
  342. match origin_side {
  343. "kd" => {
  344. params["side"] = json!("Buy");
  345. }
  346. "pd" => {
  347. params["side"] = json!("Sell");
  348. // 减仓
  349. params["reduceOnly"] = json!(true);
  350. }
  351. "kk" => {
  352. params["side"] = json!("Sell");
  353. params["positionIdx"] = json!(2);
  354. }
  355. "pk" => {
  356. params["side"] = json!("Buy");
  357. // 减仓
  358. params["reduceOnly"] = json!(true);
  359. params["positionIdx"] = json!(2);
  360. }
  361. _ => { error!("下单参数错误"); }
  362. };
  363. let res_data = self.request.swap_order(params).await;
  364. if res_data.code == 200 {
  365. let result = format_new_order_item(res_data.data, price, size);
  366. Ok(result)
  367. } else {
  368. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  369. }
  370. }
  371. async fn take_order_symbol(&mut self, symbol: String, ct_val: Decimal, custom_id: &str, origin_side: &str, price: Decimal, amount: Decimal) -> Result<Order, Error> {
  372. let symbol_upper = symbol.replace("_", "").trim().to_uppercase();
  373. let size = (amount / ct_val).floor();
  374. let order_type = if price == Decimal::ZERO {
  375. "Market"
  376. } else {
  377. "Limit"
  378. };
  379. let mut params = json!({
  380. "orderLinkId": format!("t-{}", custom_id),
  381. "symbol": symbol_upper,
  382. "price": price.to_string(),
  383. "category": "linear",
  384. "orderType": order_type,
  385. "qty": json!(size),
  386. // 0.單向持倉 1.買側雙向持倉 2.賣側雙向持倉
  387. "positionIdx": json!(1),
  388. "reduceOnly": json!(false)
  389. });
  390. if price.eq(&Decimal::ZERO) {
  391. params["timeInForce"] = json!("IOC".to_string());
  392. }
  393. match origin_side {
  394. "kd" => {
  395. params["side"] = json!("Buy");
  396. }
  397. "pd" => {
  398. params["side"] = json!("Sell");
  399. params["positionIdx"] = json!(1);
  400. // 减仓
  401. params["reduceOnly"] = json!(true);
  402. }
  403. "kk" => {
  404. params["side"] = json!("Sell");
  405. params["positionIdx"] = json!(2);
  406. }
  407. "pk" => {
  408. params["side"] = json!("Buy");
  409. params["positionIdx"] = json!(2);
  410. // 减仓
  411. params["reduceOnly"] = json!(true);
  412. }
  413. _ => { error!("下单参数错误"); }
  414. };
  415. let res_data = self.request.swap_order(params.clone()).await;
  416. if res_data.code == 200 {
  417. let result = format_new_order_item(res_data.data, price, size);
  418. Ok(result)
  419. } else {
  420. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  421. }
  422. }
  423. // 撤销订单
  424. async fn cancel_order(&mut self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
  425. let symbol = self.symbol_uppercase.clone();
  426. let id = format!("t-{}", custom_id);
  427. let res_data = self.request.cancel_order(symbol, String::from(order_id), id.clone()).await;
  428. if res_data.code == 200 {
  429. let result = format_cancel_order_item(res_data.data);
  430. Ok(result)
  431. } else {
  432. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  433. }
  434. }
  435. // 批量撤销订单
  436. async fn cancel_orders(&mut self) -> Result<Vec<Order>, Error> {
  437. let symbol = self.symbol_uppercase.clone();
  438. let res_data = self.request.cancel_orders(symbol).await;
  439. if res_data.code == 200 {
  440. let res_arr: Vec<Value> = from_value(res_data.data).unwrap();
  441. let result = res_arr.iter().map(|item| format_cancel_order_item(item.clone())).collect();
  442. Ok(result)
  443. } else {
  444. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  445. }
  446. }
  447. async fn cancel_orders_all(&mut self) -> Result<Vec<Order>, Error> {
  448. let symbol = self.symbol_uppercase.clone();
  449. let res_data = self.request.cancel_orders(symbol).await;
  450. if res_data.code == 200 {
  451. let res_arr: Vec<Value> = from_value(res_data.data["list"].clone()).unwrap();
  452. let result = res_arr.iter().map(|item| format_cancel_order_item(item.clone())).collect();
  453. Ok(result)
  454. } else {
  455. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  456. }
  457. }
  458. async fn take_stop_loss_order(&mut self, _stop_price: Decimal, _price: Decimal, _side: &str) -> Result<Value, Error> {
  459. Err(Error::new(ErrorKind::NotFound, "bybit_swap:该交易所方法未实现".to_string()))
  460. }
  461. async fn cancel_stop_loss_order(&mut self, _order_id: &str) -> Result<Value, Error> {
  462. Err(Error::new(ErrorKind::NotFound, "bybit_swap:该交易所方法未实现".to_string()))
  463. }
  464. // 设置持仓模式
  465. async fn set_dual_mode(&mut self, _coin: &str, is_dual_mode: bool) -> Result<String, Error> {
  466. let coin_format = self.symbol_uppercase.clone();
  467. let mut mod_num = 0;
  468. if is_dual_mode {
  469. mod_num = 3;
  470. }
  471. let res_data = self.request.set_position_mode(coin_format, mod_num).await;
  472. if res_data.code == 200 {
  473. Ok(res_data.data.to_string())
  474. } else {
  475. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  476. }
  477. }
  478. // 更新双持仓模式下杠杆
  479. async fn set_dual_leverage(&mut self, leverage: &str) -> Result<String, Error> {
  480. let symbol = self.symbol_uppercase.clone();
  481. let res_data = self.request.set_leverage(symbol, leverage.to_string()).await;
  482. if res_data.code == 200 {
  483. Ok(res_data.data.to_string())
  484. } else {
  485. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  486. }
  487. }
  488. async fn set_auto_deposit_status(&mut self, _status: bool) -> Result<String, Error> { Err(Error::new(ErrorKind::NotFound, "gate:该交易所方法未实现".to_string())) }
  489. // 交易账户互转
  490. async fn wallet_transfers(&mut self, _coin: &str, _from: &str, _to: &str, _amount: Decimal) -> Result<String, Error> {
  491. // let coin_format = coin.to_string().to_lowercase();
  492. // let res_data = self.request.wallet_transfers(coin_format.clone(), from.to_string(), to.to_string(), amount.to_string(), coin_format.clone()).await;
  493. // if res_data.code == 200 {
  494. // let res_data_str = &res_data.data;
  495. // let result = res_data_str.clone();
  496. // Ok(result)
  497. // } else {
  498. // Err(Error::new(ErrorKind::Other, res_data.to_string()))
  499. // }
  500. Err(Error::new(ErrorKind::Other, "暂未实现!"))
  501. }
  502. }
  503. pub fn format_position_item(position: &Value, ct_val: Decimal) -> Position {
  504. let position_idx = position["positionIdx"].to_string();
  505. let mut position_mode = match position_idx.as_str() {
  506. "0" => PositionModeEnum::Both,
  507. "1" => PositionModeEnum::Long,
  508. "2" => PositionModeEnum::Short,
  509. _ => {
  510. error!("bybit_swap:格式化持仓模式错误!\nformat_position_item:position={:?}", position);
  511. panic!("bybit_swap:格式化持仓模式错误!\nformat_position_item:position={:?}", position)
  512. }
  513. };
  514. let size_str: String = from_value(position["size"].clone()).unwrap();
  515. let size = Decimal::from_str(size_str.as_str()).unwrap();
  516. let amount = size * ct_val;
  517. let mut profit = Decimal::ZERO;
  518. let profit_str = position["unrealisedPnl"].as_str().unwrap_or("0");
  519. if profit_str != "" {
  520. profit = Decimal::from_str(profit_str).unwrap();
  521. }
  522. match position_mode {
  523. PositionModeEnum::Both => {
  524. position_mode = match amount {
  525. amount if amount > Decimal::ZERO => PositionModeEnum::Long,
  526. amount if amount < Decimal::ZERO => PositionModeEnum::Short,
  527. _ => { PositionModeEnum::Both }
  528. }
  529. }
  530. _ => {}
  531. }
  532. Position {
  533. symbol: position["symbol"].as_str().unwrap_or("").parse().unwrap(),
  534. margin_level: Decimal::from_str(position["leverage"].as_str().unwrap()).unwrap(),
  535. amount,
  536. frozen_amount: Decimal::ZERO,
  537. price: Decimal::from_str(position["avgPrice"].as_str().unwrap()).unwrap(),
  538. profit,
  539. position_mode,
  540. margin: Decimal::from_str(position["positionBalance"].as_str().unwrap()).unwrap(),
  541. }
  542. }
  543. fn format_cancel_order_item(order: Value) -> Order {
  544. Order {
  545. id: format!("{}", order["orderId"].as_str().unwrap()),
  546. custom_id: order["orderLinkId"].as_str().unwrap().replace("t-my-custom-id_", "").replace("t-", ""),
  547. price: Decimal::ZERO,
  548. amount: Decimal::ZERO,
  549. deal_amount: Decimal::ZERO,
  550. avg_price: Decimal::ZERO,
  551. status: "REMOVE".to_string(),
  552. order_type: "limit".to_string()
  553. }
  554. }
  555. fn format_new_order_item(order: Value, price: Decimal, amount: Decimal) -> Order {
  556. Order {
  557. id: format!("{}", order["orderId"].as_str().unwrap()),
  558. custom_id: order["orderLinkId"].as_str().unwrap().replace("t-my-custom-id_", "").replace("t-", ""),
  559. price,
  560. amount,
  561. deal_amount: Decimal::ZERO,
  562. avg_price: price,
  563. status: "NEW".to_string(),
  564. order_type: "limit".to_string()
  565. }
  566. }
  567. pub fn format_order_item(order: Value, ct_val: Decimal) -> Order {
  568. let status = order["orderStatus"].as_str().unwrap_or("");
  569. let text = order["orderLinkId"].as_str().unwrap_or("");
  570. let mut size = Decimal::ZERO;
  571. let mut deal_amount = Decimal::ZERO;
  572. let mut avg_price = Decimal::ZERO;
  573. let right_str = order["cumExecQty"].to_string();
  574. let size_str = order["qty"].to_string();
  575. if !order.get("qty").is_some() {
  576. size = Decimal::from_str(size_str.as_str()).unwrap();
  577. let right_val = Decimal::from_str(order["cumExecValue"].as_str().unwrap()).unwrap();
  578. let right = Decimal::from_str(right_str.as_str()).unwrap();
  579. if right != Decimal::ZERO {
  580. avg_price = right_val / right;
  581. }
  582. deal_amount = right * ct_val;
  583. }
  584. let amount = size * ct_val;
  585. let custom_status = if status == "Filled" || status == "Cancelled" { "REMOVE".to_string() } else if status == "New" { "NEW".to_string() } else {
  586. "NULL".to_string()
  587. };
  588. let rst_order = Order {
  589. id: format!("{}", order["orderId"].as_str().unwrap()),
  590. custom_id: text.replace("t-my-custom-id_", "").replace("t-", ""),
  591. price: Decimal::from_str(order["price"].as_str().unwrap()).unwrap(),
  592. amount,
  593. deal_amount,
  594. avg_price,
  595. status: custom_status,
  596. order_type: "limit".to_string()
  597. };
  598. return rst_order;
  599. }