binance_swap.rs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. use std::collections::BTreeMap;
  2. use std::io::{Error, ErrorKind};
  3. use std::result::Result;
  4. use std::str::FromStr;
  5. use async_trait::async_trait;
  6. use rust_decimal::Decimal;
  7. use rust_decimal::prelude::FromPrimitive;
  8. use rust_decimal_macros::dec;
  9. use serde_json::Value;
  10. use tokio::sync::mpsc::Sender;
  11. use tracing::{error};
  12. use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, utils, PositionModeEnum};
  13. use exchanges::binance_swap_rest::BinanceSwapRest;
  14. #[allow(dead_code)]
  15. #[derive(Clone)]
  16. pub struct BinanceSwap {
  17. exchange: ExchangeEnum,
  18. symbol: String,
  19. is_colo: bool,
  20. params: BTreeMap<String, String>,
  21. request: BinanceSwapRest,
  22. market: Market,
  23. order_sender: Sender<Order>,
  24. error_sender: Sender<Error>,
  25. }
  26. impl BinanceSwap {
  27. pub async fn new(symbol: String, is_colo: bool, params: BTreeMap<String, String>, order_sender: Sender<Order>, error_sender: Sender<Error>) -> BinanceSwap {
  28. let market = Market::new();
  29. let mut binance_swap = BinanceSwap {
  30. exchange: ExchangeEnum::BinanceSwap,
  31. symbol: symbol.to_uppercase(),
  32. is_colo,
  33. params: params.clone(),
  34. request: BinanceSwapRest::new(is_colo, params.clone()),
  35. market,
  36. order_sender,
  37. error_sender,
  38. };
  39. binance_swap.market = BinanceSwap::get_market(&mut binance_swap).await.unwrap_or(binance_swap.market);
  40. return binance_swap;
  41. }
  42. }
  43. #[async_trait]
  44. impl Platform for BinanceSwap {
  45. // 克隆方法
  46. fn clone_box(&self) -> Box<dyn Platform + Send + Sync> { Box::new(self.clone()) }
  47. // 获取交易所模式
  48. fn get_self_exchange(&self) -> ExchangeEnum {
  49. ExchangeEnum::BinanceSwap
  50. }
  51. // 获取交易对
  52. fn get_self_symbol(&self) -> String { self.symbol.clone() }
  53. // 获取是否使用高速通道
  54. fn get_self_is_colo(&self) -> bool {
  55. self.is_colo
  56. }
  57. // 获取params信息
  58. fn get_self_params(&self) -> BTreeMap<String, String> {
  59. self.params.clone()
  60. }
  61. // 获取market信息
  62. fn get_self_market(&self) -> Market { self.market.clone() }
  63. // 获取请求时间
  64. fn get_request_delays(&self) -> Vec<i64> { self.request.get_delays() }
  65. // 获取请求平均时间
  66. fn get_request_avg_delay(&self) -> Decimal { self.request.get_avg_delay() }
  67. // 获取请求最大时间
  68. fn get_request_max_delay(&self) -> i64 { self.request.get_max_delay() }
  69. // 获取服务器时间
  70. async fn get_server_time(&mut self) -> Result<String, Error> {
  71. let res_data = self.request.get_server_time().await;
  72. if res_data.code == 200 {
  73. let res_data_json = res_data.data;
  74. let result = res_data_json["serverTime"].to_string();
  75. Ok(result)
  76. } else {
  77. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  78. }
  79. }
  80. // 获取账号信息
  81. async fn get_account(&mut self) -> Result<Account, Error> {
  82. let symbol_array: Vec<&str> = self.symbol.split("_").collect();
  83. let res_data = self.request.get_account().await;
  84. if res_data.code == 200 {
  85. let res_data_json = res_data.data.as_array().unwrap();
  86. let balance_info = res_data_json.iter().find(|item| item["asset"].as_str().unwrap().to_string() == symbol_array[1].to_string());
  87. match balance_info {
  88. None => {
  89. error!("binance_swap:格式化账号信息错误!\nget_account: res_data={:?}", res_data);
  90. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  91. }
  92. Some(value) => {
  93. let balance = Decimal::from_str(value["balance"].as_str().unwrap()).unwrap();
  94. let available_balance = Decimal::from_str(value["availableBalance"].as_str().unwrap()).unwrap();
  95. let frozen_balance = balance - available_balance;
  96. let result = Account {
  97. coin: value["asset"].as_str().unwrap().to_string(),
  98. balance,
  99. available_balance,
  100. frozen_balance,
  101. stocks: Decimal::ZERO,
  102. available_stocks: Decimal::ZERO,
  103. frozen_stocks: Decimal::ZERO,
  104. };
  105. Ok(result)
  106. }
  107. }
  108. } else {
  109. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  110. }
  111. }
  112. async fn get_spot_account(&mut self) -> Result<Vec<Account>, Error> {
  113. Err(Error::new(ErrorKind::NotFound, "binance_swap:该交易所方法未实现".to_string()))
  114. }
  115. // 获取仓位信息
  116. async fn get_position(&mut self) -> Result<Vec<Position>, Error> {
  117. let symbol_format = utils::format_symbol(self.symbol.clone(), "");
  118. let ct_val = self.market.ct_val;
  119. let res_data = self.request.get_position_risk(symbol_format).await;
  120. if res_data.code == 200 {
  121. let res_data_json = res_data.data.as_array().unwrap();
  122. let result = res_data_json.iter().map(|item| { format_position_item(item, ct_val) }).collect();
  123. Ok(result)
  124. } else {
  125. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  126. }
  127. }
  128. async fn get_positions(&mut self) -> Result<Vec<Position>, Error> {
  129. let res_data = self.request.get_position_risk("".to_string()).await;
  130. if res_data.code == 200 {
  131. let res_data_json = res_data.data.as_array().unwrap();
  132. let result = res_data_json.iter().map(|item| { format_position_item(item, Decimal::ONE) }).collect();
  133. Ok(result)
  134. } else {
  135. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  136. }
  137. }
  138. // 获取市场行情
  139. async fn get_ticker(&mut self) -> Result<Ticker, Error> {
  140. let symbol_format = utils::format_symbol(self.symbol.clone(), "");
  141. let res_data = self.request.get_book_ticker(symbol_format).await;
  142. if res_data.code == 200 {
  143. let res_data_json: serde_json::Value = res_data.data;
  144. let result = Ticker {
  145. time: res_data_json["time"].as_i64().unwrap(),
  146. high: Decimal::from_str(res_data_json["askPrice"].as_str().unwrap()).unwrap(),
  147. low: Decimal::from_str(res_data_json["bidPrice"].as_str().unwrap()).unwrap(),
  148. sell: Decimal::from_str(res_data_json["askPrice"].as_str().unwrap()).unwrap(),
  149. buy: Decimal::from_str(res_data_json["bidPrice"].as_str().unwrap()).unwrap(),
  150. last: dec!(-1),
  151. volume: dec!(-1),
  152. };
  153. Ok(result)
  154. } else {
  155. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  156. }
  157. }
  158. async fn get_ticker_symbol(&mut self, symbol: String) -> Result<Ticker, Error> {
  159. let symbol_format = utils::format_symbol(symbol.clone(), "");
  160. let res_data = self.request.get_book_ticker(symbol_format).await;
  161. if res_data.code == 200 {
  162. let res_data_json: serde_json::Value = res_data.data;
  163. let result = Ticker {
  164. time: res_data_json["time"].as_i64().unwrap(),
  165. high: Decimal::from_str(res_data_json["askPrice"].as_str().unwrap()).unwrap(),
  166. low: Decimal::from_str(res_data_json["bidPrice"].as_str().unwrap()).unwrap(),
  167. sell: Decimal::from_str(res_data_json["askPrice"].as_str().unwrap()).unwrap(),
  168. buy: Decimal::from_str(res_data_json["bidPrice"].as_str().unwrap()).unwrap(),
  169. last: dec!(-1),
  170. volume: dec!(-1),
  171. };
  172. Ok(result)
  173. } else {
  174. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  175. }
  176. }
  177. async fn get_market(&mut self) -> Result<Market, Error> {
  178. let symbol_format = utils::format_symbol(self.symbol.clone(), "");
  179. let res_data = self.request.get_exchange_info().await;
  180. if res_data.code == 200 {
  181. let res_data_json = res_data.data;
  182. let symbols = res_data_json["symbols"].as_array().unwrap();
  183. let market_info = symbols.iter().find(|&item| item["symbol"].as_str().unwrap() == symbol_format);
  184. match market_info {
  185. None => {
  186. error!("binance_swap:获取Market信息错误!\nget_market:res_data={:?}", res_data_json);
  187. Err(Error::new(ErrorKind::Other, res_data_json.to_string()))
  188. }
  189. Some(value) => {
  190. let base_asset = value["baseAsset"].as_str().unwrap_or("").to_string();
  191. let quote_asset = value["quoteAsset"].as_str().unwrap_or("").to_string();
  192. let filter_array = value["filters"].as_array().unwrap().clone();
  193. let price_filter = filter_array.iter().find(|&item| item["filterType"].as_str().unwrap() == "PRICE_FILTER").unwrap();
  194. let lot_size_filter = filter_array.iter().find(|&item| item["filterType"].as_str().unwrap() == "LOT_SIZE").unwrap();
  195. let result = Market {
  196. symbol: format!("{}_{}", base_asset, quote_asset),
  197. base_asset,
  198. quote_asset,
  199. tick_size: Decimal::from_str(&price_filter["tickSize"].as_str().unwrap()).unwrap(),
  200. amount_size: Decimal::from_str(lot_size_filter["stepSize"].as_str().unwrap()).unwrap(),
  201. price_precision: Decimal::from_f64(value["pricePrecision"].as_f64().unwrap()).unwrap(),
  202. amount_precision: Decimal::from_f64(value["quantityPrecision"].as_f64().unwrap()).unwrap(),
  203. min_qty: Decimal::from_str(lot_size_filter["minQty"].as_str().unwrap()).unwrap(),
  204. max_qty: Decimal::from_str(lot_size_filter["maxQty"].as_str().unwrap()).unwrap(),
  205. min_notional: Decimal::from_str(price_filter["minPrice"].as_str().unwrap()).unwrap(),
  206. max_notional: Decimal::from_str(price_filter["maxPrice"].as_str().unwrap()).unwrap(),
  207. ct_val: Decimal::ONE,
  208. };
  209. Ok(result)
  210. }
  211. }
  212. } else {
  213. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  214. }
  215. }
  216. async fn get_market_symbol(&mut self, symbol: String) -> Result<Market, Error> {
  217. let symbol_format = utils::format_symbol(symbol.clone(), "");
  218. let res_data = self.request.get_exchange_info().await;
  219. if res_data.code == 200 {
  220. let res_data_json: serde_json::Value = res_data.data;
  221. let symbols = res_data_json["symbols"].as_array().unwrap();
  222. let market_info = symbols.iter().find(|&item| item["symbol"].as_str().unwrap() == symbol_format);
  223. match market_info {
  224. None => {
  225. error!("binance_swap:获取Market信息错误!\nget_market:res_data={:?}", res_data_json);
  226. Err(Error::new(ErrorKind::Other, res_data_json.to_string()))
  227. }
  228. Some(value) => {
  229. let base_asset = value["baseAsset"].as_str().unwrap_or("").to_string();
  230. let quote_asset = value["quoteAsset"].as_str().unwrap_or("").to_string();
  231. let filter_array = value["filters"].as_array().unwrap().clone();
  232. let price_filter = filter_array.iter().find(|&item| item["filterType"].as_str().unwrap() == "PRICE_FILTER").unwrap();
  233. let lot_size_filter = filter_array.iter().find(|&item| item["filterType"].as_str().unwrap() == "LOT_SIZE").unwrap();
  234. let result = Market {
  235. symbol: format!("{}_{}", base_asset, quote_asset),
  236. base_asset,
  237. quote_asset,
  238. tick_size: Decimal::from_str(&price_filter["tickSize"].as_str().unwrap()).unwrap(),
  239. amount_size: Decimal::from_str(lot_size_filter["stepSize"].as_str().unwrap()).unwrap(),
  240. price_precision: Decimal::from_f64(value["pricePrecision"].as_f64().unwrap()).unwrap(),
  241. amount_precision: Decimal::from_f64(value["quantityPrecision"].as_f64().unwrap()).unwrap(),
  242. min_qty: Decimal::from_str(lot_size_filter["minQty"].as_str().unwrap()).unwrap(),
  243. max_qty: Decimal::from_str(lot_size_filter["maxQty"].as_str().unwrap()).unwrap(),
  244. min_notional: Decimal::from_str(price_filter["minPrice"].as_str().unwrap()).unwrap(),
  245. max_notional: Decimal::from_str(price_filter["maxPrice"].as_str().unwrap()).unwrap(),
  246. ct_val: Decimal::ONE,
  247. };
  248. Ok(result)
  249. }
  250. }
  251. } else {
  252. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  253. }
  254. }
  255. async fn get_order_detail(&mut self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
  256. let symbol_format = utils::format_symbol(self.symbol.clone(), "");
  257. let res_data = self.request.get_order(symbol_format, order_id.parse().unwrap_or(-1), custom_id.to_string()).await;
  258. if res_data.code == 200 {
  259. let res_data_json: serde_json::Value = res_data.data;
  260. let status = res_data_json["status"].as_str().unwrap();
  261. let custom_status = if ["CANCELED", "EXPIRED", "FILLED"].contains(&status) { "REMOVE".to_string() } else if status == "NEW" { "NEW".to_string() } else {
  262. error!("binance_swap:格式化订单状态错误!\nget_order_detail:res_data={:?}", res_data_json);
  263. panic!("binance_swap:格式化订单状态错误!\nget_order_detail:res_data={:?}", res_data_json)
  264. };
  265. let result = Order {
  266. id: res_data_json["orderId"].to_string(),
  267. custom_id: res_data_json["clientOrderId"].as_str().unwrap().parse().unwrap(),
  268. price: Decimal::from_str(res_data_json["price"].as_str().unwrap()).unwrap(),
  269. amount: Decimal::from_str(res_data_json["origQty"].as_str().unwrap()).unwrap(),
  270. deal_amount: Decimal::from_str(res_data_json["executedQty"].as_str().unwrap()).unwrap(),
  271. avg_price: Decimal::from_str(res_data_json["avgPrice"].as_str().unwrap()).unwrap(),
  272. status: custom_status,
  273. order_type: res_data_json["type"].as_str().unwrap().parse().unwrap()
  274. };
  275. Ok(result)
  276. } else {
  277. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  278. }
  279. }
  280. async fn get_orders_list(&mut self, _status: &str) -> Result<Vec<Order>, Error> {
  281. let symbol_format = utils::format_symbol(self.symbol.clone(), "");
  282. let res_data = self.request.get_open_orders(symbol_format).await;
  283. if res_data.code == 200 {
  284. let res_data_json = res_data.data.as_array().unwrap();
  285. let order_info: Vec<_> = res_data_json.iter().filter(|item| item["contract"].as_str().unwrap_or("") == self.symbol).collect();
  286. let result = order_info.iter().map(|&item| {
  287. let status = item["status"].as_str().unwrap();
  288. let custom_status = if ["CANCELED", "EXPIRED", "FILLED"].contains(&status) { "REMOVE".to_string() } else if status == "NEW" { "NEW".to_string() } else {
  289. error!("binance_swap:格式化订单状态错误!\nget_order_detail:res_data={:?}", res_data);
  290. panic!("binance_swap:格式化订单状态错误!\nget_order_detail:res_data={:?}", res_data)
  291. };
  292. Order {
  293. id: item["orderId"].to_string(),
  294. custom_id: item["clientOrderId"].as_str().unwrap().parse().unwrap(),
  295. price: Decimal::from_str(item["price"].as_str().unwrap()).unwrap(),
  296. amount: Decimal::from_str(item["origQty"].as_str().unwrap()).unwrap(),
  297. deal_amount: Decimal::from_str(item["executedQty"].as_str().unwrap()).unwrap(),
  298. avg_price: Decimal::from_str(item["avgPrice"].as_str().unwrap()).unwrap(),
  299. status: custom_status,
  300. order_type: item["type"].as_str().unwrap().parse().unwrap()
  301. }
  302. }).collect();
  303. Ok(result)
  304. } else {
  305. Err(Error::new(ErrorKind::Other, res_data.to_string()))
  306. }
  307. }
  308. async fn take_order(&mut self, _custom_id: &str, _origin_side: &str, _price: Decimal, _amount: Decimal) -> Result<Order, Error> { Err(Error::new(ErrorKind::NotFound, "binance_swap:该交易所方法未实现".to_string())) }
  309. 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> { Err(Error::new(ErrorKind::NotFound, "binance_swap:该交易所方法未实现".to_string())) }
  310. async fn cancel_order(&mut self, _order_id: &str, _custom_id: &str) -> Result<Order, Error> { Err(Error::new(ErrorKind::NotFound, "binance_swap:该交易所方法未实现".to_string())) }
  311. async fn cancel_orders(&mut self) -> Result<Vec<Order>, Error> { Err(Error::new(ErrorKind::NotFound, "binance_swap:该交易所方法未实现".to_string())) }
  312. async fn cancel_orders_all(&mut self) -> Result<Vec<Order>, Error> { Err(Error::new(ErrorKind::NotFound, "binance_swap:该交易所方法未实现".to_string())) }
  313. async fn take_stop_loss_order(&mut self, _stop_price: Decimal, _price: Decimal, _side: &str) -> Result<Value, Error> {
  314. Err(Error::new(ErrorKind::NotFound, "binance_swap:该交易所方法未实现".to_string()))
  315. }
  316. async fn cancel_stop_loss_order(&mut self, _order_id: &str) -> Result<Value, Error> {
  317. Err(Error::new(ErrorKind::NotFound, "binance_swap:该交易所方法未实现".to_string()))
  318. }
  319. async fn set_dual_mode(&mut self, _coin: &str, _is_dual_mode: bool) -> Result<String, Error> { Err(Error::new(ErrorKind::NotFound, "binance_swap:该交易所方法未实现".to_string())) }
  320. async fn set_dual_leverage(&mut self, _leverage: &str) -> Result<String, Error> { Err(Error::new(ErrorKind::NotFound, "binance_swap:该交易所方法未实现".to_string())) }
  321. async fn set_auto_deposit_status(&mut self, _status: bool) -> Result<String, Error> { Err(Error::new(ErrorKind::NotFound, "binance_swap:该交易所方法未实现".to_string())) }
  322. async fn wallet_transfers(&mut self, _coin: &str, _from: &str, _to: &str, _amount: Decimal) -> Result<String, Error> { Err(Error::new(ErrorKind::NotFound, "binance_swap:该交易所方法未实现".to_string())) }
  323. }
  324. pub fn format_position_item(position: &serde_json::Value, ct_val: Decimal) -> Position {
  325. let mut position_mode = match position["positionSide"].as_str().unwrap_or("") {
  326. "BOTH" => PositionModeEnum::Both,
  327. "LONG" => PositionModeEnum::Long,
  328. "SHORT" => PositionModeEnum::Short,
  329. _ => {
  330. error!("binance_swap:格式化持仓模式错误!\nformat_position_item:position={:?}", position);
  331. panic!("binance_swap:格式化持仓模式错误!\nformat_position_item:position={:?}", position)
  332. }
  333. };
  334. let size = Decimal::from_str(position["positionAmt"].as_str().unwrap()).unwrap();
  335. let amount = size * ct_val;
  336. match position_mode {
  337. PositionModeEnum::Both => {
  338. position_mode = match amount {
  339. amount if amount > Decimal::ZERO => PositionModeEnum::Long,
  340. amount if amount < Decimal::ZERO => PositionModeEnum::Short,
  341. _ => { PositionModeEnum::Both }
  342. };
  343. }
  344. _ => {}
  345. }
  346. Position {
  347. symbol: position["symbol"].as_str().unwrap_or("").parse().unwrap(),
  348. margin_level: Decimal::from_str(position["leverage"].as_str().unwrap()).unwrap(),
  349. amount,
  350. frozen_amount: Decimal::ZERO,
  351. price: Decimal::from_str(position["entryPrice"].as_str().unwrap()).unwrap(),
  352. profit: Decimal::from_str(position["unRealizedProfit"].as_str().unwrap()).unwrap(),
  353. position_mode,
  354. margin: Decimal::from_str(position["isolatedMargin"].as_str().unwrap()).unwrap(),
  355. }
  356. }