Kaynağa Gözat

bybit标准层

gepangpang 1 yıl önce
ebeveyn
işleme
fc7e0ab448

+ 0 - 0
derive/src/bitget_swap_rest.rs


+ 0 - 0
derive/src/bitget_swap_ws.rs


+ 10 - 0
exchanges/src/bitget_swap_rest.rs

@@ -126,6 +126,16 @@ impl BitgetSwapRest {
         ).await
     }
 
+    // 获取K线
+    pub async fn get_market_candles(&mut self, params: Value) -> ResponseData {
+        self.request("GET".to_string(),
+                     "/api/v2".to_string(),
+                     "/mix/market/candles".to_string(),
+                     true,
+                     params.to_string(),
+        ).await
+    }
+
     // 下单
     pub async fn swap_order(&mut self, params: Value) -> ResponseData {
         self.request("POST".to_string(),

+ 1 - 1
standard/Cargo.toml

@@ -12,7 +12,7 @@ tokio = { version = "1.31.0", features = ["full"] }
 async-trait = "0.1.73"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0.104"
-rust_decimal = "1.32.0"
+rust_decimal = { version = "1.32.0", features = ["maths"] }
 rust_decimal_macros = "1.32.0"
 chrono = "0.4.30"
 futures = "0.3"

+ 769 - 668
standard/src/bitget_swap.rs

@@ -1,670 +1,771 @@
-// use std::collections::{BTreeMap};
-// use exchanges::bitget_swap_rest::BitgetSwapRest;
-// use std::io::{Error, ErrorKind};
-// use tokio::sync::mpsc::Sender;
-// use std::str::FromStr;
-// use async_trait::async_trait;
-// use futures::stream::FuturesUnordered;
-// use futures::TryStreamExt;
-// use rust_decimal::{Decimal, MathematicalOps};
-// use rust_decimal::prelude::ToPrimitive;
-// use rust_decimal_macros::dec;
-// use serde_json::{json, Value};
-// use tokio::spawn;
-// use tokio::time::Instant;
-// use tracing::{error, info};
-// use global::trace_stack::TraceStack;
-// use crate::exchange::ExchangeEnum;
-// use crate::{Account, Market, Order, OrderCommand, Platform, Position, PositionModeEnum, Ticker, utils};
-//
-// #[allow(dead_code)]
-// #[derive(Clone)]
-// pub struct BitgetSwap {
-//     exchange: ExchangeEnum,
-//     symbol: String,
-//     is_colo: bool,
-//     params: BTreeMap<String, String>,
-//     request: BitgetSwapRest,
-//     market: Market,
-//     order_sender: Sender<Order>,
-//     error_sender: Sender<Error>,
-// }
-//
-// impl BitgetSwap {
-//     pub async fn new(symbol: String, is_colo: bool, params: BTreeMap<String, String>, order_sender: Sender<Order>, error_sender: Sender<Error>) -> BitgetSwap {
-//         let market = Market::new();
-//         let mut bitget_swap = BitgetSwap {
-//             exchange: ExchangeEnum::BitgetSwap,
-//             symbol: symbol.to_uppercase(),
-//             is_colo,
-//             params: params.clone(),
-//             request: BitgetSwapRest::new(is_colo, params.clone()),
-//             market,
-//             order_sender,
-//             error_sender,
-//         };
-//         bitget_swap.market = BitgetSwap::get_market(&mut bitget_swap).await.unwrap();
-//         // 修改持仓模式
-//         let mode_result = bitget_swap.set_dual_mode("", true).await;
-//         match mode_result {
-//             Ok(ok) => {
-//                 info!("BitgetSwap:设置持仓模式成功!{:?}", ok);
-//             }
-//             Err(error) => {
-//                 error!("BitgetSwap:设置持仓模式失败!{:?}", error)
-//             }
-//         }
-//         // 设置持仓杠杆
-//         // let lever_rate_result = bitget_swap.set_dual_leverage("10").await;
-//         // match lever_rate_result {
-//         //     Ok(ok) => {
-//         //         info!("BitgetSwap:设置持仓杠杆成功!{:?}", ok);
-//         //     }
-//         //     Err(error) => {
-//         //         error!("BitgetSwap:设置持仓杠杆失败!{:?}", error)
-//         //     }
-//         // }
-//
-//         return bitget_swap;
-//     }
-// }
-//
-// #[async_trait]
-// impl Platform for BitgetSwap {
-//     fn clone_box(&self) -> Box<dyn Platform + Send + Sync> { Box::new(self.clone()) }
-//
-//     fn get_self_exchange(&self) -> ExchangeEnum { ExchangeEnum::BitgetSwap }
-//
-//     fn get_self_symbol(&self) -> String { self.symbol.clone() }
-//
-//     fn get_self_is_colo(&self) -> bool { self.is_colo }
-//
-//     fn get_self_params(&self) -> BTreeMap<String, String> { self.params.clone() }
-//
-//     fn get_self_market(&self) -> Market { self.market.clone() }
-//
-//     fn get_request_delays(&self) -> Vec<i64> {
-//         // self.request.get_delays()
-//         vec![]
-//     }
-//
-//     fn get_request_avg_delay(&self) -> Decimal {
-//         // self.request.get_avg_delay()
-//         Decimal::ZERO
-//     }
-//
-//     fn get_request_max_delay(&self) -> i64 { 0 }
-//
-//     async fn get_server_time(&mut self) -> Result<String, Error> {
-//         let res_data = self.request.get_server_time().await;
-//         if res_data.code == 200 {
-//             let res_data_json = res_data.data;
-//             let result = res_data_json["serverTime"].as_str().unwrap().to_string();
-//             Ok(result)
-//         } else {
-//             Err(Error::new(ErrorKind::Other, res_data.to_string()))
-//         }
-//     }
-//
-//     async fn get_account(&mut self) -> Result<Account, Error> {
-//         let response = self.request.get_account_info().await;
-//
-//         if response.code == 200 {
-//             for data in response.data.as_array().unwrap() {
-//                 if data["marginCoin"].as_str().unwrap() != "USDT" {
-//                     continue
-//                 }
-//
-//                 // 格式化account信息
-//                 let mut account = Account {
-//                     coin: data["marginCoin"].to_string(),
-//                     balance: Decimal::from_str(data["accountEquity"].as_str().unwrap()).unwrap(),
-//                     available_balance: Decimal::from_str(data["available"].as_str().unwrap()).unwrap(),
-//                     frozen_balance: Default::default(),
-//                     stocks: Default::default(),
-//                     available_stocks: Default::default(),
-//                     frozen_stocks: Default::default(),
-//                 };
-//                 account.frozen_balance = account.balance - account.available_balance;
-//
-//                 return Ok(account)
-//             }
-//
-//             Err(Error::new(ErrorKind::NotFound, format!("bitget_usdt_swap 未能找到USDT账户:{}。", response.to_string())))
-//         } else {
-//             Err(Error::new(ErrorKind::Other, response.to_string()))
-//         }
-//     }
-//
-//     async fn get_spot_account(&mut self) -> Result<Vec<Account>, Error> {
-//         Err(Error::new(ErrorKind::NotFound, "bitget_swap get_spot_account:该交易所方法未实现".to_string()))
-//     }
-//
-//     async fn get_position(&mut self) -> Result<Vec<Position>, Error> { Err(Error::new(ErrorKind::NotFound, "bitget_swap get_position:该交易所方法未实现".to_string())) }
-//
-//     async fn get_positions(&mut self) -> Result<Vec<Position>, Error> {
-//         let params = json!({
-//             "productType": "USDT-FUTURES",
-//             "marginCoin": "USDT"
-//         });
-//         let response = self.request.get_all_position(params).await;
-//         info!(?response);
-//
-//         if response.code != 200 {
-//             return Err(Error::new(ErrorKind::NotFound, format!("bitget_swap 获取仓位异常{:?}", response).to_string()))
-//         }
-//
-//         // 正常处理持仓信息
-//         let mut positions: Vec<Position> = vec![];
-//         if response.data.is_null() {
-//             return Ok(positions)
-//         }
-//
-//         let positions_json = response.data.as_array().unwrap();
-//         for position_json in positions_json {
-//             let symbol = position_json["symbol"].as_str().unwrap().to_string();
-//             let margin_level = Decimal::from_str(position_json["leverage"].as_str().unwrap()).unwrap();
-//             let amount = Decimal::from_str(position_json["total"].as_str().unwrap()).unwrap();
-//             let frozen_amount = Decimal::from_str(position_json["locked"].as_str().unwrap()).unwrap();
-//             let price = Decimal::from_str(position_json["openPriceAvg"].as_str().unwrap()).unwrap();
-//             let profit = Decimal::from_str(position_json["unrealizedPL"].as_str().unwrap()).unwrap();
-//             let position_mode = match position_json["posMode"].as_str().unwrap() {
-//                 "hedge_mode" => {
-//                     match position_json["holdSide"].as_str().unwrap() {
-//                         "short" => {
-//                             PositionModeEnum::Short
-//                         }
-//                         "long" => {
-//                             PositionModeEnum::Long
-//                         },
-//                         _ => {
-//                             panic!("bitget_usdt_swap: 未知的持仓模式与持仓方向: {}, {}",
-//                                    position_json["posMode"].as_str().unwrap(), position_json["holdSide"].as_str().unwrap())
-//                         }
-//                     }
-//                 },
-//                 "one_way_mode" => {
-//                     PositionModeEnum::Both
-//                 },
-//                 _ => {
-//                     panic!("bitget_usdt_swap: 未知的持仓模式: {}", position_json["posMode"].as_str().unwrap())
-//                 }
-//             };
-//             let margin = Decimal::from_str(position_json["marginSize"].as_str().unwrap()).unwrap();
-//
-//             positions.push(Position {
-//                 symbol,
-//                 margin_level,
-//                 amount,
-//                 frozen_amount,
-//                 price,
-//                 profit,
-//                 position_mode,
-//                 margin,
-//             });
-//         }
-//
-//         Ok(positions)
-//     }
-//
-//     async fn get_ticker(&mut self) -> Result<Ticker, Error> {
-//         return self.get_ticker_symbol(self.symbol.clone()).await
-//     }
-//
-//     async fn get_ticker_symbol(&mut self, symbol: String) -> Result<Ticker, Error> {
-//         let symbol_format = utils::format_symbol(symbol.clone(), "");
-//         let res_data = self.request.get_tickers(symbol_format).await;
-//         if res_data.code == 200 {
-//             let res_data_json = res_data.data;
-//             let ticker_info = res_data_json[0].clone();
-//             let time = (Decimal::from_str(&*ticker_info["ts"].as_str().unwrap()).unwrap() / dec!(1000)).floor().to_i64().unwrap();
-//             let result = Ticker {
-//                 time,
-//                 high: Decimal::from_str(ticker_info["high24h"].as_str().unwrap()).unwrap(),
-//                 low: Decimal::from_str(ticker_info["low24h"].as_str().unwrap()).unwrap(),
-//                 sell: Decimal::from_str(ticker_info["askPr"].as_str().unwrap()).unwrap(),
-//                 buy: Decimal::from_str(ticker_info["bidPr"].as_str().unwrap()).unwrap(),
-//                 last: Decimal::from_str(ticker_info["lastPr"].as_str().unwrap()).unwrap(),
-//                 volume: Decimal::from_str(ticker_info["quoteVolume"].as_str().unwrap()).unwrap(),
-//             };
-//             Ok(result)
-//         } else {
-//             Err(Error::new(ErrorKind::Other, res_data.to_string()))
-//         }
-//     }
-//
-//     async fn get_market(&mut self) -> Result<Market, Error> {
-//         self.get_market_symbol(self.symbol.clone()).await
-//     }
-//
-//     async fn get_market_symbol(&mut self, symbol: String) -> Result<Market, Error> {
-//         let symbol_format = utils::format_symbol(symbol.clone(), "");
-//         let response = self.request.get_contracts(symbol_format.clone()).await;
-//
-//         if response.code == 200 {
-//             let res_data_json = response.data.as_array().unwrap();
-//             let market_info = res_data_json[0].clone();
-//
-//             info!(?market_info);
-//             if !market_info["symbol"].as_str().unwrap().to_string().eq(&symbol_format) {
-//                 return Err(Error::new(ErrorKind::NotFound, format!("符号未找到:symbol={}, response={:?}", symbol_format, response))).unwrap();
-//             }
-//
-//             let base_asset = market_info["baseCoin"].as_str().unwrap().to_string();
-//             let quote_asset = market_info["quoteCoin"].as_str().unwrap().to_string();
-//             let price_precision = Decimal::from_str(market_info["pricePlace"].as_str().unwrap()).unwrap();
-//             let tick_size = Decimal::TEN.powd(Decimal::NEGATIVE_ONE * price_precision);
-//             let amount_precision = Decimal::from_str(market_info["volumePlace"].as_str().unwrap()).unwrap();
-//             let amount_size = Decimal::TEN.powd(Decimal::NEGATIVE_ONE * amount_precision);
-//             let min_qty = Decimal::NEGATIVE_ONE;
-//             let max_qty = Decimal::NEGATIVE_ONE;
-//             // let ct_val = Decimal::from_str(&market_info["sizeMultiplier"].as_str().unwrap()).unwrap();
-//             let ct_val = Decimal::ONE;
-//
-//             let result = Market {
-//                 symbol: format!("{}_{}", base_asset, quote_asset),
-//                 base_asset,
-//                 quote_asset,
-//                 tick_size,
-//                 amount_size,
-//                 price_precision,
-//                 amount_precision,
-//                 min_qty,
-//                 max_qty,
-//                 min_notional: min_qty,
-//                 max_notional: max_qty,
-//                 ct_val,
-//             };
-//             Ok(result)
-//         } else {
-//             Err(Error::new(ErrorKind::Other, response.to_string()))
-//         }
-//     }
-//
-//     async fn get_order_detail(&mut self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
-//         let symbol_format = utils::format_symbol(self.symbol.clone(), "");
-//         let params = json!({
-//             "symbol": symbol_format,
-//             "productType": "USDT-FUTURES",
-//             "clientOid": custom_id,
-//             "orderId": order_id
-//         });
-//
-//         let ct_val = self.market.ct_val;
-//         let response = self.request.get_order(params).await;
-//         if response.code == 200 {
-//             let res_data_json = response.data;
-//             let result = format_order_item(res_data_json, ct_val);
-//             Ok(result)
-//         } else {
-//             Err(Error::new(ErrorKind::Other, response.to_string()))
-//         }
-//     }
-//
-//     async fn get_orders_list(&mut self, _status: &str) -> Result<Vec<Order>, Error> {
-//         Err(Error::new(ErrorKind::NotFound, "bitget_swap get_orders_list:该交易所方法未实现".to_string()))
-//         // let symbol_format = utils::format_symbol(self.symbol.clone(), "");
-//         // let ct_val = self.market.ct_val;
-//         // let res_data = self.request.get_unfilled_orders(symbol_format.to_string(), "".to_string(), "".to_string(), "".to_string(), "100".to_string(), "".to_string()).await;
-//         // if res_data.code == 200 {
-//         //     let res_data_str = &res_data.data;
-//         //     let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
-//         //     let result = res_data_json.iter().map(|item| format_order_item(item.clone(), ct_val)).collect();
-//         //     Ok(result)
-//         // } else {
-//         //     Err(Error::new(ErrorKind::Other, res_data.to_string()))
-//         // }
-//     }
-//
-//     async fn take_order(&mut self, custom_id: &str, origin_side: &str, price: Decimal, amount: Decimal) -> Result<Order, Error> {
-//         let ct_val = self.market.ct_val;
-//
-//         return self.take_order_symbol(self.symbol.clone(), ct_val, custom_id, origin_side, price, amount).await;
-//     }
-//
-//     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> {
-//         let symbol_format = utils::format_symbol(symbol, "");
-//         let final_size = amount / ct_val;
-//         let mut params = json!({
-//             "symbol": symbol_format,
-//             "clientOid": custom_id,
-//             "productType": "USDT-FUTURES",
-//             "marginMode": "crossed",
-//             "marginCoin": "USDT",
-//             "size": final_size.to_string()
-//         });
-//         if price.eq(&Decimal::ZERO) {
-//             params["orderType"] = json!("market");
-//             params["force"] = json!("gtc");
-//         } else {
-//             params["price"] = json!(price.to_string());
-//             params["orderType"] = json!("limit");
-//             params["force"] = json!("gtc");
-//         };
-//         match origin_side {
-//             "kd" => {
-//                 params["side"] = json!("buy");
-//                 params["tradeSide"] = json!("open");
-//             }
-//             "pd" => {
-//                 params["side"] = json!("buy");
-//                 params["tradeSide"] = json!("close");
-//             }
-//             "kk" => {
-//                 params["side"] = json!("sell");
-//                 params["tradeSide"] = json!("open");
-//             }
-//             "pk" => {
-//                 params["side"] = json!("sell");
-//                 params["tradeSide"] = json!("close");
-//             }
-//             _ => { panic!("bitget_usdt_swap 下单参数错误"); }
-//         };
-//         let res_data = self.request.swap_order(params).await;
-//         if res_data.code != 200 {
-//             return Err(Error::new(ErrorKind::Other, res_data.to_string()))
-//         }
-//
-//         let res_data_json = res_data.data;
-//         let result = Order {
-//             id: res_data_json["orderId"].as_str().unwrap().to_string(),
-//             custom_id: res_data_json["clientOid"].as_str().unwrap().to_string(),
-//             price: Decimal::ZERO,
-//             amount: Decimal::ZERO,
-//             deal_amount: Decimal::ZERO,
-//             avg_price: Decimal::ZERO,
-//             status: "NEW".to_string(),
-//             order_type: "".to_string(),
-//             trace_stack: TraceStack::new(0, Instant::now()).on_special("328 bitget_swap".to_string()),
-//         };
-//         return Ok(result)
-//     }
-//
-//     async fn cancel_order(&mut self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
-//         let symbol_format = utils::format_symbol(self.symbol.clone(), "");
-//         let params = json!({
-//             "symbol": symbol_format,
-//             "productType": "USDT-FUTURES",
-//             "clientOid": custom_id,
-//             "orderId": order_id
-//         });
-//         let response = self.request.cancel_order(params).await;
-//
-//         // 取消失败,进行报错
-//         if response.code != 200 {
-//             return Err(Error::new(ErrorKind::NotFound, response.to_string()));
-//         }
-//
-//         let res_data_json = response.data;
-//         let result = Order {
-//             id: res_data_json["orderId"].as_str().unwrap().to_string(),
-//             custom_id: res_data_json["clientOid"].as_str().unwrap().to_string(),
-//             price: Decimal::ZERO,
-//             amount: Decimal::ZERO,
-//             deal_amount: Decimal::ZERO,
-//             avg_price: Decimal::ZERO,
-//             status: "REMOVE".to_string(),
-//             order_type: "".to_string(),
-//             trace_stack: TraceStack::new(0, Instant::now()).on_special("443 bitget_swap".to_string()),
-//         };
-//         Ok(result)
-//     }
-//
-//     async fn cancel_orders(&mut self) -> Result<Vec<Order>, Error> {
-//         Err(Error::new(ErrorKind::NotFound, "bitget_swap cancel_orders:该交易所方法未实现".to_string()))
-//     }
-//
-//     async fn cancel_orders_all(&mut self) -> Result<Vec<Order>, Error> {
-//         let response = self.request.get_pending_orders().await;
-//         if response.code == 200 {
-//             info!("{}", response.data.to_string());
-//             let mut result = vec![];
-//
-//             if !response.data["entrustedList"].is_null() {
-//                 let orders_res_data_json = response.data["entrustedList"].as_array().unwrap();
-//                 for order in orders_res_data_json {
-//                     let symbol = order["symbol"].as_str().unwrap().to_string();
-//                     let order_id = order["orderId"].as_str().unwrap().to_string();
-//                     let params = json!({
-//                         "symbol": symbol,
-//                         "productType": "USDT-FUTURES",
-//                         "orderId": order_id,
-//                     });
-//                     let cancel_res_data = self.request.cancel_order(params).await;
-//                     if cancel_res_data.code == 200 {
-//                         let cancel_res_data_json = cancel_res_data.data;
-//                         result.push(Order {
-//                             id: cancel_res_data_json["orderId"].as_str().unwrap().to_string(),
-//                             custom_id: cancel_res_data_json["clientOid"].as_str().unwrap().to_string(),
-//                             price: Decimal::ZERO,
-//                             amount: Decimal::ZERO,
-//                             deal_amount: Decimal::ZERO,
-//                             avg_price: Decimal::ZERO,
-//                             status: "REMOVE".to_string(),
-//                             order_type: "".to_string(),
-//                             trace_stack: TraceStack::new(0, Instant::now()).on_special("457 bitget_swap".to_string()),
-//                         });
-//                     } else {
-//                         return Err(Error::new(ErrorKind::Other, cancel_res_data.to_string()));
-//                     }
-//                 }
-//             }
-//             Ok(result)
-//         } else {
-//             Err(Error::new(ErrorKind::Other, response.to_string()))
-//         }
-//     }
-//
-//     async fn take_stop_loss_order(&mut self, _stop_price: Decimal, _price: Decimal, _side: &str) -> Result<Value, Error> {
-//         Err(Error::new(ErrorKind::NotFound, "bitget_swap take_stop_loss_order:该交易所方法未实现".to_string()))
-//     }
-//
-//     async fn cancel_stop_loss_order(&mut self, _order_id: &str) -> Result<Value, Error> {
-//         Err(Error::new(ErrorKind::NotFound, "bitget_swap cancel_stop_loss_order:该交易所方法未实现".to_string()))
-//     }
-//
-//     async fn set_dual_mode(&mut self, _coin: &str, is_dual_mode: bool) -> Result<String, Error> {
-//         let pos_mode = if is_dual_mode {
-//             "hedge_mode"
-//         } else {
-//             "one_way_mode"
-//         };
-//         let params = json!({
-//             "productType": "USDT-FUTURES",
-//             "posMode": pos_mode,
-//         });
-//         let response = self.request.set_position_mode(params).await;
-//
-//         if response.code != 200 {
-//             return Err(Error::new(ErrorKind::Other, format!("设置持仓模式失败:{:?}", response).to_string()))
-//         }
-//
-//         return Ok(response.data.to_string());
-//     }
-//
-//     async fn set_dual_leverage(&mut self, leverage: &str) -> Result<String, Error> {
-//         let params = json!({
-//             "symbol": "ETHUSDT",
-//             "productType": "USDT-FUTURES",
-//             "marginCoin": "USDT",
-//             "leverage": leverage
-//         });
-//         let response = self.request.set_leverage(params).await;
-//
-//         if response.code != 200 {
-//             return Err(Error::new(ErrorKind::Other, format!("设置杠杆失败:{:?}", response).to_string()))
-//         }
-//
-//         return Ok(response.data.to_string());
-//     }
-//
-//     async fn set_auto_deposit_status(&mut self, _status: bool) -> Result<String, Error> {
-//         Err(Error::new(ErrorKind::NotFound, "bitget_swap set_auto_deposit_status:该交易所方法未实现".to_string()))
-//     }
-//
-//     async fn wallet_transfers(&mut self, _coin: &str, _from: &str, _to: &str, _amount: Decimal) -> Result<String, Error> {
-//         Err(Error::new(ErrorKind::NotFound, "bitget_swap wallet_transfers:该交易所方法未实现".to_string()))
-//         // let coin_format = coin.to_string().to_uppercase();
-//         // let res_data = self.request.wallet_transfer(from.to_string(), to.to_string(), amount.to_string(), coin_format.clone(), "".to_string(), "".to_string()).await;
-//         // if res_data.code == 200 {
-//         //     let res_data_str = &res_data.data;
-//         //     let result = res_data_str.clone();
-//         //     Ok(result)
-//         // } else {
-//         //     Err(Error::new(ErrorKind::Other, res_data.to_string()))
-//         // }
-//     }
-//
-//     async fn command_order(&mut self, order_command: &mut OrderCommand, trace_stack: &TraceStack) {
-//         let mut handles = vec![];
-//
-//         // 下单指令
-//         for item in order_command.limits_open.keys() {
-//             let mut ts = trace_stack.clone();
-//
-//             let amount = Decimal::from_str(&*order_command.limits_open[item].get(0).unwrap().clone()).unwrap();
-//             let side = order_command.limits_open[item].get(1).unwrap().clone();
-//             let price = Decimal::from_str(&*order_command.limits_open[item].get(2).unwrap().clone()).unwrap();
-//             let cid = order_command.limits_open[item].get(3).unwrap().clone();
-//
-//             //  order_name: [数量,方向,价格,c_id]
-//             let mut self_clone = self.clone();
-//             let handle = spawn(async move {
-//                 // TraceStack::show_delay(&ts.ins);
-//                 ts.on_before_send();
-//                 let result = self_clone.take_order(cid.as_str(), side.as_str(), price, amount).await;
-//                 ts.on_after_send();
-//
-//                 match result {
-//                     Ok(mut result) => {
-//                         result.trace_stack = ts;
-//
-//                         self_clone.order_sender.send(result).await.unwrap();
-//                     }
-//                     Err(error) => {
-//                         info!(?error);
-//                         let mut err_order = Order::new();
-//                         err_order.custom_id = cid.clone();
-//                         err_order.status = "REMOVE".to_string();
-//
-//                         self_clone.order_sender.send(err_order).await.unwrap();
-//                         self_clone.error_sender.send(error).await.unwrap();
-//                     }
-//                 }
-//             });
-//             handles.push(handle)
-//         }
-//         let futures = FuturesUnordered::from_iter(handles);
-//         // 等待所有任务完成
-//         let _: Result<Vec<_>, _> = futures.try_collect().await;
-//
-//         // 撤销订单
-//         let mut cancel_handlers = vec![];
-//         for item in order_command.cancel.keys() {
-//             let order_id = order_command.cancel[item].get(1).unwrap().clone();
-//             let custom_id = order_command.cancel[item].get(0).unwrap().clone();
-//
-//             let mut self_clone = self.clone();
-//             let handle = spawn(async move {
-//                 let result = self_clone.cancel_order(&order_id, &custom_id).await;
-//                 match result {
-//                     Ok(_) => {
-//                         // result_sd.send(result).await.unwrap();
-//                     }
-//                     Err(error) => {
-//                         // 取消失败去查订单。
-//                         let query_rst = self_clone.get_order_detail(&order_id, &custom_id).await;
-//                         match query_rst {
-//                             Ok(order) => {
-//                                 self_clone.order_sender.send(order).await.unwrap();
-//                             }
-//                             Err(err) => {
-//                                 error!("撤单失败,而且查单也失败了,bitget_swap,oid={}, cid={}, err={:?}。", order_id.clone(), custom_id.clone(), err);
-//                             }
-//                         }
-//                         self_clone.error_sender.send(error).await.unwrap();
-//                     }
-//                 }
-//             });
-//             cancel_handlers.push(handle)
-//         }
-//         let futures = FuturesUnordered::from_iter(cancel_handlers);
-//         // 等待所有任务完成
-//         let _: Result<Vec<_>, _> = futures.try_collect().await;
-//
-//         // 检查订单指令
-//         let mut check_handlers = vec![];
-//         for item in order_command.check.keys() {
-//             let order_id = order_command.check[item].get(1).unwrap().clone();
-//             let custom_id = order_command.check[item].get(0).unwrap().clone();
-//
-//             let mut self_clone = self.clone();
-//             let handle = spawn(async move {
-//                 let result = self_clone.get_order_detail(order_id.as_str(), custom_id.as_str()).await;
-//                 match result {
-//                     Ok(result) => {
-//                         self_clone.order_sender.send(result).await.unwrap();
-//                     }
-//                     Err(error) => {
-//                         self_clone.error_sender.send(error).await.unwrap();
-//                     }
-//                 }
-//             });
-//             check_handlers.push(handle)
-//         }
-//
-//         let futures = FuturesUnordered::from_iter(check_handlers);
-//         // 等待所有任务完成
-//         let _: Result<Vec<_>, _> = futures.try_collect().await;
-//     }
-// }
-//
-// // pub fn format_account_info(balance_data: Value) -> Account {
-// //     let balance_coin = balance_data["coin"].as_str().unwrap().to_string().to_uppercase();
-// //     let available_balance = Decimal::from_str(balance_data["available"].as_str().unwrap()).unwrap();
-// //     let frozen_balance = Decimal::from_str(balance_data["frozen"].as_str().unwrap()).unwrap();
-// //     let balance = available_balance + frozen_balance;
-// //
-// //     Account {
-// //         coin: balance_coin,
-// //         balance,
-// //         available_balance,
-// //         frozen_balance,
-// //         stocks: Decimal::ZERO,
-// //         available_stocks: Decimal::ZERO,
-// //         frozen_stocks: Decimal::ZERO,
-// //     }
-// // }
-//
-// pub fn format_order_item(order: Value, ct_val: Decimal) -> Order {
-//     let price = Decimal::from_str(order["price"].as_str().unwrap_or(order["priceAvg"].as_str().unwrap())).unwrap();
-//     let size = Decimal::from_str(order["size"].as_str().unwrap()).unwrap();
-//     let status = order["state"].as_str().unwrap();
-//     let base_volume = Decimal::from_str(order["quoteVolume"].as_str().unwrap()).unwrap();
-//     let avg_price = if order["priceAvg"].is_null() || order["priceAvg"].as_str().unwrap().is_empty() {
-//         Decimal::ZERO
-//     } else {
-//         Decimal::from_str(order["priceAvg"].as_str().unwrap().to_string().as_str()).unwrap()
-//     };
-//
-//     let amount = size * ct_val;
-//     let deal_amount = base_volume * ct_val;
-//     let custom_status = if ["filled", "cancelled"].contains(&status) {
-//         "REMOVE".to_string()
-//     } else if ["init", "live", "new", "partially_filled"].contains(&status) {
-//         "NEW".to_string()
-//     } else {
-//         "NULL".to_string()
-//     };
-//     Order {
-//         id: order["orderId"].as_str().unwrap().to_string(),
-//         custom_id: order["clientOid"].as_str().unwrap().to_string(),
-//         price,
-//         amount,
-//         deal_amount,
-//         avg_price,
-//         status: custom_status,
-//         order_type: order["orderType"].as_str().unwrap().to_string(),
-//         trace_stack: TraceStack::new(0, Instant::now()).on_special("700 bitget_swap".to_string()),
+use std::collections::{BTreeMap};
+use exchanges::bitget_swap_rest::BitgetSwapRest;
+use std::io::{Error, ErrorKind};
+use tokio::sync::mpsc::Sender;
+use std::str::FromStr;
+use async_trait::async_trait;
+use futures::stream::FuturesUnordered;
+use futures::TryStreamExt;
+use rust_decimal::{Decimal, MathematicalOps};
+use rust_decimal::prelude::ToPrimitive;
+use rust_decimal_macros::dec;
+use serde_json::{json, Value};
+use tokio::spawn;
+use tokio::time::Instant;
+use tracing::{error, info};
+use global::trace_stack::TraceStack;
+use crate::exchange::ExchangeEnum;
+use crate::{Account, Market, Order, OrderCommand, Platform, Position, PositionModeEnum, Record, Ticker, utils};
+use crate::bybit_swap::format_position_item;
+
+#[allow(dead_code)]
+#[derive(Clone)]
+pub struct BitgetSwap {
+    exchange: ExchangeEnum,
+    symbol: String,
+    is_colo: bool,
+    params: BTreeMap<String, String>,
+    request: BitgetSwapRest,
+    market: Market,
+    order_sender: Sender<Order>,
+    error_sender: Sender<Error>,
+}
+
+impl BitgetSwap {
+    pub async fn new(symbol: String, is_colo: bool, params: BTreeMap<String, String>, order_sender: Sender<Order>, error_sender: Sender<Error>) -> BitgetSwap {
+        let market = Market::new();
+        let mut bitget_swap = BitgetSwap {
+            exchange: ExchangeEnum::BitgetSwap,
+            symbol: symbol.to_uppercase(),
+            is_colo,
+            params: params.clone(),
+            request: BitgetSwapRest::new(is_colo, params.clone()),
+            market,
+            order_sender,
+            error_sender,
+        };
+        bitget_swap.market = BitgetSwap::get_market(&mut bitget_swap).await.unwrap();
+        // 修改持仓模式
+        let mode_result = bitget_swap.set_dual_mode("", false).await;
+        match mode_result {
+            Ok(ok) => {
+                info!("BitgetSwap:设置持仓模式成功!{:?}", ok);
+            }
+            Err(error) => {
+                error!("BitgetSwap:设置持仓模式失败!{:?}", error)
+            }
+        }
+        // 设置持仓杠杆
+        let lever_rate_result = bitget_swap.set_dual_leverage("1").await;
+        match lever_rate_result {
+            Ok(ok) => {
+                info!("BitgetSwap:设置持仓杠杆成功!{:?}", ok);
+            }
+            Err(error) => {
+                error!("BitgetSwap:设置持仓杠杆失败!{:?}", error)
+            }
+        }
+
+        return bitget_swap;
+    }
+}
+
+#[async_trait]
+impl Platform for BitgetSwap {
+    fn clone_box(&self) -> Box<dyn Platform + Send + Sync> { Box::new(self.clone()) }
+
+    fn get_self_exchange(&self) -> ExchangeEnum { ExchangeEnum::BitgetSwap }
+
+    fn get_self_symbol(&self) -> String { self.symbol.clone() }
+
+    fn get_self_is_colo(&self) -> bool { self.is_colo }
+
+    fn get_self_params(&self) -> BTreeMap<String, String> { self.params.clone() }
+
+    fn get_self_market(&self) -> Market { self.market.clone() }
+
+    fn get_request_delays(&self) -> Vec<i64> {
+        // self.request.get_delays()
+        vec![]
+    }
+
+    fn get_request_avg_delay(&self) -> Decimal {
+        // self.request.get_avg_delay()
+        Decimal::ZERO
+    }
+
+    fn get_request_max_delay(&self) -> i64 { 0 }
+
+    async fn get_server_time(&mut self) -> Result<String, Error> {
+        let res_data = self.request.get_server_time().await;
+        if res_data.code == 200 {
+            let res_data_json = res_data.data;
+            let result = res_data_json["serverTime"].as_str().unwrap().to_string();
+            Ok(result)
+        } else {
+            Err(Error::new(ErrorKind::Other, res_data.to_string()))
+        }
+    }
+
+    async fn get_account(&mut self) -> Result<Account, Error> {
+        let response = self.request.get_account_info().await;
+
+        if response.code == 200 {
+            for data in response.data.as_array().unwrap() {
+                if data["marginCoin"].as_str().unwrap() != "USDT" {
+                    continue;
+                }
+
+                // 格式化account信息
+                let mut account = Account {
+                    coin: data["marginCoin"].as_str().unwrap().to_string(),
+                    balance: Decimal::from_str(data["accountEquity"].as_str().unwrap()).unwrap(),
+                    available_balance: Decimal::from_str(data["available"].as_str().unwrap()).unwrap(),
+                    frozen_balance: Default::default(),
+                    stocks: Default::default(),
+                    available_stocks: Default::default(),
+                    frozen_stocks: Default::default(),
+                };
+                account.frozen_balance = account.balance - account.available_balance;
+
+                return Ok(account);
+            }
+
+            Err(Error::new(ErrorKind::NotFound, format!("bitget_usdt_swap 未能找到USDT账户:{}。", response.to_string())))
+        } else {
+            Err(Error::new(ErrorKind::Other, response.to_string()))
+        }
+    }
+
+    async fn get_spot_account(&mut self) -> Result<Vec<Account>, Error> {
+        Err(Error::new(ErrorKind::NotFound, "bitget_swap get_spot_account:该交易所方法未实现".to_string()))
+    }
+
+    async fn get_position(&mut self) -> Result<Vec<Position>, Error> {
+        let symbol_format = utils::format_symbol(self.symbol.clone(), "");
+        let params = json!({
+            "productType": "USDT-FUTURES",
+            "marginCoin": "USDT",
+            "symbol": symbol_format
+        });
+        let ct_val = self.market.multiplier;
+        println!("{:?}", params.clone());
+        let response = self.request.get_single_position(params).await;
+        println!("{:?}", response);
+        if response.code != 200 {
+            return Err(Error::new(ErrorKind::NotFound, format!("bitget_swap 获取仓位异常{:?}", response).to_string()));
+        }
+
+        // 正常处理持仓信息
+        let mut positions: Vec<Position> = vec![];
+        if response.data.is_null() {
+            return Ok(positions);
+        }
+
+        let positions_json = response.data.as_array().unwrap();
+        for position_json in positions_json {
+            let symbol = position_json["symbol"].as_str().unwrap().to_string();
+            let margin_level = Decimal::from_str(position_json["leverage"].as_str().unwrap()).unwrap();
+            let amount = Decimal::from_str(position_json["total"].as_str().unwrap()).unwrap();
+            let frozen_amount = Decimal::from_str(position_json["locked"].as_str().unwrap()).unwrap();
+            let price = Decimal::from_str(position_json["openPriceAvg"].as_str().unwrap()).unwrap();
+            let profit = Decimal::from_str(position_json["unrealizedPL"].as_str().unwrap()).unwrap();
+            let position_mode = match position_json["posMode"].as_str().unwrap() {
+                "hedge_mode" => {
+                    match position_json["holdSide"].as_str().unwrap() {
+                        "short" => {
+                            PositionModeEnum::Short
+                        }
+                        "long" => {
+                            PositionModeEnum::Long
+                        }
+                        _ => {
+                            panic!("bitget_usdt_swap: 未知的持仓模式与持仓方向: {}, {}",
+                                   position_json["posMode"].as_str().unwrap(), position_json["holdSide"].as_str().unwrap())
+                        }
+                    }
+                }
+                "one_way_mode" => {
+                    PositionModeEnum::Both
+                }
+                _ => {
+                    panic!("bitget_usdt_swap: 未知的持仓模式: {}", position_json["posMode"].as_str().unwrap())
+                }
+            };
+            let margin = Decimal::from_str(position_json["marginSize"].as_str().unwrap()).unwrap();
+
+            positions.push(Position {
+                symbol,
+                margin_level,
+                amount,
+                frozen_amount,
+                price,
+                profit,
+                position_mode,
+                margin,
+            });
+        }
+
+        Ok(positions)
+    }
+
+    async fn get_positions(&mut self) -> Result<Vec<Position>, Error> {
+        let params = json!({
+            "productType": "USDT-FUTURES",
+            "marginCoin": "USDT"
+        });
+        let response = self.request.get_all_position(params).await;
+        info!(?response);
+
+        if response.code != 200 {
+            return Err(Error::new(ErrorKind::NotFound, format!("bitget_swap 获取仓位异常{:?}", response).to_string()));
+        }
+
+        // 正常处理持仓信息
+        let mut positions: Vec<Position> = vec![];
+        if response.data.is_null() {
+            return Ok(positions);
+        }
+
+        let positions_json = response.data.as_array().unwrap();
+        for position_json in positions_json {
+            let symbol = position_json["symbol"].as_str().unwrap().to_string();
+            let margin_level = Decimal::from_str(position_json["leverage"].as_str().unwrap()).unwrap();
+            let amount = Decimal::from_str(position_json["total"].as_str().unwrap()).unwrap();
+            let frozen_amount = Decimal::from_str(position_json["locked"].as_str().unwrap()).unwrap();
+            let price = Decimal::from_str(position_json["openPriceAvg"].as_str().unwrap()).unwrap();
+            let profit = Decimal::from_str(position_json["unrealizedPL"].as_str().unwrap()).unwrap();
+            let position_mode = match position_json["posMode"].as_str().unwrap() {
+                "hedge_mode" => {
+                    match position_json["holdSide"].as_str().unwrap() {
+                        "short" => {
+                            PositionModeEnum::Short
+                        }
+                        "long" => {
+                            PositionModeEnum::Long
+                        }
+                        _ => {
+                            panic!("bitget_usdt_swap: 未知的持仓模式与持仓方向: {}, {}",
+                                   position_json["posMode"].as_str().unwrap(), position_json["holdSide"].as_str().unwrap())
+                        }
+                    }
+                }
+                "one_way_mode" => {
+                    PositionModeEnum::Both
+                }
+                _ => {
+                    panic!("bitget_usdt_swap: 未知的持仓模式: {}", position_json["posMode"].as_str().unwrap())
+                }
+            };
+            let margin = Decimal::from_str(position_json["marginSize"].as_str().unwrap()).unwrap();
+
+            positions.push(Position {
+                symbol,
+                margin_level,
+                amount,
+                frozen_amount,
+                price,
+                profit,
+                position_mode,
+                margin,
+            });
+        }
+
+        Ok(positions)
+    }
+
+    async fn get_ticker(&mut self) -> Result<Ticker, Error> {
+        return self.get_ticker_symbol(self.symbol.clone()).await;
+    }
+
+    async fn get_record(&mut self, interval: String) -> Result<Vec<Record>, Error> {
+        let symbol_format = utils::format_symbol(self.symbol.clone(), "");
+
+        let params = json!({
+            "symbol": symbol_format.clone(),
+            "productType": "USDT-FUTURES",
+            "granularity": format!("{}m",interval),
+            "limit": "3"
+        });
+
+        let res_data = self.request.get_market_candles(params).await;
+        if res_data.code == 200 {
+            let mut records: Vec<Record> = vec![];
+            for record_value in res_data.data.as_array().unwrap() {
+                records.push(Record {
+                    time: Decimal::from_str(record_value[0].as_str().unwrap()).unwrap(),
+                    open: Decimal::from_str(record_value[1].as_str().unwrap()).unwrap(),
+                    high: Decimal::from_str(record_value[2].as_str().unwrap()).unwrap(),
+                    low: Decimal::from_str(record_value[3].as_str().unwrap()).unwrap(),
+                    close: Decimal::from_str(record_value[4].as_str().unwrap()).unwrap(),
+                    volume: Decimal::from_str(record_value[5].as_str().unwrap()).unwrap(),
+                    symbol: symbol_format.clone(),
+                });
+            }
+
+            records.reverse();
+            Ok(records)
+        } else {
+            Err(Error::new(ErrorKind::Other, res_data.to_string()))
+        }
+
+    }
+
+    async fn get_ticker_symbol(&mut self, symbol: String) -> Result<Ticker, Error> {
+        let symbol_format = utils::format_symbol(symbol.clone(), "");
+        let res_data = self.request.get_tickers(symbol_format).await;
+        if res_data.code == 200 {
+            let res_data_json = res_data.data;
+            let ticker_info = res_data_json[0].clone();
+            let time = Decimal::from_str(&*ticker_info["ts"].as_str().unwrap()).unwrap() / dec!(1000);
+            let result = Ticker {
+                time,
+                high: Decimal::from_str(ticker_info["high24h"].as_str().unwrap()).unwrap(),
+                low: Decimal::from_str(ticker_info["low24h"].as_str().unwrap()).unwrap(),
+                sell: Decimal::from_str(ticker_info["askPr"].as_str().unwrap()).unwrap(),
+                buy: Decimal::from_str(ticker_info["bidPr"].as_str().unwrap()).unwrap(),
+                last: Decimal::from_str(ticker_info["lastPr"].as_str().unwrap()).unwrap(),
+                volume: Decimal::from_str(ticker_info["quoteVolume"].as_str().unwrap()).unwrap(),
+                open_interest: Default::default(),
+            };
+            Ok(result)
+        } else {
+            Err(Error::new(ErrorKind::Other, res_data.to_string()))
+        }
+    }
+
+    async fn get_market(&mut self) -> Result<Market, Error> {
+        self.get_market_symbol(self.symbol.clone()).await
+    }
+
+    async fn get_market_symbol(&mut self, symbol: String) -> Result<Market, Error> {
+        let symbol_format = utils::format_symbol(symbol.clone(), "");
+        let response = self.request.get_contracts(symbol_format.clone()).await;
+
+        if response.code == 200 {
+            let res_data_json = response.data.as_array().unwrap();
+            let market_info = res_data_json[0].clone();
+
+            if !market_info["symbol"].as_str().unwrap().to_string().eq(&symbol_format) {
+                return Err(Error::new(ErrorKind::NotFound, format!("符号未找到:symbol={}, response={:?}", symbol_format, response))).unwrap();
+            }
+
+            let base_asset = market_info["baseCoin"].as_str().unwrap().to_string();
+            let quote_asset = market_info["quoteCoin"].as_str().unwrap().to_string();
+            let price_precision = Decimal::from_str(market_info["pricePlace"].as_str().unwrap()).unwrap();
+            let tick_size = Decimal::TEN.powd(Decimal::NEGATIVE_ONE * price_precision);
+            let amount_precision = Decimal::from_str(market_info["volumePlace"].as_str().unwrap()).unwrap();
+            let amount_size = Decimal::TEN.powd(Decimal::NEGATIVE_ONE * amount_precision);
+            let min_qty = Decimal::NEGATIVE_ONE;
+            let max_qty = Decimal::NEGATIVE_ONE;
+            // let multiplier = Decimal::from_str(&market_info["sizeMultiplier"].as_str().unwrap()).unwrap();
+            let multiplier = Decimal::ONE;
+
+            let result = Market {
+                symbol: format!("{}_{}", base_asset, quote_asset),
+                base_asset,
+                quote_asset,
+                tick_size,
+                amount_size,
+                price_precision,
+                amount_precision,
+                min_qty,
+                max_qty,
+                min_notional: min_qty,
+                max_notional: max_qty,
+                multiplier,
+            };
+            Ok(result)
+        } else {
+            Err(Error::new(ErrorKind::Other, response.to_string()))
+        }
+    }
+
+    async fn get_order_detail(&mut self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
+        let symbol_format = utils::format_symbol(self.symbol.clone(), "");
+        let params = json!({
+            "symbol": symbol_format,
+            "productType": "USDT-FUTURES",
+            "clientOid": custom_id,
+            "orderId": order_id
+        });
+
+        let multiplier = self.market.multiplier;
+        let response = self.request.get_order(params).await;
+        if response.code == 200 {
+            let res_data_json = response.data;
+            let result = format_order_item(res_data_json, multiplier);
+            Ok(result)
+        } else {
+            Err(Error::new(ErrorKind::Other, response.to_string()))
+        }
+    }
+
+    async fn get_orders_list(&mut self, _status: &str) -> Result<Vec<Order>, Error> {
+        Err(Error::new(ErrorKind::NotFound, "bitget_swap get_orders_list:该交易所方法未实现".to_string()))
+        // let symbol_format = utils::format_symbol(self.symbol.clone(), "");
+        // let multiplier = self.market.multiplier;
+        // let res_data = self.request.get_unfilled_orders(symbol_format.to_string(), "".to_string(), "".to_string(), "".to_string(), "100".to_string(), "".to_string()).await;
+        // if res_data.code == 200 {
+        //     let res_data_str = &res_data.data;
+        //     let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
+        //     let result = res_data_json.iter().map(|item| format_order_item(item.clone(), multiplier)).collect();
+        //     Ok(result)
+        // } else {
+        //     Err(Error::new(ErrorKind::Other, res_data.to_string()))
+        // }
+    }
+
+    async fn take_order(&mut self, custom_id: &str, origin_side: &str, price: Decimal, amount: Decimal) -> Result<Order, Error> {
+        let multiplier = self.market.multiplier;
+
+        return self.take_order_symbol(self.symbol.clone(), multiplier, custom_id, origin_side, price, amount).await;
+    }
+
+    async fn take_order_symbol(&mut self, symbol: String, multiplier: Decimal, custom_id: &str, origin_side: &str, price: Decimal, amount: Decimal) -> Result<Order, Error> {
+        let symbol_format = utils::format_symbol(symbol, "");
+        let final_size = amount / multiplier;
+        let mut params = json!({
+            "symbol": symbol_format,
+            "clientOid": custom_id,
+            "productType": "USDT-FUTURES",
+            "marginMode": "crossed",
+            "marginCoin": "USDT",
+            "size": final_size.to_string()
+        });
+        if price.eq(&Decimal::ZERO) {
+            params["orderType"] = json!("market");
+            params["force"] = json!("gtc");
+        } else {
+            params["price"] = json!(price.to_string());
+            params["orderType"] = json!("limit");
+            params["force"] = json!("gtc");
+        };
+        match origin_side {
+            "kd" => {
+                params["side"] = json!("buy");
+                params["reduceOnly"] = json!("NO");
+            }
+            "pd" => {
+                params["side"] = json!("sell");
+                params["reduceOnly"] = json!("YES");
+            }
+            "kk" => {
+                params["side"] = json!("sell");
+                params["reduceOnly"] = json!("NO");
+            }
+            "pk" => {
+                params["side"] = json!("buy");
+                params["reduceOnly"] = json!("YES");
+            }
+            _ => { panic!("bitget_usdt_swap 下单参数错误"); }
+        };
+        let res_data = self.request.swap_order(params).await;
+        if res_data.code != 200 {
+            return Err(Error::new(ErrorKind::Other, res_data.to_string()));
+        }
+
+        let res_data_json = res_data.data;
+        let result = Order {
+            id: res_data_json["orderId"].as_str().unwrap().to_string(),
+            custom_id: res_data_json["clientOid"].as_str().unwrap().to_string(),
+            price: Decimal::ZERO,
+            amount: Decimal::ZERO,
+            deal_amount: Decimal::ZERO,
+            avg_price: Decimal::ZERO,
+            status: "NEW".to_string(),
+            order_type: "".to_string(),
+            trace_stack: TraceStack::new(0, Instant::now()).on_special("328 bitget_swap".to_string()),
+        };
+        return Ok(result);
+    }
+
+    async fn cancel_order(&mut self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
+        let symbol_format = utils::format_symbol(self.symbol.clone(), "");
+        let params = json!({
+            "symbol": symbol_format,
+            "productType": "USDT-FUTURES",
+            "clientOid": custom_id,
+            "orderId": order_id
+        });
+        let response = self.request.cancel_order(params).await;
+
+        // 取消失败,进行报错
+        if response.code != 200 {
+            return Err(Error::new(ErrorKind::NotFound, response.to_string()));
+        }
+
+        let res_data_json = response.data;
+        let result = Order {
+            id: res_data_json["orderId"].as_str().unwrap().to_string(),
+            custom_id: res_data_json["clientOid"].as_str().unwrap().to_string(),
+            price: Decimal::ZERO,
+            amount: Decimal::ZERO,
+            deal_amount: Decimal::ZERO,
+            avg_price: Decimal::ZERO,
+            status: "REMOVE".to_string(),
+            order_type: "".to_string(),
+            trace_stack: TraceStack::new(0, Instant::now()).on_special("443 bitget_swap".to_string()),
+        };
+        Ok(result)
+    }
+
+    async fn cancel_orders(&mut self) -> Result<Vec<Order>, Error> {
+        Err(Error::new(ErrorKind::NotFound, "bitget_swap cancel_orders:该交易所方法未实现".to_string()))
+    }
+
+    async fn cancel_orders_all(&mut self) -> Result<Vec<Order>, Error> {
+        let response = self.request.get_pending_orders().await;
+        if response.code == 200 {
+            info!("{}", response.data.to_string());
+            let mut result = vec![];
+
+            if !response.data["entrustedList"].is_null() {
+                let orders_res_data_json = response.data["entrustedList"].as_array().unwrap();
+                for order in orders_res_data_json {
+                    let symbol = order["symbol"].as_str().unwrap().to_string();
+                    let order_id = order["orderId"].as_str().unwrap().to_string();
+                    let params = json!({
+                        "symbol": symbol,
+                        "productType": "USDT-FUTURES",
+                        "orderId": order_id,
+                    });
+                    let cancel_res_data = self.request.cancel_order(params).await;
+                    if cancel_res_data.code == 200 {
+                        let cancel_res_data_json = cancel_res_data.data;
+                        result.push(Order {
+                            id: cancel_res_data_json["orderId"].as_str().unwrap().to_string(),
+                            custom_id: cancel_res_data_json["clientOid"].as_str().unwrap().to_string(),
+                            price: Decimal::ZERO,
+                            amount: Decimal::ZERO,
+                            deal_amount: Decimal::ZERO,
+                            avg_price: Decimal::ZERO,
+                            status: "REMOVE".to_string(),
+                            order_type: "".to_string(),
+                            trace_stack: TraceStack::new(0, Instant::now()).on_special("457 bitget_swap".to_string()),
+                        });
+                    } else {
+                        return Err(Error::new(ErrorKind::Other, cancel_res_data.to_string()));
+                    }
+                }
+            }
+            Ok(result)
+        } else {
+            Err(Error::new(ErrorKind::Other, response.to_string()))
+        }
+    }
+
+    async fn take_stop_loss_order(&mut self, _stop_price: Decimal, _price: Decimal, _side: &str) -> Result<Value, Error> {
+        Err(Error::new(ErrorKind::NotFound, "bitget_swap take_stop_loss_order:该交易所方法未实现".to_string()))
+    }
+
+    async fn cancel_stop_loss_order(&mut self, _order_id: &str) -> Result<Value, Error> {
+        Err(Error::new(ErrorKind::NotFound, "bitget_swap cancel_stop_loss_order:该交易所方法未实现".to_string()))
+    }
+
+    async fn set_dual_mode(&mut self, _coin: &str, is_dual_mode: bool) -> Result<String, Error> {
+        let pos_mode = if is_dual_mode {
+            "hedge_mode"
+        } else {
+            "one_way_mode"
+        };
+        let params = json!({
+            "productType": "USDT-FUTURES",
+            "posMode": pos_mode,
+        });
+        let response = self.request.set_position_mode(params).await;
+
+        if response.code != 200 {
+            return Err(Error::new(ErrorKind::Other, format!("设置持仓模式失败:{:?}", response).to_string()));
+        }
+
+        return Ok(response.data.to_string());
+    }
+
+    async fn set_dual_leverage(&mut self, leverage: &str) -> Result<String, Error> {
+        let symbol_format = utils::format_symbol(self.symbol.clone(), "");
+        let params = json!({
+            "symbol": symbol_format,
+            "productType": "USDT-FUTURES",
+            "marginCoin": "USDT",
+            "leverage": leverage
+        });
+        let response = self.request.set_leverage(params).await;
+
+        if response.code != 200 {
+            return Err(Error::new(ErrorKind::Other, format!("设置杠杆失败:{:?}", response).to_string()));
+        }
+
+        return Ok(response.data.to_string());
+    }
+
+    async fn set_auto_deposit_status(&mut self, _status: bool) -> Result<String, Error> {
+        Err(Error::new(ErrorKind::NotFound, "bitget_swap set_auto_deposit_status:该交易所方法未实现".to_string()))
+    }
+
+    async fn wallet_transfers(&mut self, _coin: &str, _from: &str, _to: &str, _amount: Decimal) -> Result<String, Error> {
+        Err(Error::new(ErrorKind::NotFound, "bitget_swap wallet_transfers:该交易所方法未实现".to_string()))
+        // let coin_format = coin.to_string().to_uppercase();
+        // let res_data = self.request.wallet_transfer(from.to_string(), to.to_string(), amount.to_string(), coin_format.clone(), "".to_string(), "".to_string()).await;
+        // if res_data.code == 200 {
+        //     let res_data_str = &res_data.data;
+        //     let result = res_data_str.clone();
+        //     Ok(result)
+        // } else {
+        //     Err(Error::new(ErrorKind::Other, res_data.to_string()))
+        // }
+    }
+
+    async fn command_order(&mut self, order_command: &mut OrderCommand, trace_stack: &TraceStack) {
+        let mut handles = vec![];
+
+        // 下单指令
+        for item in order_command.limits_open.keys() {
+            let mut ts = trace_stack.clone();
+
+            let amount = Decimal::from_str(&*order_command.limits_open[item].get(0).unwrap().clone()).unwrap();
+            let side = order_command.limits_open[item].get(1).unwrap().clone();
+            let price = Decimal::from_str(&*order_command.limits_open[item].get(2).unwrap().clone()).unwrap();
+            let cid = order_command.limits_open[item].get(3).unwrap().clone();
+
+            //  order_name: [数量,方向,价格,c_id]
+            let mut self_clone = self.clone();
+            let handle = spawn(async move {
+                // TraceStack::show_delay(&ts.ins);
+                ts.on_before_send();
+                let result = self_clone.take_order(cid.as_str(), side.as_str(), price, amount).await;
+                ts.on_after_send();
+
+                match result {
+                    Ok(mut result) => {
+                        result.trace_stack = ts;
+
+                        self_clone.order_sender.send(result).await.unwrap();
+                    }
+                    Err(error) => {
+                        info!(?error);
+                        let mut err_order = Order::new();
+                        err_order.custom_id = cid.clone();
+                        err_order.status = "REMOVE".to_string();
+
+                        self_clone.order_sender.send(err_order).await.unwrap();
+                        self_clone.error_sender.send(error).await.unwrap();
+                    }
+                }
+            });
+            handles.push(handle)
+        }
+        let futures = FuturesUnordered::from_iter(handles);
+        // 等待所有任务完成
+        let _: Result<Vec<_>, _> = futures.try_collect().await;
+
+        // 撤销订单
+        let mut cancel_handlers = vec![];
+        for item in order_command.cancel.keys() {
+            let order_id = order_command.cancel[item].get(1).unwrap().clone();
+            let custom_id = order_command.cancel[item].get(0).unwrap().clone();
+
+            let mut self_clone = self.clone();
+            let handle = spawn(async move {
+                let result = self_clone.cancel_order(&order_id, &custom_id).await;
+                match result {
+                    Ok(_) => {
+                        // result_sd.send(result).await.unwrap();
+                    }
+                    Err(error) => {
+                        // 取消失败去查订单。
+                        let query_rst = self_clone.get_order_detail(&order_id, &custom_id).await;
+                        match query_rst {
+                            Ok(order) => {
+                                self_clone.order_sender.send(order).await.unwrap();
+                            }
+                            Err(err) => {
+                                error!("撤单失败,而且查单也失败了,bitget_swap,oid={}, cid={}, err={:?}。", order_id.clone(), custom_id.clone(), err);
+                            }
+                        }
+                        self_clone.error_sender.send(error).await.unwrap();
+                    }
+                }
+            });
+            cancel_handlers.push(handle)
+        }
+        let futures = FuturesUnordered::from_iter(cancel_handlers);
+        // 等待所有任务完成
+        let _: Result<Vec<_>, _> = futures.try_collect().await;
+
+        // 检查订单指令
+        let mut check_handlers = vec![];
+        for item in order_command.check.keys() {
+            let order_id = order_command.check[item].get(1).unwrap().clone();
+            let custom_id = order_command.check[item].get(0).unwrap().clone();
+
+            let mut self_clone = self.clone();
+            let handle = spawn(async move {
+                let result = self_clone.get_order_detail(order_id.as_str(), custom_id.as_str()).await;
+                match result {
+                    Ok(result) => {
+                        self_clone.order_sender.send(result).await.unwrap();
+                    }
+                    Err(error) => {
+                        self_clone.error_sender.send(error).await.unwrap();
+                    }
+                }
+            });
+            check_handlers.push(handle)
+        }
+
+        let futures = FuturesUnordered::from_iter(check_handlers);
+        // 等待所有任务完成
+        let _: Result<Vec<_>, _> = futures.try_collect().await;
+    }
+}
+
+// pub fn format_account_info(balance_data: Value) -> Account {
+//     let balance_coin = balance_data["coin"].as_str().unwrap().to_string().to_uppercase();
+//     let available_balance = Decimal::from_str(balance_data["available"].as_str().unwrap()).unwrap();
+//     let frozen_balance = Decimal::from_str(balance_data["frozen"].as_str().unwrap()).unwrap();
+//     let balance = available_balance + frozen_balance;
+//
+//     Account {
+//         coin: balance_coin,
+//         balance,
+//         available_balance,
+//         frozen_balance,
+//         stocks: Decimal::ZERO,
+//         available_stocks: Decimal::ZERO,
+//         frozen_stocks: Decimal::ZERO,
 //     }
 // }
+
+pub fn format_order_item(order: Value, multiplier: Decimal) -> Order {
+    let price = Decimal::from_str(order["price"].as_str().unwrap_or(order["priceAvg"].as_str().unwrap())).unwrap();
+    let size = Decimal::from_str(order["size"].as_str().unwrap()).unwrap();
+    let status = order["state"].as_str().unwrap();
+    let base_volume = Decimal::from_str(order["quoteVolume"].as_str().unwrap()).unwrap();
+    let avg_price = if order["priceAvg"].is_null() || order["priceAvg"].as_str().unwrap().is_empty() {
+        Decimal::ZERO
+    } else {
+        Decimal::from_str(order["priceAvg"].as_str().unwrap().to_string().as_str()).unwrap()
+    };
+
+    let amount = size * multiplier;
+    let deal_amount = base_volume * multiplier;
+    let custom_status = if ["filled", "canceled"].contains(&status) {
+        "REMOVE".to_string()
+    } else if ["init", "live", "new", "partially_filled"].contains(&status) {
+        "NEW".to_string()
+    } else {
+        "NULL".to_string()
+    };
+    Order {
+        id: order["orderId"].as_str().unwrap().to_string(),
+        custom_id: order["clientOid"].as_str().unwrap().to_string(),
+        price,
+        amount,
+        deal_amount,
+        avg_price,
+        status: custom_status,
+        order_type: order["orderType"].as_str().unwrap().to_string(),
+        trace_stack: TraceStack::new(0, Instant::now()).on_special("700 bitget_swap".to_string()),
+    }
+}

+ 217 - 220
standard/src/bitget_swap_handle.rs

@@ -1,224 +1,221 @@
-// use std::str::FromStr;
-// use rust_decimal::Decimal;
-// use rust_decimal::prelude::FromPrimitive;
-// use serde_json::Value;
-// use exchanges::response_base::ResponseData;
-// use crate::{Account, OrderBook, Order, Position, PositionModeEnum, SpecialOrder, Trade, Record};
-//
-// // 处理账号信息
-// pub fn handle_account_info(response: &ResponseData, _symbol: &String) -> Account {
-//     let mut rst = Account::new();
-//
-//     for data in response.data.as_array().unwrap() {
-//         if data["marginCoin"].as_str().unwrap() != "USDT" {
-//             continue
-//         }
-//
-//         // 格式化account信息
-//         let mut account = Account {
-//             coin: data["marginCoin"].to_string(),
-//             balance: Decimal::from_str(data["usdtEquity"].as_str().unwrap()).unwrap(),
-//             available_balance: Decimal::from_str(data["available"].as_str().unwrap()).unwrap(),
-//             frozen_balance: Decimal::from_str(data["frozen"].as_str().unwrap()).unwrap(),
-//             stocks: Default::default(),
-//             available_stocks: Default::default(),
-//             frozen_stocks: Default::default(),
-//         };
-//         account.frozen_balance = account.balance - account.available_balance;
-//
-//         rst = account
-//     }
-//
-//     return rst;
-// }
-//
-// // 处理order信息
-// pub fn handle_order(res_data: &ResponseData, ct_val: Decimal) -> SpecialOrder {
-//     let res_data_json = res_data.data.as_array().unwrap();
-//     let mut order_info = Vec::new();
-//     for item in res_data_json.iter() {
-//         order_info.push(format_order_item(item.clone(), ct_val));
-//     }
-//     SpecialOrder {
-//         name: res_data.label.clone(),
-//         order: order_info,
-//     }
-// }
-//
-// // 处理订单信息
-// pub fn format_order_item(order: Value, ct_val: Decimal) -> Order {
-//     let price = Decimal::from_str(order["price"].as_str().unwrap().to_string().as_str()).unwrap();
-//     let size = Decimal::from_str(order["size"].as_str().unwrap().to_string().as_str()).unwrap();
-//     let binding = order["status"].clone().as_str().unwrap().to_string();
-//     let status = binding.as_str();
-//     let acc_base_volume = Decimal::from_str(order["accBaseVolume"].as_str().unwrap().to_string().as_str()).unwrap();
-//     let avg_price = if order["priceAvg"].is_null() || order["priceAvg"].as_str().unwrap().is_empty() {
-//         Decimal::ZERO
-//     } else {
-//         Decimal::from_str(order["priceAvg"].as_str().unwrap().to_string().as_str()).unwrap()
-//     };
-//     let c_id = if order["clientOid"].is_null() {
-//         ""
-//     } else {
-//         order["clientOid"].as_str().unwrap()
-//     };
-//
-//     let amount = size * ct_val;
-//     let deal_amount = acc_base_volume * ct_val;
-//     let custom_status = if ["filled", "canceled"].contains(&status) {
-//         "REMOVE".to_string()
-//     } else if ["init", "live", "new", "partially_filled"].contains(&status) {
-//         "NEW".to_string()
-//     } else {
-//         "NULL".to_string()
-//     };
-//     Order {
-//         id: order["orderId"].as_str().unwrap().to_string(),
-//         custom_id: c_id.to_string(),
-//         price,
-//         amount,
-//         deal_amount,
-//         avg_price,
-//         status: custom_status,
-//         order_type: order["orderType"].as_str().unwrap().to_string()
-//     }
-// }
-//
-// // 格式化深度信息
-// pub fn format_depth_items(value: Value) -> Vec<OrderBook> {
-//     let mut depth_items: Vec<OrderBook> = vec![];
-//     for value in value.as_array().unwrap() {
-//         depth_items.push(OrderBook {
-//             price: Decimal::from_str(value[0].as_str().unwrap()).unwrap(),
-//             amount: Decimal::from_str(value[1].as_str().unwrap()).unwrap(),
-//         })
-//     }
-//     return depth_items;
+use std::str::FromStr;
+use rust_decimal::Decimal;
+use rust_decimal::prelude::FromPrimitive;
+use serde_json::Value;
+use tokio::time::Instant;
+use tracing::error;
+use exchanges::response_base::ResponseData;
+use global::trace_stack::TraceStack;
+use crate::{Account, OrderBook, Order, Position, PositionModeEnum, SpecialOrder, Depth, Trade, Ticker, Record};
+
+// 处理账号信息
+pub fn handle_account_info(response: &ResponseData, _symbol: &String) -> Account {
+    let mut rst = Account::new();
+
+    for data in response.data.as_array().unwrap() {
+        if data["marginCoin"].as_str().unwrap() != "USDT" {
+            continue
+        }
+
+        // 格式化account信息
+        let mut account = Account {
+            coin: data["marginCoin"].to_string(),
+            balance: Decimal::from_str(data["usdtEquity"].as_str().unwrap()).unwrap(),
+            available_balance: Decimal::from_str(data["available"].as_str().unwrap()).unwrap(),
+            frozen_balance: Decimal::from_str(data["frozen"].as_str().unwrap()).unwrap(),
+            stocks: Default::default(),
+            available_stocks: Default::default(),
+            frozen_stocks: Default::default(),
+        };
+        account.frozen_balance = account.balance - account.available_balance;
+
+        rst = account
+    }
+
+    return rst;
+}
+
+// 处理order信息
+pub fn handle_order(res_data: ResponseData, ct_val: Decimal) -> SpecialOrder {
+    let res_data_json = res_data.data.as_array().unwrap();
+    let mut order_info = Vec::new();
+    for item in res_data_json.iter() {
+        order_info.push(format_order_item(item.clone(), ct_val));
+    }
+    SpecialOrder {
+        name: res_data.label,
+        order: order_info,
+    }
+}
+
+// 处理订单信息
+pub fn format_order_item(order: Value, ct_val: Decimal) -> Order {
+    let price = Decimal::from_str(order["price"].as_str().unwrap().to_string().as_str()).unwrap();
+    let size = Decimal::from_str(order["size"].as_str().unwrap().to_string().as_str()).unwrap();
+    let binding = order["status"].clone().as_str().unwrap().to_string();
+    let status = binding.as_str();
+    let acc_base_volume = Decimal::from_str(order["accBaseVolume"].as_str().unwrap().to_string().as_str()).unwrap();
+    let avg_price = if order["priceAvg"].is_null() || order["priceAvg"].as_str().unwrap().is_empty() {
+        Decimal::ZERO
+    } else {
+        Decimal::from_str(order["priceAvg"].as_str().unwrap().to_string().as_str()).unwrap()
+    };
+    let c_id = if order["clientOid"].is_null() {
+        ""
+    } else {
+        order["clientOid"].as_str().unwrap()
+    };
+
+    let amount = size * ct_val;
+    let deal_amount = acc_base_volume * ct_val;
+    let custom_status = if ["filled", "canceled"].contains(&status) {
+        "REMOVE".to_string()
+    } else if ["init", "live", "new", "partially_filled"].contains(&status) {
+        "NEW".to_string()
+    } else {
+        "NULL".to_string()
+    };
+    Order {
+        id: order["orderId"].as_str().unwrap().to_string(),
+        custom_id: c_id.to_string(),
+        price,
+        amount,
+        deal_amount,
+        avg_price,
+        status: custom_status,
+        order_type: order["orderType"].as_str().unwrap().to_string(),
+        trace_stack: TraceStack::new(0, Instant::now()).on_special("86 bitget_swap_handle".to_string()),
+    }
+}
+
+// 格式化深度信息
+pub fn format_depth_items(value: Value, mul: &Decimal) -> Vec<OrderBook> {
+    let mut depth_items: Vec<OrderBook> = vec![];
+    for value in value.as_array().unwrap() {
+        let price = Decimal::from_str(value[0].as_str().unwrap()).unwrap();
+        let size = Decimal::from_str(value[1].as_str().unwrap()).unwrap();
+        depth_items.push(OrderBook {
+            price,
+            size,
+            value: price * size * mul,
+        })
+    }
+    return depth_items;
+}
+
+// 处理position信息
+pub fn handle_position(res_data: &ResponseData, ct_val: &Decimal) -> Vec<Position> {
+    let res_data_json = res_data.data.as_array().unwrap();
+    res_data_json.iter().map(|item| { format_position_item(item, ct_val) }).collect()
+}
+
+pub fn format_position_item(position_json: &Value, ct_val: &Decimal) -> Position {
+    let symbol = position_json["instId"].as_str().unwrap().to_string();
+    let margin_level = Decimal::from_i64(position_json["leverage"].as_i64().unwrap()).unwrap();
+    let amount = Decimal::from_str(position_json["total"].as_str().unwrap()).unwrap() * ct_val;
+    let frozen_amount = Decimal::from_str(position_json["frozen"].as_str().unwrap()).unwrap() * ct_val;
+    let price = Decimal::from_str(position_json["openPriceAvg"].as_str().unwrap()).unwrap();
+    let profit = Decimal::from_str(position_json["unrealizedPL"].as_str().unwrap()).unwrap();
+    let position_mode = match position_json["posMode"].as_str().unwrap() {
+        "hedge_mode" => {
+            match position_json["holdSide"].as_str().unwrap() {
+                "short" => {
+                    PositionModeEnum::Short
+                }
+                "long" => {
+                    PositionModeEnum::Long
+                },
+                _ => {
+                    panic!("bitget_usdt_swap: 未知的持仓模式与持仓方向: {}, {}",
+                           position_json["posMode"].as_str().unwrap(), position_json["holdSide"].as_str().unwrap())
+                }
+            }
+        },
+        "one_way_mode" => {
+            PositionModeEnum::Both
+        },
+        _ => {
+            panic!("bitget_usdt_swap: 未知的持仓模式: {}", position_json["posMode"].as_str().unwrap())
+        }
+    };
+    let margin = Decimal::from_str(position_json["marginSize"].as_str().unwrap()).unwrap();
+
+    Position {
+        symbol,
+        margin_level,
+        amount,
+        frozen_amount,
+        price,
+        profit,
+        position_mode,
+        margin,
+    }
+}
+
+pub fn format_trade_items(response: &ResponseData) -> Vec<Trade> {
+    let result = response.data.as_array().unwrap();
+    let mut trades = vec![];
+
+    for item in result {
+        // 因为gate的量都是张数,所以要进行真实交易量处理
+        let mut size = Decimal::from_str(item["v"].as_str().unwrap()).unwrap();
+        let price = Decimal::from_str(item["p"].as_str().unwrap().to_string().as_str()).unwrap();
+        let side = item["S"].as_str().unwrap().to_string();
+        size = match side.as_str() {
+            "Buy" => {
+                size
+            }
+            "Sell" => {
+                -size
+            }
+            _ => {
+                error!("{}", item.to_string());
+                panic!("Bitget trade error side(bitget_swap_handle_156)")
+            }
+        };
+        let value = (size * price).abs();
+
+        trades.push(Trade {
+            id: item["i"].as_str().unwrap().to_string(),
+            time: Decimal::from_i64(item["T"].as_i64().unwrap()).unwrap(),
+            size,
+            price,
+            value,
+            symbol: item["s"].as_str().unwrap().to_string(),
+        })
+    }
+
+    return trades
+}
+
+// 处理特殊深度数据
+// pub fn handle_special_depth(res_data: ResponseData) -> SpecialDepth {
+//     HandleSwapInfo::handle_special_depth(ExchangeEnum::BitgetSwap, res_data)
 // }
-//
-// // 处理position信息
-// pub fn handle_position(res_data: &ResponseData, ct_val: &Decimal) -> Vec<Position> {
-//     let res_data_json = res_data.data.as_array().unwrap();
-//     res_data_json.iter().map(|item| { format_position_item(item, ct_val) }).collect()
+
+// // 处理特殊Ticker信息
+// pub fn handle_special_ticker(res_data: ResponseData) -> SpecialDepth {
+//     let res_data_str = res_data.data;
+//     let res_data_json: Vec<serde_json::Value> = serde_json::from_str(&*res_data_str).unwrap();
+//     format_special_ticker(res_data_json[0].clone(), res_data.label)
 // }
 //
-// pub fn format_position_item(position_json: &Value, ct_val: &Decimal) -> Position {
-//     let symbol = position_json["instId"].as_str().unwrap().to_string();
-//     let margin_level = Decimal::from_i64(position_json["leverage"].as_i64().unwrap()).unwrap();
-//     let amount = Decimal::from_str(position_json["total"].as_str().unwrap()).unwrap() * ct_val;
-//     let frozen_amount = Decimal::from_str(position_json["frozen"].as_str().unwrap()).unwrap() * ct_val;
-//     let price = Decimal::from_str(position_json["openPriceAvg"].as_str().unwrap()).unwrap();
-//     let profit = Decimal::from_str(position_json["unrealizedPL"].as_str().unwrap()).unwrap();
-//     let position_mode = match position_json["posMode"].as_str().unwrap() {
-//         "hedge_mode" => {
-//             match position_json["holdSide"].as_str().unwrap() {
-//                 "short" => {
-//                     PositionModeEnum::Short
-//                 }
-//                 "long" => {
-//                     PositionModeEnum::Long
-//                 },
-//                 _ => {
-//                     panic!("bitget_usdt_swap: 未知的持仓模式与持仓方向: {}, {}",
-//                            position_json["posMode"].as_str().unwrap(), position_json["holdSide"].as_str().unwrap())
-//                 }
-//             }
-//         },
-//         "one_way_mode" => {
-//             PositionModeEnum::Both
-//         },
-//         _ => {
-//             panic!("bitget_usdt_swap: 未知的持仓模式: {}", position_json["posMode"].as_str().unwrap())
-//         }
-//     };
-//     let margin = Decimal::from_str(position_json["marginSize"].as_str().unwrap()).unwrap();
-//
-//     Position {
-//         symbol,
-//         margin_level,
-//         amount,
-//         frozen_amount,
-//         price,
-//         profit,
-//         position_mode,
-//         margin,
+// pub fn format_special_ticker(data: serde_json::Value, label: String) -> SpecialDepth {
+//     let bp = Decimal::from_str(data["bidPr"].as_str().unwrap()).unwrap();
+//     let bq = Decimal::from_str(data["bidSz"].as_str().unwrap()).unwrap();
+//     let ap = Decimal::from_str(data["askPr"].as_str().unwrap()).unwrap();
+//     let aq = Decimal::from_str(data["askSz"].as_str().unwrap()).unwrap();
+//     let mp = (bp + ap) * dec!(0.5);
+//     let t = Decimal::from_str(data["ts"].as_str().unwrap()).unwrap();
+//     let create_at = data["ts"].as_str().unwrap().parse::<i64>().unwrap() * 1000;
+//
+//     let ticker_info = SpecialTicker { sell: ap, buy: bp, mid_price: mp, t, create_at };
+//     let depth_info = vec![bp, bq, ap, aq];
+//     SpecialDepth {
+//         name: label,
+//         depth: depth_info,
+//         ticker: ticker_info,
+//         t,
+//         create_at,
 //     }
-// }
-//
-// pub fn format_trade_items(res_data: &ResponseData) -> Vec<Trade> {
-//     let arg = res_data.data["arg"].clone();
-//     let symbol = arg["instId"].as_str().unwrap().to_string().replace("USDT", "_USDT");
-//     let result = res_data.data["data"].as_array().unwrap();
-//     let mut trades = vec![];
-//
-//     for item in result {
-//         let mut trade = Trade {
-//             id: item["tradeId"].as_str().unwrap().to_string(),
-//             time: Decimal::from_str(item["ts"].as_str().unwrap()).unwrap(),
-//             size: Decimal::from_str(item["size"].as_str().unwrap()).unwrap(),
-//             price: Decimal::from_str(item["price"].as_str().unwrap().to_string().as_str()).unwrap(),
-//             symbol: symbol.to_string(),
-//         };
-//
-//         if item["side"].as_str().unwrap().eq("sell") {
-//             trade.size = trade.size * Decimal::NEGATIVE_ONE;
-//         }
-//
-//         trades.push(trade)
-//     }
-//
-//     return trades
-// }
-//
-// pub fn handle_records(value: &Value) -> Vec<Record> {
-//     let mut records = vec![];
-//
-//     let record_value_vec = value["data"].as_array().unwrap();
-//     let symbol = value["arg"]["instId"].as_str().unwrap().to_string().replace("USDT", "_USDT");
-//     for record_value in record_value_vec {
-//         let arr = record_value.as_array().unwrap();
-//         records.push(Record {
-//             time: Decimal::from_str(arr[0].as_str().unwrap()).unwrap(),
-//             open: Decimal::from_str(arr[1].as_str().unwrap()).unwrap(),
-//             high: Decimal::from_str(arr[2].as_str().unwrap()).unwrap(),
-//             low: Decimal::from_str(arr[3].as_str().unwrap()).unwrap(),
-//             close: Decimal::from_str(arr[4].as_str().unwrap()).unwrap(),
-//             volume: Decimal::from_str(arr[6].as_str().unwrap()).unwrap(),
-//             symbol: symbol.clone(),
-//         });
-//     }
-//
-//     return records
-// }
-//
-// // 处理特殊深度数据
-// // pub fn handle_special_depth(res_data: ResponseData) -> SpecialDepth {
-// //     HandleSwapInfo::handle_special_depth(ExchangeEnum::BitgetSwap, res_data)
-// // }
-//
-// // // 处理特殊Ticker信息
-// // pub fn handle_special_ticker(res_data: ResponseData) -> SpecialDepth {
-// //     let res_data_str = res_data.data;
-// //     let res_data_json: Vec<serde_json::Value> = serde_json::from_str(&*res_data_str).unwrap();
-// //     format_special_ticker(res_data_json[0].clone(), res_data.tag)
-// // }
-// //
-// // pub fn format_special_ticker(data: serde_json::Value, tag: String) -> SpecialDepth {
-// //     let bp = Decimal::from_str(data["bidPr"].as_str().unwrap()).unwrap();
-// //     let bq = Decimal::from_str(data["bidSz"].as_str().unwrap()).unwrap();
-// //     let ap = Decimal::from_str(data["askPr"].as_str().unwrap()).unwrap();
-// //     let aq = Decimal::from_str(data["askSz"].as_str().unwrap()).unwrap();
-// //     let mp = (bp + ap) * dec!(0.5);
-// //     let t = Decimal::from_str(data["ts"].as_str().unwrap()).unwrap();
-// //     let create_at = data["ts"].as_str().unwrap().parse::<i64>().unwrap() * 1000;
-// //
-// //     let ticker_info = SpecialTicker { sell: ap, buy: bp, mid_price: mp, t, create_at };
-// //     let depth_info = vec![bp, bq, ap, aq];
-// //     SpecialDepth {
-// //         name: tag,
-// //         depth: depth_info,
-// //         ticker: ticker_info,
-// //         t,
-// //         create_at,
-// //     }
-// // }
+// }

+ 1 - 1
standard/src/bybit_swap.rs

@@ -89,7 +89,7 @@ impl Platform for BybitSwap {
     fn clone_box(&self) -> Box<dyn Platform + Send + Sync> { Box::new(self.clone()) }
     // 获取交易所模式
     fn get_self_exchange(&self) -> ExchangeEnum {
-        ExchangeEnum::GateSwap
+        ExchangeEnum::BybitSwap
     }
     // 获取交易对
     fn get_self_symbol(&self) -> String { self.symbol.clone() }

+ 5 - 4
standard/src/exchange.rs

@@ -3,6 +3,7 @@ use std::io::Error;
 use tokio::sync::mpsc::Sender;
 use crate::{Order, Platform};
 use crate::binance_swap::BinanceSwap;
+use crate::bitget_swap::BitgetSwap;
 use crate::bybit_swap::BybitSwap;
 use crate::coinex_swap::CoinexSwap;
 use crate::gate_swap::GateSwap;
@@ -24,7 +25,7 @@ pub enum ExchangeEnum {
     // KucoinSpot,
     // OkxSwap,
     // BitgetSpot,
-    // BitgetSwap,
+    BitgetSwap,
     BybitSwap,
     // HtxSwap,
     // BingxSwap,
@@ -99,9 +100,9 @@ impl Exchange {
             // ExchangeEnum::BitgetSpot => {
             //     Box::new(BitgetSpot::new(symbol, is_colo, params, order_sender, error_sender).await)
             // }
-            // ExchangeEnum::BitgetSwap => {
-            //     Box::new(BitgetSwap::new(symbol, is_colo, params, order_sender, error_sender).await)
-            // }
+            ExchangeEnum::BitgetSwap => {
+                Box::new(BitgetSwap::new(symbol, is_colo, params, order_sender, error_sender).await)
+            }
             ExchangeEnum::BybitSwap => {
                 Box::new(BybitSwap::new(symbol, is_colo, params, order_sender, error_sender).await)
             }

+ 4 - 4
standard/src/exchange_struct_handler.rs

@@ -4,7 +4,7 @@ use rust_decimal::prelude::FromPrimitive;
 use tracing::error;
 use exchanges::response_base::ResponseData;
 use crate::exchange::ExchangeEnum;
-use crate::{binance_swap_handle, bybit_swap_handle, coinex_swap_handle, gate_swap_handle, Ticker};
+use crate::{binance_swap_handle, bitget_swap_handle, bybit_swap_handle, coinex_swap_handle, gate_swap_handle, Ticker};
 use crate::{Record, Trade, Depth};
 use crate::{Account, OrderBook, Position, SpecialOrder};
 
@@ -109,9 +109,9 @@ impl ExchangeStructHandler {
             // ExchangeEnum::GateSpot => {
             //     gate_spot_handle::format_trade_items(&res_data)
             // }
-            // ExchangeEnum::BitgetSwap => {
-            //     bitget_swap_handle::format_trade_items(&res_data)
-            // }
+            ExchangeEnum::BitgetSwap => {
+                bitget_swap_handle::format_trade_items(&res_data)
+            }
             ExchangeEnum::BinanceSwap => {
                 binance_swap_handle::format_trade_items(&res_data)
             }

+ 255 - 0
standard/tests/bitget_swap_test.rs

@@ -0,0 +1,255 @@
+mod exchange_test;
+
+use std::collections::BTreeMap;
+use std::env;
+use std::io::Error;
+use rust_decimal_macros::dec;
+use tokio::sync::mpsc;
+use tracing::{instrument, trace};
+use standard::exchange::{Exchange, ExchangeEnum};
+use standard::{Order, OrderCommand, Platform, utils};
+use crate::exchange_test::{test_new_exchange};
+
+const SYMBOL: &str = "XTZ_USDT";
+
+// 测试获取Exchange实体
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_self_exchange() {
+    global::log_utils::init_log_with_trace();
+
+    let bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_self_exchange = bitget_swap_exchange.get_self_exchange();
+    trace!(?bitget_get_self_exchange);
+}
+
+// 测试获取交易对信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_self_symbol() {
+    global::log_utils::init_log_with_trace();
+
+    let bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_self_symbol = bitget_swap_exchange.get_self_symbol();
+    trace!(?bitget_get_self_symbol);
+}
+
+// 测试获取是否使用高速通道
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_self_is_colo() {
+    global::log_utils::init_log_with_trace();
+
+    let bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_self_is_colo = bitget_swap_exchange.get_self_is_colo();
+    trace!(?bitget_get_self_is_colo);
+}
+
+// 测试获取登录params信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_self_params() {
+    global::log_utils::init_log_with_trace();
+
+    let bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_self_params = bitget_swap_exchange.get_self_params();
+    trace!("bitget_get_self_params={:?}",bitget_get_self_params);
+}
+
+// 测试获取Market信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_self_market() {
+    global::log_utils::init_log_with_trace();
+
+    let bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_self_market = bitget_swap_exchange.get_self_market();
+    trace!(?bitget_get_self_market);
+}
+
+// 测试获取请求时间信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_request_delays() {
+    global::log_utils::init_log_with_trace();
+
+    let bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_request_delays = bitget_swap_exchange.get_request_delays();
+    trace!(?bitget_get_request_delays);
+}
+
+// 测试获取请求平均时间信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_request_avg_delay() {
+    global::log_utils::init_log_with_trace();
+
+    let bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_request_avg_delay = bitget_swap_exchange.get_request_avg_delay();
+    trace!(?bitget_get_request_avg_delay);
+}
+
+// 测试获取最大请求时间信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_request_max_delay() {
+    global::log_utils::init_log_with_trace();
+
+    let bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_request_max_delay = bitget_swap_exchange.get_request_max_delay();
+    trace!(?bitget_get_request_max_delay);
+}
+
+// 测试获取服务器时间
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_server_time() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_server_time = bitget_swap_exchange.get_server_time().await;
+    trace!(?bitget_get_server_time);
+}
+
+// 测试获取账号信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_account() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_account = bitget_swap_exchange.get_account().await;
+    trace!(?bitget_get_account);
+}
+
+// 测试获取持仓信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_position() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_position = bitget_swap_exchange.get_position().await;
+    trace!(?bitget_get_position);
+}
+
+// 测试获取所有持仓信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_positions() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_positions = bitget_swap_exchange.get_positions().await;
+    trace!(?bitget_get_positions);
+}
+
+// 测试获取Ticker信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_ticker() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_ticker = bitget_swap_exchange.get_ticker().await;
+    trace!(?bitget_get_ticker);
+}
+
+// 测试获取Market信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_market() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_market = bitget_swap_exchange.get_market().await;
+    trace!(?bitget_get_market);
+}
+
+// 测试获取Kline信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_record() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_market = bitget_swap_exchange.get_record("3".to_string()).await;
+    trace!(?bitget_get_market);
+}
+
+// 测试获取Order详情信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_order_detail() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_order_detail = bitget_swap_exchange.get_order_detail("", "999993").await;
+    trace!(?bitget_get_order_detail);
+}
+
+// 测试获取Order列表信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_orders_list() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_get_orders_list = bitget_swap_exchange.get_orders_list("finished").await;
+    trace!(?bitget_get_orders_list);
+}
+
+// 测试下单
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_take_order() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_take_order = bitget_swap_exchange.take_order("999994", "pd", dec!(0), dec!(7)).await;
+    trace!(?bitget_take_order);
+}
+
+// 测试撤销订单
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_cancel_order() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_cancel_order = bitget_swap_exchange.cancel_order("", "999992").await;
+    trace!(?bitget_cancel_order);
+}
+
+// 测试批量撤销订单
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_cancel_orders() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_cancel_orders = bitget_swap_exchange.cancel_orders().await;
+    trace!(?bitget_cancel_orders);
+}
+
+// 测试设置持仓模式
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_set_dual_mode() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_set_dual_mode = bitget_swap_exchange.set_dual_mode("usdt", true).await;
+    trace!(?bitget_set_dual_mode);
+}
+
+// 测试设置杠杆
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_set_dual_leverage() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSwap, SYMBOL).await;
+    let bitget_set_dual_leverage = bitget_swap_exchange.set_dual_leverage("1").await;
+    trace!(?bitget_set_dual_leverage);
+}

