Browse Source

仓位可以识别出来了。

skyffire 1 year ago
parent
commit
83889ff104
4 changed files with 77 additions and 6 deletions
  1. 10 0
      exchanges/src/bitget_swap_rest.rs
  2. 63 2
      standard/src/bitget_usdt_swap.rs
  3. 3 3
      standard/src/lib.rs
  4. 1 1
      strategy/src/core.rs

+ 10 - 0
exchanges/src/bitget_swap_rest.rs

@@ -115,6 +115,16 @@ impl BitgetSwapRest {
         ).await
     }
 
+    // 获取所有仓位
+    pub async fn get_all_position(&mut self, params: Value) -> ResponseData {
+        self.request("GET".to_string(),
+                     "/api/v2".to_string(),
+                     "/mix/position/all-position".to_string(),
+                     true,
+                     params.to_string(),
+        ).await
+    }
+
     // 下单
     pub async fn swap_order(&mut self, params: Value) -> ResponseData {
         self.request("POST".to_string(),

+ 63 - 2
standard/src/bitget_usdt_swap.rs

@@ -13,7 +13,7 @@ use tracing::info;
 use tracing_subscriber::fmt::format;
 use global::trace_stack::TraceStack;
 use crate::exchange::ExchangeEnum;
-use crate::{Account, Market, Order, OrderCommand, Platform, Position, Ticker, utils};
+use crate::{Account, Market, Order, OrderCommand, Platform, Position, PositionModeEnum, Ticker, utils};
 
 #[allow(dead_code)]
 #[derive(Clone)]
@@ -120,7 +120,68 @@ impl Platform for BitgetSwap {
     async fn get_position(&mut self) -> Result<Vec<Position>, Error> { Err(Error::new(ErrorKind::NotFound, "bitget_swap:该交易所方法未实现".to_string())) }
 
     async fn get_positions(&mut self) -> Result<Vec<Position>, Error> {
-        Err(Error::new(ErrorKind::NotFound, "bitget_swap get_positions:该交易所方法未实现".to_string()))
+        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" => {
+                    PositionModeEnum::Both
+                },
+                "one_way_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())
+                        }
+                    }
+                },
+                _ => {
+                    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> {

+ 3 - 3
standard/src/lib.rs

@@ -386,9 +386,9 @@ impl Market {
 
 /// Position结构体(仓位信息)
 /// - `symbol(String)`: 币对
-/// - `margin_level(String)`: 持仓杆杠大小
-/// - `amount(String)`: 持仓量
-/// - `frozen_amount(String)`: 仓位冻结量
+/// - `margin_level(Decimal)`: 持仓杆杠大小
+/// - `amount(Decimal)`: 持仓量
+/// - `frozen_amount(Decimal)`: 仓位冻结量
 /// - `price(Decimal)`: 持仓均价
 /// - `profit(Decimal)`: 持仓浮动盈亏
 /// - `position_mode(PositionModeEnum)`: 持仓模式

+ 1 - 1
strategy/src/core.rs

@@ -1299,7 +1299,7 @@ impl Core {
         let mut length = 0;
         match self.platform_rest.get_positions().await {
             Ok(val) => {
-                info!("检查仓位信息({}条仓位信息,部分交易所会返回0持仓的):", length);
+                info!("检查仓位信息");
 
                 for position in val {
                     if position.amount.eq(&Decimal::ZERO) {