phemex_swap.rs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  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 futures::stream::FuturesUnordered;
  7. use futures::TryStreamExt;
  8. use rust_decimal::Decimal;
  9. use rust_decimal_macros::dec;
  10. use serde_json::{json, Value};
  11. use tokio::spawn;
  12. use tokio::time::Instant;
  13. use tracing::{error, info, trace, warn};
  14. use exchanges::phemex_swap_rest::PhemexSwapRest;
  15. use exchanges::response_base::ResponseData;
  16. use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, OrderCommand, PositionModeEnum, utils};
  17. use global::trace_stack::TraceStack;
  18. #[allow(dead_code)]
  19. #[derive(Clone)]
  20. pub struct PhemexSwap {
  21. exchange: ExchangeEnum,
  22. symbol: String,
  23. is_colo: bool,
  24. params: BTreeMap<String, String>,
  25. request: PhemexSwapRest,
  26. market: Market,
  27. order_sender: Sender<Order>,
  28. error_sender: Sender<Error>,
  29. }
  30. impl PhemexSwap {
  31. pub async fn new(symbol: String, is_colo: bool, params: BTreeMap<String, String>, order_sender: Sender<Order>, error_sender: Sender<Error>) -> PhemexSwap {
  32. let market = Market::new();
  33. let mut phemex_swap = PhemexSwap {
  34. exchange: ExchangeEnum::PhemexSwap,
  35. symbol: symbol.to_uppercase(),
  36. is_colo,
  37. params: params.clone(),
  38. request: PhemexSwapRest::new(is_colo, params.clone()),
  39. market,
  40. order_sender,
  41. error_sender,
  42. };
  43. // 修改持仓模式
  44. let mode_result = phemex_swap.set_dual_mode("", false).await;
  45. match mode_result {
  46. Ok(_) => {
  47. trace!("Phemex:设置持仓模式成功!")
  48. }
  49. Err(error) => {
  50. error!("Phemex:设置持仓模式失败!mode_result={}", error)
  51. }
  52. }
  53. // 获取市场信息
  54. phemex_swap.market = PhemexSwap::get_market(&mut phemex_swap).await.unwrap_or(phemex_swap.market);
  55. // phemex_swap.market = Market::new();
  56. // 设置持仓杠杆
  57. let lever_rate_result = phemex_swap.set_dual_leverage("10").await;
  58. match lever_rate_result {
  59. Ok(ok) => {
  60. info!("Phemex:设置持仓杠杆成功!{:?}", ok);
  61. }
  62. Err(error) => {
  63. error!("Phemex:设置持仓杠杆失败!{:?}", error)
  64. }
  65. }
  66. return phemex_swap;
  67. }
  68. }
  69. #[async_trait]
  70. impl Platform for PhemexSwap {
  71. // 克隆方法
  72. fn clone_box(&self) -> Box<dyn Platform + Send + Sync> { Box::new(self.clone()) }
  73. // 获取交易所模式
  74. fn get_self_exchange(&self) -> ExchangeEnum {
  75. ExchangeEnum::PhemexSwap
  76. }
  77. // 获取交易对
  78. fn get_self_symbol(&self) -> String { self.symbol.clone() }
  79. // 获取是否使用高速通道
  80. fn get_self_is_colo(&self) -> bool {
  81. self.is_colo
  82. }
  83. // 获取params信息
  84. fn get_self_params(&self) -> BTreeMap<String, String> {
  85. self.params.clone()
  86. }
  87. // 获取market信息
  88. fn get_self_market(&self) -> Market { self.market.clone() }
  89. // 获取请求时间
  90. fn get_request_delays(&self) -> Vec<i64> { self.request.get_delays() }
  91. // 获取请求平均时间
  92. fn get_request_avg_delay(&self) -> Decimal { self.request.get_avg_delay() }
  93. // 获取请求最大时间
  94. fn get_request_max_delay(&self) -> i64 { self.request.get_max_delay() }
  95. // 获取服务器时间
  96. async fn get_server_time(&mut self) -> Result<String, Error> {
  97. let res_data = self.request.get_server().await;
  98. if res_data.code == 200 {
  99. let res_data_json: Value = res_data.data;
  100. let result = res_data_json["serverTime"].to_string();
  101. Ok(result)
  102. } else {
  103. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  104. }
  105. }
  106. // 获取账号信息
  107. async fn get_account(&mut self) -> Result<Account, Error> {
  108. let params = json!({"currency": "USDT"});
  109. let response = self.request.get_account_and_positions(params).await;
  110. if response.code != 200 {
  111. return Err(Error::new(ErrorKind::NotFound, format!("phemex_swap 获取仓位异常{:?}", response).to_string()));
  112. }
  113. let account_info = response.data["account"].clone();
  114. let coin = account_info["currency"].as_str().unwrap().to_string();
  115. let available_balance = Decimal::from_str(account_info["accountBalanceRv"].as_str().unwrap()).unwrap();
  116. let frozen_balance = Decimal::from_str(account_info["totalUsedBalanceRv"].as_str().unwrap()).unwrap();
  117. let balance = available_balance + frozen_balance;
  118. let result = Account {
  119. coin,
  120. balance,
  121. available_balance,
  122. frozen_balance,
  123. stocks: Decimal::ZERO,
  124. available_stocks: Decimal::ZERO,
  125. frozen_stocks: Decimal::ZERO,
  126. };
  127. Ok(result)
  128. }
  129. async fn get_spot_account(&mut self) -> Result<Vec<Account>, Error> {
  130. Err(Error::new(ErrorKind::NotFound, "phemex_swap:该方法暂未实现".to_string()))
  131. }
  132. // 获取持仓信息
  133. async fn get_position(&mut self) -> Result<Vec<Position>, Error> {
  134. let symbol_format = utils::format_symbol(self.symbol.clone(), "").replace("1000", "u1000");
  135. let ct_val = self.market.ct_val;
  136. let params = json!({
  137. "symbol":symbol_format,
  138. "currency": "USDT"
  139. });
  140. let response = self.request.get_account_and_positions(params).await;
  141. if response.code != 200 {
  142. return Err(Error::new(ErrorKind::NotFound, format!("phemex_swap 获取仓位异常{:?}", response).to_string()));
  143. }
  144. let res_data_json = response.data["positions"].clone();
  145. let positions_info = res_data_json.as_array().unwrap();
  146. let result = positions_info.iter().map(|item| { format_position_item(item, ct_val) }).collect();
  147. Ok(result)
  148. }
  149. // 获取所有持仓
  150. async fn get_positions(&mut self) -> Result<Vec<Position>, Error> {
  151. let params = json!({
  152. "currency": "USDT"
  153. });
  154. let response = self.request.get_account_and_positions(params).await;
  155. if response.code != 200 {
  156. return Err(Error::new(ErrorKind::NotFound, format!("phemex_swap 获取仓位异常{:?}", response).to_string()));
  157. }
  158. let res_data_json = response.data["positions"].clone();
  159. let positions_info = res_data_json.as_array().unwrap();
  160. let result = positions_info.iter().map(|item| { format_position_item(item, Decimal::ONE) }).collect();
  161. Ok(result)
  162. }
  163. // 获取市场行情
  164. async fn get_ticker(&mut self) -> Result<Ticker, Error> {
  165. self.get_ticker_symbol(self.symbol.clone()).await
  166. }
  167. async fn get_ticker_symbol(&mut self, symbol: String) -> Result<Ticker, Error> {
  168. let symbol_format = utils::format_symbol(symbol.clone(), "").replace("1000", "u1000");
  169. let params = json!({
  170. "symbol":symbol_format
  171. });
  172. let response = self.request.get_ticker(params).await;
  173. if response.code != 200 {
  174. return Err(Error::new(ErrorKind::NotFound, format!("phemex_swap 获取市场行情异常{:?}", response).to_string()));
  175. }
  176. let ticker_info = response.data;
  177. let result = Ticker {
  178. time: ticker_info["timestamp"].as_i64().unwrap() / 1_000_000,
  179. high: Decimal::from_str(ticker_info["highRp"].as_str().unwrap()).unwrap(),
  180. low: Decimal::from_str(ticker_info["lowRp"].as_str().unwrap()).unwrap(),
  181. sell: Decimal::from_str(ticker_info["askRp"].as_str().unwrap()).unwrap(),
  182. buy: Decimal::from_str(ticker_info["bidRp"].as_str().unwrap()).unwrap(),
  183. last: Decimal::from_str(ticker_info["lastRp"].as_str().unwrap()).unwrap(),
  184. volume: Decimal::from_str(ticker_info["volumeRq"].as_str().unwrap()).unwrap(),
  185. };
  186. Ok(result)
  187. }
  188. async fn get_market(&mut self) -> Result<Market, Error> {
  189. self.get_market_symbol(self.symbol.clone()).await
  190. }
  191. async fn get_market_symbol(&mut self, symbol: String) -> Result<Market, Error> {
  192. let symbol_format = utils::format_symbol(symbol.clone(), "").replace("1000", "u1000");
  193. let params = json!({});
  194. let response = self.request.get_market(params).await;
  195. // let response = get_market_info(params);
  196. if response.code != 200 {
  197. return Err(Error::new(ErrorKind::NotFound, format!("phemex_swap 获取市场行情异常{:?}", response).to_string()));
  198. }
  199. let res_data_json = response.data["perpProductsV2"].as_array().unwrap();
  200. let market_info = res_data_json.iter().find(|item| {
  201. item["symbol"].as_str().unwrap() == symbol_format
  202. });
  203. match market_info {
  204. None => {
  205. error!("phemex_swap:获取Market信息错误!\nget_market:res_data={:?}", response);
  206. Err(Error::new(ErrorKind::Other, response.to_string()))
  207. }
  208. Some(value) => {
  209. let symbol = value["symbol"].as_str().unwrap().to_string();
  210. let base_asset = value["baseCurrency"].as_str().unwrap().to_string().split_whitespace().collect();
  211. let quote_asset = value["quoteCurrency"].as_str().unwrap().to_string();
  212. let price_precision = Decimal::from_str(&value["pricePrecision"].to_string()).unwrap();
  213. let tick_size = Decimal::from_str(value["tickSize"].as_str().unwrap()).unwrap();
  214. let amount_precision = Decimal::from_str(&value["qtyPrecision"].to_string()).unwrap();
  215. let amount_size = Decimal::from_str(&value["qtyStepSize"].as_str().unwrap()).unwrap();
  216. let min_notional = Decimal::from_str(value["minPriceRp"].as_str().unwrap()).unwrap();
  217. let max_qty = Decimal::from_str(value["maxOrderQtyRq"].as_str().unwrap()).unwrap();
  218. let min_qty = Decimal::from_str(value["minOrderValueRv"].as_str().unwrap()).unwrap() / min_notional;
  219. let max_notional = Decimal::from_str(value["maxPriceRp"].as_str().unwrap()).unwrap() * max_qty;
  220. let ct_val = Decimal::ONE;
  221. let result = Market {
  222. symbol,
  223. base_asset,
  224. quote_asset,
  225. tick_size,
  226. amount_size,
  227. price_precision,
  228. amount_precision,
  229. min_qty,
  230. max_qty,
  231. min_notional,
  232. max_notional,
  233. ct_val,
  234. };
  235. Ok(result)
  236. }
  237. }
  238. }
  239. // 获取订单详情
  240. async fn get_order_detail(&mut self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
  241. let symbol_format = utils::format_symbol(self.symbol.clone(), "").replace("1000", "u1000");
  242. let ct_val = self.market.ct_val;
  243. let mut params = json!({
  244. "symbol":symbol_format,
  245. });
  246. if order_id.eq("") { params["clOrdID"] = json!(custom_id.to_string()) } else { params["orderID"] = json!(order_id.to_string()) };
  247. if order_id == "" && custom_id == "" { return Err(Error::new(ErrorKind::Other, format!("订单id和客户端id都为空,查询失败!order_id :{}, custom_id: {}", order_id, custom_id))); }
  248. let response = self.request.get_orders_by_id(params).await;
  249. if response.code != 200 {
  250. return Err(Error::new(ErrorKind::NotFound, format!("phemex_swap 获取订单详情异常{:?}", response).to_string()));
  251. }
  252. let res_data_json = response.data["rows"].as_array().unwrap();
  253. let order_info = res_data_json.iter().find(|item| item["orderId"].as_str().unwrap() == order_id || item["clOrdId"] == custom_id);
  254. match order_info {
  255. None => {
  256. error!("phemex_swap:获取order信息错误!\nget_order_detail:res_data={:?},order_id={},custom_id:{}", response, order_id, custom_id);
  257. Err(Error::new(ErrorKind::Other, response.to_string()))
  258. }
  259. Some(order) => {
  260. let result = format_order_item(order.clone(), ct_val);
  261. return Ok(result);
  262. }
  263. }
  264. }
  265. // 获取未完成订单列表
  266. async fn get_orders_list(&mut self, _status: &str) -> Result<Vec<Order>, Error> {
  267. let symbol_format = utils::format_symbol(self.symbol.clone(), "").replace("1000", "u1000");
  268. let ct_val = self.market.ct_val;
  269. let params = json!({
  270. "symbol": symbol_format
  271. });
  272. let response = self.request.get_orders(params).await;
  273. if response.code != 200 {
  274. return Err(Error::new(ErrorKind::NotFound, format!("phemex_swap 获取订单列表异常{:?}", response).to_string()));
  275. }
  276. let result = response.data["rows"].as_array().unwrap().iter().map(|item| format_order_item(item.clone(), ct_val)).collect();
  277. return Ok(result);
  278. }
  279. // 下单接口
  280. async fn take_order(&mut self, custom_id: &str, origin_side: &str, price: Decimal, amount: Decimal) -> Result<Order, Error> {
  281. self.take_order_symbol(self.symbol.clone(), self.market.ct_val, custom_id, origin_side, price, amount).await
  282. }
  283. 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> {
  284. let symbol_format = utils::format_symbol(symbol.clone(), "").replace("1000", "u1000");
  285. let mut params = json!({
  286. "clOrdID": custom_id,
  287. "symbol":symbol_format,
  288. "priceRp": price,
  289. "orderQtyRq": amount * ct_val
  290. });
  291. if price == dec!(0) { params["ordType"] = json!("Market") };
  292. match origin_side {
  293. "kd" => {
  294. params["reduce_only"] = json!(false);
  295. params["posSide"] = json!("Long");
  296. params["side"] = json!("Buy");
  297. }
  298. "pd" => {
  299. params["reduce_only"] = json!(true);
  300. params["posSide"] = json!("Long");
  301. params["side"] = json!("Sell");
  302. }
  303. "kk" => {
  304. params["reduce_only"] = json!(false);
  305. params["posSide"] = json!("Short");
  306. params["side"] = json!("Sell");
  307. }
  308. "pk" => {
  309. params["reduce_only"] = json!(true);
  310. params["posSide"] = json!("Short");
  311. params["side"] = json!("Buy");
  312. }
  313. _ => {
  314. error!("下单参数错误");
  315. params["posSide"] = json!("error");
  316. params["side"] = json!("error");
  317. }
  318. };
  319. let res_data = self.request.orders(params).await;
  320. println!("{:?}", res_data);
  321. if res_data.code == 200 {
  322. let res_data_json: Value = res_data.data;
  323. let result = format_order_item(res_data_json, ct_val);
  324. Ok(result)
  325. } else {
  326. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  327. }
  328. }
  329. // 撤销订单
  330. async fn cancel_order(&mut self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
  331. let symbol = utils::format_symbol(self.symbol.clone(), "").replace("1000", "u1000");
  332. let ct_val = self.market.ct_val;
  333. let mut params = json!({
  334. "orderID": order_id,
  335. "clOrdID": custom_id,
  336. "symbol": symbol,
  337. });
  338. params["posSide"] = json!("Short");
  339. let response_long = self.request.cancel_order(params.clone()).await;
  340. params["posSide"] = json!("Long");
  341. let response_short = self.request.cancel_order(params.clone()).await;
  342. if response_long.code != 200 && response_short.code != 200 {
  343. return Err(Error::new(ErrorKind::NotFound, format!("phemex_swap 撤销订单失败 order_id: {}, custom_id: {}, response_long: {:?}, response_short: {:?}", order_id, custom_id, response_long, response_short)));
  344. };
  345. let res_data_json: Value = if response_long.code == 200 { response_long.data } else { response_short.data };
  346. let mut result = format_order_item(res_data_json, ct_val);
  347. result.status = "REMOVE".to_string();
  348. Ok(result)
  349. }
  350. // 批量撤销订单
  351. async fn cancel_orders(&mut self) -> Result<Vec<Order>, Error> {
  352. let symbol = utils::format_symbol(self.symbol.clone(), "").replace("1000", "u1000");
  353. let params = json!({
  354. "symbol":symbol
  355. });
  356. let response = self.request.cancel_order_all(params).await;
  357. if response.code != 200 {
  358. return Err(Error::new(ErrorKind::NotFound, format!("phemex_swap 批量撤销订单失败 res_data: {:?}", response)));
  359. };
  360. return Ok(vec![]);
  361. }
  362. async fn cancel_orders_all(&mut self) -> Result<Vec<Order>, Error> {
  363. let params = json!({});
  364. let response = self.request.cancel_order_all(params).await;
  365. if response.code != 200 {
  366. return Err(Error::new(ErrorKind::NotFound, format!("phemex_swap 批量撤销订单失败 res_data: {:?}", response)));
  367. };
  368. // info!("{}", response.data.to_string());
  369. return Ok(vec![]);
  370. }
  371. async fn take_stop_loss_order(&mut self, _stop_price: Decimal, _price: Decimal, _side: &str) -> Result<Value, Error> {
  372. Err(Error::new(ErrorKind::NotFound, "coin_ex:该交易所暂未实现自动订单下单".to_string()))
  373. }
  374. async fn cancel_stop_loss_order(&mut self, _order_id: &str) -> Result<Value, Error> {
  375. Err(Error::new(ErrorKind::NotFound, "coin_ex:该交易所暂未实现取消自动订单".to_string()))
  376. }
  377. // 设置持仓模式
  378. async fn set_dual_mode(&mut self, _coin: &str, _is_dual_mode: bool) -> Result<String, Error> {
  379. let symbol = utils::format_symbol(self.symbol.clone(), "").replace("1000", "u1000");
  380. let params = json!({
  381. "symbol": symbol,
  382. "targetPosMode": "Hedged"
  383. });
  384. let response = self.request.set_target_pos_mode(params).await;
  385. if response.code != 200 {
  386. return Err(Error::new(ErrorKind::NotFound, format!("phemex_swap 设置持仓模式{:?}", response).to_string()));
  387. }
  388. let result = &response.data;
  389. Ok(result.as_str().unwrap().to_string())
  390. }
  391. // 更新杠杆
  392. async fn set_dual_leverage(&mut self, leverage: &str) -> Result<String, Error> {
  393. let symbol = utils::format_symbol(self.symbol.clone(), "").replace("1000", "u1000");
  394. let params = json!({
  395. "symbol": symbol,
  396. "longLeverageRr": leverage,
  397. "shortLeverageRr": leverage,
  398. });
  399. let response = self.request.set_leverage(params).await;
  400. if response.code != 200 {
  401. return Err(Error::new(ErrorKind::NotFound, format!("phemex_swap 设置杠杆异常{:?}", response).to_string()));
  402. }
  403. let result = &response.data;
  404. Ok(result.as_str().unwrap().to_string())
  405. }
  406. async fn set_auto_deposit_status(&mut self, _status: bool) -> Result<String, Error> { Err(Error::new(ErrorKind::NotFound, "Phemex:该交易所方法未实现".to_string())) }
  407. async fn wallet_transfers(&mut self, _coin: &str, _from: &str, _to: &str, _amount: Decimal) -> Result<String, Error> {
  408. Err(Error::new(ErrorKind::NotFound, "Phemex wallet_transfers:该交易所方法未实现".to_string()))
  409. }
  410. // 指令下单
  411. async fn command_order(&mut self, order_command: &mut OrderCommand, trace_stack: &TraceStack) {
  412. let mut handles = vec![];
  413. // 下单指令
  414. for item in order_command.limits_open.keys() {
  415. let mut ts = trace_stack.clone();
  416. let amount = Decimal::from_str(&*order_command.limits_open[item].get(0).unwrap().clone()).unwrap();
  417. let side = order_command.limits_open[item].get(1).unwrap().clone();
  418. let price = Decimal::from_str(&*order_command.limits_open[item].get(2).unwrap().clone()).unwrap();
  419. let cid = order_command.limits_open[item].get(3).unwrap().clone();
  420. // order_name: [数量,方向,价格,c_id]
  421. let mut self_clone = self.clone();
  422. let handle = spawn(async move {
  423. // info!("数量 {},方向 {},价格 {},c_id {}", amount, side, price, cid);
  424. ts.on_before_send();
  425. let result = self_clone.take_order(&cid, &side, price, amount).await;
  426. ts.on_after_send();
  427. match result {
  428. Ok(mut result) => {
  429. result.trace_stack = ts;
  430. // info!("数量 {},方向 {},价格 {},c_id {}", amount, side, price, cid);
  431. self_clone.order_sender.send(result).await.unwrap();
  432. }
  433. Err(error) => {
  434. let mut err_order = Order::new();
  435. err_order.custom_id = cid.clone();
  436. err_order.status = "REMOVE".to_string();
  437. // info!("err 数量 {},方向 {},价格 {},c_id {}", amount, side, price, cid);
  438. self_clone.order_sender.send(err_order).await.unwrap();
  439. self_clone.error_sender.send(error).await.unwrap();
  440. // 触发限频
  441. // if error_info.to_string().contains("213:Please don't try too frequently") {
  442. // Err(Error::new(ErrorKind::Other, "触发限频, 请调整下单频率"))
  443. // }
  444. }
  445. }
  446. });
  447. handles.push(handle)
  448. }
  449. let futures = FuturesUnordered::from_iter(handles);
  450. // 等待所有任务完成
  451. let _: Result<Vec<_>, _> = futures.try_collect().await;
  452. // 撤销订单
  453. let mut cancel_handlers = vec![];
  454. for item in order_command.cancel.keys() {
  455. let order_id = order_command.cancel[item].get(1).unwrap().clone();
  456. let custom_id = order_command.cancel[item].get(0).unwrap().clone();
  457. let mut self_clone = self.clone();
  458. let handle = spawn(async move {
  459. let result = self_clone.cancel_order(&order_id, &custom_id).await;
  460. match result {
  461. Ok(_) => {
  462. // self_clone.order_sender.send(order).await.unwrap();
  463. }
  464. Err(error) => {
  465. // info!("撤单失败:{:?}", error.to_string());
  466. // 取消失败去查订单。
  467. let query_rst = self_clone.get_order_detail(&order_id, &custom_id).await;
  468. match query_rst {
  469. Ok(order) => {
  470. // info!("查单 订单详情:{:?}", order);
  471. self_clone.order_sender.send(order).await.unwrap();
  472. }
  473. Err(err) => {
  474. // 未成交已取消的订单会报不存在
  475. if err.to_string().contains("3103:order not exists") {
  476. let mut order = Order::new();
  477. order.id = order_id.to_string();
  478. order.custom_id = custom_id.to_string();
  479. order.status = "REMOVE".to_string();
  480. self_clone.order_sender.send(order).await.unwrap();
  481. } else {
  482. warn!("撤单失败,而且查单也失败了,Phemex_io_swap,oid={}, cid={} err={:?}", order_id.clone(), custom_id.clone(), err);
  483. }
  484. // panic!("撤单失败,而且查单也失败了,Phemex_io_swap,oid={}, cid={}。", order_id.clone(), custom_id.clone());
  485. }
  486. }
  487. self_clone.error_sender.send(error).await.unwrap();
  488. }
  489. }
  490. });
  491. cancel_handlers.push(handle)
  492. }
  493. let futures = FuturesUnordered::from_iter(cancel_handlers);
  494. // 等待所有任务完成
  495. let _: Result<Vec<_>, _> = futures.try_collect().await;
  496. // 检查订单指令
  497. let mut check_handlers = vec![];
  498. for item in order_command.check.keys() {
  499. let order_id = order_command.check[item].get(1).unwrap().clone();
  500. let custom_id = order_command.check[item].get(0).unwrap().clone();
  501. let mut self_clone = self.clone();
  502. let handle = spawn(async move {
  503. let result = self_clone.get_order_detail(&order_id, &custom_id).await;
  504. match result {
  505. Ok(result) => {
  506. self_clone.order_sender.send(result).await.unwrap();
  507. }
  508. Err(error) => {
  509. self_clone.error_sender.send(error).await.unwrap();
  510. }
  511. }
  512. });
  513. check_handlers.push(handle)
  514. }
  515. let futures = FuturesUnordered::from_iter(check_handlers);
  516. // 等待所有任务完成
  517. let _: Result<Vec<_>, _> = futures.try_collect().await;
  518. }
  519. }
  520. pub fn format_position_item(position: &Value, ct_val: Decimal) -> Position {
  521. let position_mode = match position["posSide"].as_str().unwrap_or("") {
  522. "Long" => PositionModeEnum::Long,
  523. "Short" => PositionModeEnum::Short,
  524. _ => {
  525. error!("phemex_swap:格式化持仓模式错误!\nformat_position_item:position={:?}", position);
  526. panic!("phemex_swap:格式化持仓模式错误!\nformat_position_item:position={:?}", position)
  527. }
  528. };
  529. let size = Decimal::from_str(&position["size"].as_str().unwrap()).unwrap();
  530. let amount = size * ct_val;
  531. Position {
  532. symbol: position["symbol"].as_str().unwrap().to_string(),
  533. margin_level: Decimal::from_str(position["leverageRr"].as_str().unwrap()).unwrap(),
  534. amount,
  535. frozen_amount: Decimal::ZERO,
  536. price: Decimal::from_str(position["avgEntryPrice"].as_str().unwrap()).unwrap(),
  537. profit: Decimal::from_str(position["curTermRealisedPnlRv"].as_str().unwrap()).unwrap(),
  538. position_mode,
  539. margin: Decimal::from_str(position["positionMarginRv"].as_str().unwrap()).unwrap(),
  540. }
  541. }
  542. pub fn format_order_item(order: Value, ct_val: Decimal) -> Order {
  543. // info!("需要格式化的订单数据: {}", order);
  544. let id = match order["orderId"].as_str() {
  545. Some(val) => {
  546. val.to_string()
  547. },
  548. None => {
  549. order["orderID"].as_str().unwrap().to_string()
  550. }
  551. };
  552. let custom_id = match order["clOrdId"].as_str() {
  553. Some(val) => {
  554. val.to_string()
  555. },
  556. None => {
  557. order["clOrdID"].as_str().unwrap().to_string()
  558. }
  559. };
  560. let price = Decimal::from_str(order["priceRp"].as_str().unwrap()).unwrap();
  561. let amount = Decimal::from_str(order["orderQtyRq"].as_str().unwrap()).unwrap() * ct_val;
  562. let deal_amount = Decimal::from_str(order["cumQtyRq"].as_str().unwrap()).unwrap() * ct_val;
  563. let avg_price = Decimal::from_str(order["cumValueRv"].as_str().unwrap()).unwrap();
  564. let status = order["ordStatus"].as_str().unwrap();
  565. let custom_status;
  566. if vec!["Rejected"].contains(&status) {
  567. custom_status = "NULL".to_string()
  568. } else if vec!["Filled", "Canceled"].contains(&status) {
  569. custom_status = "REMOVE".to_string()
  570. } else if vec!["New", "Init", "Created"].contains(&status) {
  571. custom_status = "NEW".to_string()
  572. } else {
  573. error!("gate_swap:格式化订单状态错误!\nformat_order_item:order={:?}", order);
  574. panic!("gate_swap:格式化订单状态错误!\nformat_order_item:order={:?}", order)
  575. };
  576. let result = Order {
  577. id,
  578. custom_id,
  579. price,
  580. amount,
  581. deal_amount,
  582. avg_price,
  583. status: custom_status,
  584. order_type: "limit".to_string(),
  585. trace_stack: TraceStack::new(0, Instant::now()).on_special("669 trace_stack".to_string()),
  586. };
  587. return result;
  588. }
  589. fn get_market_info(_params: Value) -> ResponseData {
  590. let aa = json!({"perpProductsV2": [{
  591. "symbol": "u1000PEPEUSDT",
  592. "code": 66041,
  593. "type": "PerpetualV2",
  594. "displaySymbol": "1000PEPE / USDT",
  595. "indexSymbol": ".u1000PEPEUSDT",
  596. "markSymbol": ".Mu1000PEPEUSDT",
  597. "fundingRateSymbol": ".u1000PEPEUSDTFR",
  598. "fundingRate8hSymbol": ".u1000PEPEUSDTFR8H",
  599. "contractUnderlyingAssets": "1000 PEPE",
  600. "settleCurrency": "USDT",
  601. "quoteCurrency": "USDT",
  602. "tickSize": "0.0000001",
  603. "priceScale": 0,
  604. "ratioScale": 0,
  605. "pricePrecision": 7,
  606. "baseCurrency": "1000 PEPE",
  607. "description": "1000 PEPE/USDT perpetual contracts are priced on the .u1000PEPEUSDT Index. Each contract is worth 1 1000PEPE. Funding fees are paid and received every 8 hours at UTC time: 00:00, 08:00 and 16:00.",
  608. "status": "Listed",
  609. "tipOrderQty": 0,
  610. "listTime": "1683367200000",
  611. "majorSymbol": false,
  612. "defaultLeverage": "-10",
  613. "fundingInterval": 28800,
  614. "maxLeverage": 50,
  615. "leverageMargin": 1015,
  616. "maxOrderQtyRq": "400000000",
  617. "maxPriceRp": "2000",
  618. "minOrderValueRv": "1",
  619. "minPriceRp": "0.001",
  620. "qtyPrecision": 0,
  621. "qtyStepSize": "1.0",
  622. "tipOrderQtyRq": "80000000",
  623. "maxOpenPosLeverage": 50.0
  624. }, {
  625. "symbol": "EDUUSDT",
  626. "code": 66241,
  627. "type": "PerpetualV2",
  628. "displaySymbol": "EDU / USDT",
  629. "indexSymbol": ".EDUUSDT",
  630. "markSymbol": ".MEDUUSDT",
  631. "fundingRateSymbol": ".EDUUSDTFR",
  632. "fundingRate8hSymbol": ".EDUUSDTFR8H",
  633. "contractUnderlyingAssets": "EDU",
  634. "settleCurrency": "USDT",
  635. "quoteCurrency": "USDT",
  636. "tickSize": "0.0001",
  637. "priceScale": 0,
  638. "ratioScale": 0,
  639. "pricePrecision": 4,
  640. "baseCurrency": "EDU",
  641. "description": "EDU/USDT perpetual contracts are priced on the .EDUUSDT Index. Each contract is worth 1 EDU. Funding fees are paid and received every 8 hours at UTC time: 00:00, 08:00 and 16:00.",
  642. "status": "Listed",
  643. "tipOrderQty": 0,
  644. "listTime": "1683367200000",
  645. "majorSymbol": false,
  646. "defaultLeverage": "-10",
  647. "fundingInterval": 28800,
  648. "maxLeverage": 50,
  649. "leverageMargin": 1015,
  650. "maxOrderQtyRq": "800000",
  651. "maxPriceRp": "2000000",
  652. "minOrderValueRv": "1",
  653. "minPriceRp": "1.0",
  654. "qtyPrecision": 0,
  655. "qtyStepSize": "1.0",
  656. "tipOrderQtyRq": "160000",
  657. "maxOpenPosLeverage": 50.0
  658. }]});
  659. ResponseData::new("".to_string(), 200, "".to_string(), aa)
  660. }