+ 25 - 27
standard/tests/exchange_test.rs

@@ -107,26 +107,24 @@ pub async fn test_new_exchange(exchange: ExchangeEnum, symbol: &str) -> Box<dyn
         //     params.insert("pass_key".to_string(), pass_key);
         //     Exchange::new(exchange, symbol.to_string(), false, params, order_sender, error_sender).await
         // }
-        // ExchangeEnum::BitgetSwap => {
-        //     let mut params: BTreeMap<String, String> = BTreeMap::new();
-        //     let access_key = account_info.bitget_access_key;
-        //     let secret_key = account_info.bitget_secret_key;
-        //     let pass_key = account_info.bitget_pass;
-        //     params.insert("access_key".to_string(), access_key);
-        //     params.insert("secret_key".to_string(), secret_key);
-        //     params.insert("pass_key".to_string(), pass_key);
-        //     Exchange::new(exchange, symbol.to_string(), false, params, order_sender, error_sender).await
-        // }
-        // ExchangeEnum::BybitSwap => {
-        //     let mut params: BTreeMap<String, String> = BTreeMap::new();
-        //     let access_key = account_info.bybit_access_key;
-        //     let secret_key = account_info.bybit_secret_key;
-        //     let pass_key = account_info.bybit_pass;
-        //     params.insert("access_key".to_string(), access_key);
-        //     params.insert("secret_key".to_string(), secret_key);
-        //     params.insert("pass_key".to_string(), pass_key);
-        //     Exchange::new(exchange, symbol.to_string(), false, params, order_sender, error_sender).await
-        // }
+        ExchangeEnum::BitgetSwap => {
+            let mut params: BTreeMap<String, String> = BTreeMap::new();
+            let access_key = account_info.bitget_access_key;
+            let secret_key = account_info.bitget_secret_key;
+            let pass_key = account_info.bitget_pass;
+            params.insert("access_key".to_string(), access_key);
+            params.insert("secret_key".to_string(), secret_key);
+            params.insert("pass_key".to_string(), pass_key);
+            Exchange::new(exchange, symbol.to_string(), false, params, order_sender, error_sender).await
+        }
+        ExchangeEnum::BybitSwap => {
+            let mut params: BTreeMap<String, String> = BTreeMap::new();
+            let access_key = account_info.bybit_access_key;
+            let secret_key = account_info.bybit_secret_key;
+            params.insert("access_key".to_string(), access_key);
+            params.insert("secret_key".to_string(), secret_key);
+            Exchange::new(exchange, symbol.to_string(), false, params, order_sender, error_sender).await
+        }
         // ExchangeEnum::HtxSwap => {
         //     let mut params: BTreeMap<String, String> = BTreeMap::new();
         //     let access_key = account_info.htx_access_key;
@@ -137,9 +135,9 @@ pub async fn test_new_exchange(exchange: ExchangeEnum, symbol: &str) -> Box<dyn
         //     params.insert("pass_key".to_string(), pass_key);
         //     Exchange::new(exchange, symbol.to_string(), false, params, order_sender, error_sender).await
         // }
-        // _ => {
-        //     panic!("该交易所未实现!")
-        // }
+        _ => {
+            panic!("该交易所未实现!")
+        }
     }
 }
 
@@ -709,9 +707,9 @@ where
         //     };
         //     exchange_wss.ws_connect_async(bool_v3_clone, fun, &write_tx_am, write_rx).await.expect("链接失败(内部一个心跳线程应该已经关闭了)");
         // }
-        // _ => {
-        //     error!("该交易所不支持!test_new_exchange_wss:{:?}", exchange);
-        //     panic!("该交易所不支持!test_new_exchange_wss:{:?}", exchange)
-        // }
+        _ => {
+            error!("该交易所不支持!test_new_exchange_wss:{:?}", exchange);
+            panic!("该交易所不支持!test_new_exchange_wss:{:?}", exchange)
+        }
     }
 }