浏览代码

完成kucoin测试

gepangpang 2 年之前
父节点
当前提交
cb54a9a11d
共有 4 个文件被更改,包括 187 次插入33 次删除
  1. 94 31
      standard/src/kucoin_handle.rs
  2. 5 2
      standard/src/kucoin_swap.rs
  3. 20 0
      standard/tests/gate_handle_test.rs
  4. 68 0
      standard/tests/kucoin_handle_test.rs

+ 94 - 31
standard/src/kucoin_handle.rs

@@ -16,20 +16,16 @@ pub fn handle_account_info(res_data: ResponseData, symbol: String) -> Account {
 
 pub fn format_account_info(data: serde_json::Value, symbol: String) -> Account {
     let symbol_array: Vec<&str> = symbol.split("_").collect();
-    if data["data"]["currency"].as_str().unwrap() == symbol_array[1].to_string() && data["subject"].as_str().unwrap() == "availableBalance.change" {
-        let available_balance = Decimal::from_str(&data["data"]["availableBalance"].to_string()).unwrap();
-        let frozen_balance = Decimal::from_str(&data["data"]["holdBalance"].to_string()).unwrap();
-        let balance = available_balance + frozen_balance;
-        Account {
-            balance,
-            available_balance,
-            frozen_balance,
-            stocks: dec!(0),
-            available_stocks: dec!(0),
-            frozen_stocks: dec!(0),
-        }
-    } else {
-        panic!("Kucoin:格式化账号信息错误!\nformat_account_info:data={:?}", data);
+    let available_balance = Decimal::from_str(data["availableBalance"].as_str().unwrap()).unwrap();
+    let frozen_balance = Decimal::from_str(data["holdBalance"].as_str().unwrap()).unwrap();
+    let balance = available_balance + frozen_balance;
+    Account {
+        balance,
+        available_balance,
+        frozen_balance,
+        stocks: dec!(0),
+        available_stocks: dec!(0),
+        frozen_stocks: dec!(0),
     }
 }
 
@@ -59,35 +55,97 @@ pub fn format_special_ticker(data: serde_json::Value, label: String) -> SpecialD
 // 处理position信息
 pub fn handle_position(res_data: ResponseData, amount_size: Decimal) -> Vec<Position> {
     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_position_item(item, amount_size) }).collect();
+    let res_data_json: serde_json::Value = serde_json::from_str(&res_data_str).unwrap();
+    let result = format_position_item(&res_data_json, amount_size);
     return result;
 }
 
-pub fn format_position_item(position: &serde_json::Value, amount_size: Decimal) -> Position {
+pub fn format_position_item(position: &serde_json::Value, amount_size: Decimal) -> Vec<Position> {
     let symbol = position["symbol"].as_str().unwrap_or("");
+    let real_leverage = Decimal::from_str(&position["realLeverage"].to_string()).unwrap();
     let currency = position["settleCurrency"].as_str().unwrap_or("");
     let coin = &symbol[..symbol.find(currency).unwrap_or(0)];
+    let avg_entry_price = Decimal::from_str(&position["avgEntryPrice"].to_string()).unwrap();
+    let unrealised_pnl = Decimal::from_str(&position["unrealisedPnl"].to_string()).unwrap();
+    let pos_margin = Decimal::from_str(&position["posMargin"].to_string()).unwrap();
 
     let current_qty = Decimal::from_str(&position["currentQty"].to_string()).unwrap();
     let amount = current_qty * amount_size;
     let position_mode = if amount > dec!(0) { PositionModeEnum::Long } else { PositionModeEnum::Short };
-    Position {
-        symbol: format!("{}_{}", coin, currency),
-        margin_level: Decimal::from_str(&position["realLeverage"].to_string()).unwrap(),
-        amount: amount.abs(),
-        frozen_amount: dec!(0),
-        price: Decimal::from_str(&position["avgEntryPrice"].to_string()).unwrap(),
-        profit: Decimal::from_str(&position["unrealisedPnl"].to_string()).unwrap(),
-        position_mode,
-        margin: Decimal::from_str(&position["posMargin"].to_string()).unwrap(),
-    }
+    let mut position_array = Vec::new();
+    return match position_mode {
+        PositionModeEnum::Long => {
+            position_array.push(
+                Position {
+                    symbol: format!("{}_{}", coin, currency),
+                    margin_level: real_leverage,
+                    amount: amount.abs(),
+                    frozen_amount: dec!(0),
+                    price: avg_entry_price,
+                    profit: unrealised_pnl,
+                    position_mode: PositionModeEnum::Long,
+                    margin: pos_margin,
+                }
+            );
+            position_array.push(
+                Position {
+                    symbol: format!("{}_{}", coin, currency),
+                    margin_level: real_leverage,
+                    amount: dec!(0),
+                    frozen_amount: dec!(0),
+                    price: dec!(0),
+                    profit: dec!(0),
+                    position_mode: PositionModeEnum::Short,
+                    margin: dec!(0),
+                });
+            position_array
+        }
+        PositionModeEnum::Short => {
+            position_array.push(
+                Position {
+                    symbol: format!("{}_{}", coin, currency),
+                    margin_level: real_leverage,
+                    amount: dec!(0),
+                    frozen_amount: dec!(0),
+                    price: dec!(0),
+                    profit: dec!(0),
+                    position_mode: PositionModeEnum::Long,
+                    margin: dec!(0),
+                });
+            position_array.push(
+                Position {
+                    symbol: format!("{}_{}", coin, currency),
+                    margin_level: real_leverage,
+                    amount: amount.abs(),
+                    frozen_amount: dec!(0),
+                    price: Decimal::from_str(&position["avgEntryPrice"].to_string()).unwrap(),
+                    profit: Decimal::from_str(&position["unrealisedPnl"].to_string()).unwrap(),
+                    position_mode: PositionModeEnum::Short,
+                    margin: Decimal::from_str(&position["posMargin"].to_string()).unwrap(),
+                });
+            position_array
+        }
+        _ => {
+            position_array.push(
+                Position {
+                    symbol: format!("{}_{}", coin, currency),
+                    margin_level: real_leverage,
+                    amount,
+                    frozen_amount: dec!(0),
+                    price: Decimal::from_str(&position["avgEntryPrice"].to_string()).unwrap(),
+                    profit: Decimal::from_str(&position["unrealisedPnl"].to_string()).unwrap(),
+                    position_mode: PositionModeEnum::Both,
+                    margin: Decimal::from_str(&position["posMargin"].to_string()).unwrap(),
+                });
+            position_array
+        }
+    };
 }
 
 // 处理order信息
 pub fn handle_order(res_data: ResponseData, amount_size: Decimal) -> SpecialOrder {
     let res_data_str = res_data.data;
-    let res_data_json: Vec<serde_json::Value> = serde_json::from_str(&*res_data_str).unwrap();
+    let res_data_json: Vec<serde_json::Value> = vec![serde_json::from_str(&*res_data_str).unwrap()];
     let mut order_info = Vec::new();
     for item in res_data_json.iter() {
         order_info.push(format_order_item(item.clone(), amount_size));
@@ -103,14 +161,19 @@ pub fn format_order_item(order: serde_json::Value, amount_size: Decimal) -> Orde
     let size = Decimal::from_str(order["size"].as_str().unwrap()).unwrap();
     let status = order["status"].as_str().unwrap_or("");
     let filled_size = Decimal::from_str(order["filledSize"].as_str().unwrap()).unwrap();
-    let match_price = Decimal::from_str(order["matchPrice"].as_str().unwrap()).unwrap();
+
+    let mut avg_price;
+    if status == "match" {
+        avg_price = Decimal::from_str(order["matchPrice"].as_str().unwrap_or("-1")).unwrap();
+    } else {
+        avg_price = price;
+    };
 
     let amount = size * amount_size;
     let deal_amount = filled_size * amount_size;
-    let avg_price = if status == "match" { match_price } else { price };
     let custom_status = if ["done", "match"].contains(&status) { "REMOVE".to_string() } else if status == "open" { "NEW".to_string() } else { panic!("Kucoin:格式化订单状态错误!\nformat_order_item:status={:?}", status); };
     Order {
-        id: order["id"].as_str().unwrap().to_string(),
+        id: order["orderId"].as_str().unwrap().to_string(),
         custom_id: order["clientOid"].as_str().unwrap().to_string(),
         price,
         amount,

+ 5 - 2
standard/src/kucoin_swap.rs

@@ -114,7 +114,7 @@ impl Platform for KucoinSwap {
             let res_data_str = &res_data.data;
             let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
             let result = kucoin_handle::format_position_item(&res_data_json, amount_size);
-            Ok(vec![result])
+            Ok(result)
         } else {
             Err(Error::new(ErrorKind::Other, res_data.message))
         }
@@ -127,7 +127,10 @@ impl Platform for KucoinSwap {
         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| { kucoin_handle::format_position_item(item, amount_size) }).collect();
+            let mut result = Vec::new();
+            for item in res_data_json.iter() {
+                result.extend(kucoin_handle::format_position_item(item, amount_size))
+            }
             Ok(result)
         } else {
             Err(Error::new(ErrorKind::Other, res_data.message))

+ 20 - 0
standard/tests/gate_handle_test.rs

@@ -0,0 +1,20 @@
+mod exchange_test;
+
+use tracing::{instrument};
+use exchanges::gate_swap_ws::GateSubscribeType;
+use standard::exchange::ExchangeEnum;
+use crate::exchange_test::test_new_exchange_wss;
+
+const SYMBOL: &str = "BLZ_USDT";
+
+// 测试获取Exchange实体
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_self_exchange() {
+    global::log_utils::init_log_with_trace();
+
+    // let gate_subscribe_type = vec![
+    //     GateSubscribeType::PuFuturesOrderBook
+    // ];
+    // test_new_exchange_wss(ExchangeEnum::KucoinSwap, SYMBOL, gate_subscribe_type, "depth").await;
+}

+ 68 - 0
standard/tests/kucoin_handle_test.rs

@@ -0,0 +1,68 @@
+mod exchange_test;
+
+use tracing::{instrument};
+use exchanges::kucoin_swap_ws::{KucoinSubscribeType};
+use standard::exchange::ExchangeEnum;
+use crate::exchange_test::test_new_exchange_wss;
+
+const SYMBOL: &str = "BLZ_USDT";
+
+// 测试订阅深度订阅
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_wss_depth() {
+    global::log_utils::init_log_with_trace();
+
+    let kucoin_subscribe_type = vec![
+        KucoinSubscribeType::PuContractMarketLevel2Depth50
+    ];
+    test_new_exchange_wss(ExchangeEnum::KucoinSwap, SYMBOL, kucoin_subscribe_type, "depth").await;
+}
+
+// 测试订阅Ticker信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_wss_ticker() {
+    global::log_utils::init_log_with_trace();
+
+    let kucoin_subscribe_type = vec![
+        KucoinSubscribeType::PuContractMarkettickerV2
+    ];
+    test_new_exchange_wss(ExchangeEnum::KucoinSwap, SYMBOL, kucoin_subscribe_type, "ticker").await;
+}
+
+// 测试订阅Account信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_wss_account() {
+    global::log_utils::init_log_with_trace();
+
+    let kucoin_subscribe_type = vec![
+        KucoinSubscribeType::PrContractAccountWallet
+    ];
+    test_new_exchange_wss(ExchangeEnum::KucoinSwap, SYMBOL, kucoin_subscribe_type, "account").await;
+}
+
+// 测试订阅Position信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_wss_position() {
+    global::log_utils::init_log_with_trace();
+
+    let kucoin_subscribe_type = vec![
+        KucoinSubscribeType::PrContractPosition
+    ];
+    test_new_exchange_wss(ExchangeEnum::KucoinSwap, SYMBOL, kucoin_subscribe_type, "position").await;
+}
+
+// 测试订阅Orders信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_wss_orders() {
+    global::log_utils::init_log_with_trace();
+
+    let kucoin_subscribe_type = vec![
+        KucoinSubscribeType::PrContractMarketTradeOrders
+    ];
+    test_new_exchange_wss(ExchangeEnum::KucoinSwap, SYMBOL, kucoin_subscribe_type, "orders").await;
+}