ソースを参照

修改kucoin相关接口
修改查询订单和撤单接口

gepangpang 2 年 前
コミット
7d2cee8576

+ 1 - 1
exchanges/src/kucoin_swap_rest.rs

@@ -149,7 +149,7 @@ impl KucoinSwapRest {
         ).await;
         data
     }
-    async fn swap_order(&self, params: serde_json::Value) -> ResponseData {
+    pub async fn swap_order(&self, params: serde_json::Value) -> ResponseData {
         let data = self.request("POST".to_string(),
                                 "/api/v1".to_string(),
                                 format!("/orders"),

+ 10 - 5
standard/src/binance_spot.rs

@@ -1,10 +1,10 @@
 use std::collections::BTreeMap;
 use std::io::{Error};
 use std::result::Result;
-use std::sync::mpsc::Sender;
+use tokio::sync::mpsc::Sender;
 use async_trait::async_trait;
 use rust_decimal::Decimal;
-use crate::{Platform, ExchangeEnum, Account, binance_handle, Position, PositionModeEnum, Ticker, Market, Order, OrderCommand};
+use crate::{Platform, ExchangeEnum, Account, binance_handle, Position, Ticker, Market, Order, OrderCommand};
 use exchanges::binance_spot_rest::BinanceSpotRest;
 use exchanges::response_base::ResponseData;
 
@@ -61,9 +61,14 @@ impl Platform for BinanceSpot {
         binance_handle::handle_account_info(res_data, self.symbol.clone())
     }
     // 获取仓位信息
-    async fn get_position(&self, _mode: PositionModeEnum) -> Result<Position, Error> {
+    async fn get_position(&self) -> Result<Position, Error> {
         todo!()
     }
+
+    async fn get_positions(&self) -> Result<Vec<Position>, Error> {
+        todo!()
+    }
+
     // 获取市场行情
     async fn get_ticker(&self) -> Result<Ticker, Error> {
         todo!()
@@ -73,7 +78,7 @@ impl Platform for BinanceSpot {
         todo!()
     }
 
-    async fn get_order_detail(&self, _order_id: &str, _is_custom_id: bool) -> Result<Order, Error> {
+    async fn get_order_detail(&self, _order_id: &str, _custom_id: &str) -> Result<Order, Error> {
         todo!()
     }
 
@@ -97,7 +102,7 @@ impl Platform for BinanceSpot {
         todo!()
     }
 
-    async fn cancel_order(&self, _order_id: &str, _is_custom_id: bool) -> Result<Order, Error> {
+    async fn cancel_order(&self, _order_id: &str, _custom_id: &str) -> Result<Order, Error> {
         todo!()
     }
 

+ 10 - 5
standard/src/binance_swap.rs

@@ -1,12 +1,12 @@
 use std::collections::BTreeMap;
 use std::io::{Error, ErrorKind};
 use std::result::Result;
-use std::sync::mpsc::Sender;
+use tokio::sync::mpsc::Sender;
 use async_trait::async_trait;
 use rust_decimal::Decimal;
 use rust_decimal_macros::dec;
 use serde_json::json;
-use crate::{Platform, ExchangeEnum, Account, Position, PositionModeEnum, Ticker, Market, Order, OrderCommand};
+use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, OrderCommand};
 use exchanges::binance_usdt_swap_rest::BinanceUsdtSwapRest;
 
 #[allow(dead_code)]
@@ -77,9 +77,14 @@ impl Platform for BinanceSwap {
         }
     }
     // 获取仓位信息
-    async fn get_position(&self, _mode: PositionModeEnum) -> Result<Position, Error> {
+    async fn get_position(&self) -> Result<Position, Error> {
         todo!()
     }
+
+    async fn get_positions(&self) -> Result<Vec<Position>, Error> {
+        todo!()
+    }
+
     // 获取市场行情
     async fn get_ticker(&self) -> Result<Ticker, Error> {
         todo!()
@@ -89,7 +94,7 @@ impl Platform for BinanceSwap {
         todo!()
     }
 
-    async fn get_order_detail(&self, _order_id: &str, _is_custom_id: bool) -> Result<Order, Error> {
+    async fn get_order_detail(&self, _order_id: &str, _custom_id: &str) -> Result<Order, Error> {
         todo!()
     }
 
@@ -113,7 +118,7 @@ impl Platform for BinanceSwap {
         todo!()
     }
 
-    async fn cancel_order(&self, _order_id: &str, _is_custom_id: bool) -> Result<Order, Error> {
+    async fn cancel_order(&self, _order_id: &str, _custom_id: &str) -> Result<Order, Error> {
         todo!()
     }
 

+ 10 - 5
standard/src/gate_spot.rs

@@ -1,9 +1,9 @@
 use std::collections::BTreeMap;
 use std::io::{Error};
-use std::sync::mpsc::Sender;
+use tokio::sync::mpsc::Sender;
 use async_trait::async_trait;
 use rust_decimal::Decimal;
-use crate::{Platform, ExchangeEnum, Account, Position, PositionModeEnum, Ticker, Market, Order, OrderCommand};
+use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, OrderCommand};
 use exchanges::gate_spot_rest::GateSpotRest;
 
 #[allow(dead_code)]
@@ -53,9 +53,14 @@ impl Platform for GateSpot {
         todo!()
     }
     // 获取仓位信息
-    async fn get_position(&self, _mode: PositionModeEnum) -> Result<Position, Error> {
+    async fn get_position(&self) -> Result<Position, Error> {
         todo!()
     }
+
+    async fn get_positions(&self) -> Result<Vec<Position>, Error> {
+        todo!()
+    }
+
     // 获取市场行情
     async fn get_ticker(&self) -> Result<Ticker, Error> {
         todo!()
@@ -65,7 +70,7 @@ impl Platform for GateSpot {
         todo!()
     }
 
-    async fn get_order_detail(&self, _order_id: &str, _is_custom_id: bool) -> Result<Order, Error> {
+    async fn get_order_detail(&self, _order_id: &str, _custom_id: &str) -> Result<Order, Error> {
         todo!()
     }
 
@@ -89,7 +94,7 @@ impl Platform for GateSpot {
         todo!()
     }
 
-    async fn cancel_order(&self, _order_id: &str, _is_custom_id: bool) -> Result<Order, Error> {
+    async fn cancel_order(&self, _order_id: &str, _custom_id: &str) -> Result<Order, Error> {
         todo!()
     }
 

+ 56 - 41
standard/src/gate_swap.rs

@@ -1,14 +1,14 @@
 use std::collections::{BTreeMap, HashMap};
 use std::io::{Error, ErrorKind};
 use std::str::FromStr;
-use std::sync::mpsc::Sender;
+use tokio::sync::mpsc::Sender;
 use async_trait::async_trait;
 use rust_decimal::Decimal;
 use rust_decimal::prelude::{FromPrimitive, ToPrimitive};
 use rust_decimal_macros::dec;
 use serde_json::{json};
 use futures::stream::FuturesUnordered;
-use futures::{StreamExt, TryStreamExt};
+use futures::{TryStreamExt};
 use crate::{Platform, ExchangeEnum, Account, Position, PositionModeEnum, Ticker, Market, Order, OrderCommand};
 use exchanges::gate_swap_rest::GateSwapRest;
 
@@ -85,28 +85,27 @@ impl Platform for GateSwap {
         }
     }
     // 获取持仓信息
-    async fn get_position(&self, _mode: PositionModeEnum) -> Result<Position, Error> {
+    async fn get_position(&self) -> Result<Position, Error> {
         let symbol_array: Vec<&str> = self.symbol.split("_").collect();
         let res_data = self.request.get_position(symbol_array[1].to_string().to_lowercase(), self.symbol.clone()).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 position_info = res_data_json.iter().find(|item| item["contract"].as_str().unwrap() == self.symbol).unwrap();
-            let position_mode = match position_info["mode"].as_str().unwrap_or("") {
-                "single" => PositionModeEnum::Both,
-                "dual_long" => PositionModeEnum::Long,
-                "dual_short" => PositionModeEnum::Short,
-                _ => PositionModeEnum::Both
-            };
-            let result = Position {
-                margin_level: position_info["leverage"].as_str().unwrap_or("1").parse().unwrap_or(dec!(0)),
-                amount: position_info["size"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
-                frozen_amount: dec!(0),
-                price: position_info["price"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
-                profit: position_info["unrealised_pnl"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
-                position_mode,
-                margin: position_info["margin"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
-            };
+            let result = parse_position_item(position_info);
+            Ok(result)
+        } else {
+            Err(Error::new(ErrorKind::Other, res_data.message))
+        }
+    }
+    // 获取所有持仓
+    async fn get_positions(&self) -> Result<Vec<Position>, Error> {
+        let symbol_array: Vec<&str> = self.symbol.split("_").collect();
+        let res_data = self.request.get_user_position(symbol_array[1].to_string().to_lowercase()).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| { parse_position_item(item) }).collect();
             Ok(result)
         } else {
             Err(Error::new(ErrorKind::Other, res_data.message))
@@ -169,9 +168,9 @@ impl Platform for GateSwap {
         }
     }
     // 获取订单详情
-    async fn get_order_detail(&self, order_id: &str, is_custom_id: bool) -> Result<Order, Error> {
+    async fn get_order_detail(&self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
         let symbol_array: Vec<&str> = self.symbol.split("_").collect();
-        let id = if is_custom_id { format!("t-my-custom-id_{}", order_id) } else { order_id.to_string() };
+        let id = if custom_id.eq("") { format!("t-my-custom-id_{}", custom_id) } else { order_id.to_string() };
         let res_data = self.request.get_order_details(symbol_array[1].to_string().to_lowercase(), id).await;
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
@@ -278,10 +277,10 @@ impl Platform for GateSwap {
         }
     }
     // 撤销订单
-    async fn cancel_order(&self, order_id: &str, is_custom_id: bool) -> Result<Order, Error> {
+    async fn cancel_order(&self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
         let symbol_array: Vec<&str> = self.symbol.split("_").collect();
         let settle = symbol_array[1].to_string().to_lowercase();
-        let id = if is_custom_id { format!("t-my-custom-id_{}", order_id) } else { order_id.to_string() };
+        let id = if order_id.eq("") { format!("t-my-custom-id_{}", custom_id) } else { order_id.to_string() };
         let res_data = self.request.cancel_order(settle, id.to_string()).await;
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
@@ -311,21 +310,21 @@ impl Platform for GateSwap {
         // 撤销订单
         let cancel = order_command.cancel;
         for item in cancel.keys() {
+            let self_clone = self.clone();
             let cancel_clone = cancel.clone();
             let item_clone = item.clone();
-            let is_custom_id = if cancel_clone[&item_clone][0].eq("") { true } else { false };
-            let self_clone = self.clone();
-            let order_id = cancel_clone[&item_clone][0].clone();
+            let order_id = cancel_clone[&item_clone].get(0).unwrap_or(&"".to_string()).clone();
+            let custom_id = cancel_clone[&item_clone].get(1).unwrap_or(&"".to_string()).clone();
             let result_sd = order_sender.clone();
             let err_sd = error_sender.clone();
             let handle = tokio::spawn(async move {
-                let result = self_clone.cancel_order(&order_id, is_custom_id).await;
+                let result = self_clone.cancel_order(&order_id, &custom_id).await;
                 match result {
                     Ok(result) => {
-                        result_sd.send(result).unwrap();
+                        result_sd.send(result).await.unwrap();
                     }
                     Err(error) => {
-                        err_sd.send(error).unwrap();
+                        err_sd.send(error).await.unwrap();
                     }
                 }
             });
@@ -345,19 +344,19 @@ impl Platform for GateSwap {
             let err_sd = error_sender.clone();
             let handle = tokio::spawn(async move {
                 let value = limits_clone[&item_clone].clone();
-                let amount = (Decimal::from_str(value.get(0).unwrap()).unwrap() / market_clone.amount_size).floor();
+                let amount = (Decimal::from_str(value.get(0).unwrap_or(&"0".to_string())).unwrap() / market_clone.amount_size).floor();
                 let side = value.get(1).unwrap();
-                let price = Decimal::from_str(value.get(2).unwrap()).unwrap();
+                let price = Decimal::from_str(value.get(2).unwrap_or(&"0".to_string())).unwrap();
                 let cid = value.get(3).unwrap();
 
                 //  order_name: [数量,方向,价格,c_id]
                 let result = self_clone.take_order(cid, side, price, amount).await;
                 match result {
                     Ok(result) => {
-                        result_sd.send(result).unwrap();
+                        result_sd.send(result).await.unwrap();
                     }
                     Err(error) => {
-                        err_sd.send(error).unwrap();
+                        err_sd.send(error).await.unwrap();
                     }
                 }
             });
@@ -369,28 +368,25 @@ impl Platform for GateSwap {
             let self_clone = self.clone();
             let check_clone = check.clone();
             let item_clone = item.clone();
+            let order_id = check_clone[&item_clone].get(0).unwrap_or(&"".to_string()).clone();
+            let custom_id = check_clone[&item_clone].get(1).unwrap_or(&"".to_string()).clone();
             let result_sd = order_sender.clone();
             let err_sd = error_sender.clone();
             let handle = tokio::spawn(async move {
-                let value = check_clone[&item_clone].clone();
-                let cid = value.get(0).unwrap();
-                let oid = value.get(1).unwrap();
-                let is_custom_id = if cid.eq("") { false } else { true };
-                let order_id = if cid.eq("") { oid } else { cid };
-                let result = self_clone.get_order_detail(order_id, is_custom_id).await;
+                let result = self_clone.get_order_detail(&order_id, &custom_id).await;
                 match result {
                     Ok(result) => {
-                        result_sd.send(result).unwrap();
+                        result_sd.send(result).await.unwrap();
                     }
                     Err(error) => {
-                        err_sd.send(error).unwrap();
+                        err_sd.send(error).await.unwrap();
                     }
                 }
             });
             handles.push(handle)
         }
 
-        let mut futures = FuturesUnordered::from_iter(handles);
+        let futures = FuturesUnordered::from_iter(handles);
         let _: Result<Vec<_>, _> = futures.try_collect().await;
     }
 }
@@ -406,4 +402,23 @@ fn parse_order_item(order: &serde_json::Value) -> Order {
         status: "".to_string(),
         order_type: "".to_string(),
     }
+}
+
+fn parse_position_item(position: &serde_json::Value) -> Position {
+    let position_mode = match position["mode"].as_str().unwrap_or("") {
+        "single" => PositionModeEnum::Both,
+        "dual_long" => PositionModeEnum::Long,
+        "dual_short" => PositionModeEnum::Short,
+        _ => PositionModeEnum::Both
+    };
+    Position {
+        symbol: position["contract"].as_str().unwrap_or("").parse().unwrap(),
+        margin_level: position["leverage"].as_str().unwrap_or("1").parse().unwrap_or(dec!(0)),
+        amount: position["size"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
+        frozen_amount: dec!(0),
+        price: position["price"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
+        profit: position["unrealised_pnl"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
+        position_mode,
+        margin: position["margin"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
+    }
 }

+ 77 - 35
standard/src/kucoin_swap.rs

@@ -1,7 +1,7 @@
 use std::collections::BTreeMap;
 use std::io::{Error, ErrorKind};
 use std::str::FromStr;
-use std::sync::mpsc::Sender;
+use tokio::sync::mpsc::Sender;
 use async_trait::async_trait;
 use rust_decimal::Decimal;
 use rust_decimal::prelude::ToPrimitive;
@@ -83,28 +83,32 @@ impl Platform for KucoinSwap {
         }
     }
 
-    async fn get_position(&self, _mode: PositionModeEnum) -> Result<Position, Error> {
-        let symbol_array: Vec<&str> = self.symbol.split("_").collect();
+    async fn get_position(&self) -> Result<Position, Error> {
         let symbol_format = format!("{}M", utils::format_symbol(self.symbol.clone(), ""));
-        let res_data = self.request.get_positions(symbol_array[1].to_string()).await;
+        let res_data = self.request.get_position(symbol_format).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 res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
+            println!("get_position {}", res_data_json);
             let default_info = json!({"high_24h": "0","low_24h": "0","lowest_ask": "0","highest_bid": "0","last": "0","volume_24h": "0"});
-            let position_info = res_data_json.iter().find(|item| item["symbol"].as_str().unwrap() == format!("{}M", symbol_format)).unwrap_or(&default_info);
+            let position_info = res_data_json;
             let position_mode = match position_info["mode"].as_str().unwrap_or("") {
                 "dual_long" => PositionModeEnum::Long,
                 "dual_short" => PositionModeEnum::Both,
                 _ => PositionModeEnum::Long,
             };
+            let symbol = position_info["symbol"].as_str().unwrap_or("");
+            let currency = position_info["settleCurrency"].as_str().unwrap_or("");
+            let coin = symbol.strip_suffix(currency).unwrap();
             let result = Position {
-                margin_level: position_info["size"].as_str().unwrap_or("1").parse().unwrap_or(dec!(1)),
+                symbol: format!("{}_{}", coin, currency),
+                margin_level: position_info["realLeverage"].as_str().unwrap_or("1").parse().unwrap_or(dec!(1)),
                 amount: position_info["size"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
                 frozen_amount: dec!(0),
                 price: position_info["price"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
                 profit: position_info["unrealised_pnl"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
                 position_mode,
-                margin: position_info["margin"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
+                margin: position_info["posMargin"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
             };
             Ok(result)
         } else {
@@ -112,6 +116,10 @@ impl Platform for KucoinSwap {
         }
     }
 
+    async fn get_positions(&self) -> Result<Vec<Position>, Error> {
+        todo!()
+    }
+
     async fn get_ticker(&self) -> Result<Ticker, Error> {
         let symbol_format = format!("{}M", utils::format_symbol(self.symbol.clone(), ""));
         let res_data = self.request.get_ticker(symbol_format).await;
@@ -122,11 +130,11 @@ impl Platform for KucoinSwap {
             let time = (Decimal::from_str(&*ticker_info["ts"].to_string()).unwrap() / dec!(1000000)).floor().to_i64().unwrap();
             let result = Ticker {
                 time,
-                high: ticker_info["bestAskPrice"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
-                low: ticker_info["bestBidPrice"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
-                sell: ticker_info["bestAskPrice"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
-                buy: ticker_info["bestBidPrice"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
-                last: ticker_info["price"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
+                high: ticker_info["bestAskPrice"].to_string().parse().unwrap_or(dec!(0)),
+                low: ticker_info["bestBidPrice"].to_string().parse().unwrap_or(dec!(0)),
+                sell: ticker_info["bestAskPrice"].to_string().parse().unwrap_or(dec!(0)),
+                buy: ticker_info["bestBidPrice"].to_string().parse().unwrap_or(dec!(0)),
+                last: ticker_info["price"].to_string().parse().unwrap_or(dec!(0)),
                 volume: ticker_info["size"].to_string().parse().unwrap_or(dec!(0)),
             };
             Ok(result)
@@ -143,21 +151,20 @@ impl Platform for KucoinSwap {
             let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
             let default_info = json!({});
             let market_info = res_data_json.iter().find(|item| item["symbol"].as_str().unwrap() == symbol_format).unwrap_or(&default_info);
-            let tick_size = market_info["order_price_round"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
-            let amount_size = market_info["quanto_multiplier"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
+            println!("{}", market_info);
 
             let result = Market {
                 symbol: self.symbol.clone(),
                 base_asset: market_info["baseCurrency"].as_str().unwrap_or("").to_string(),
                 quote_asset: market_info["quoteCurrency"].as_str().unwrap_or("").to_string(),
-                tick_size,
-                amount_size,
+                tick_size: market_info["tickSize"].to_string().parse().unwrap_or(dec!(0)),
+                amount_size: dec!(0),
                 price_precision: dec!(0),
                 amount_precision: dec!(0),
-                min_qty: market_info["order_size_min"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
-                max_qty: market_info["order_size_max"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
+                min_qty: market_info["lotSize"].to_string().parse().unwrap_or(dec!(0)),
+                max_qty: market_info["maxOrderQty"].to_string().parse().unwrap_or(dec!(0)),
                 min_notional: Default::default(),
-                max_notional: Default::default(),
+                max_notional: market_info["maxPrice"].to_string().parse().unwrap_or(dec!(0)),
                 ct_val: Default::default(),
             };
             Ok(result)
@@ -166,8 +173,17 @@ impl Platform for KucoinSwap {
         }
     }
 
-    async fn get_order_detail(&self, _order_id: &str, _is_custom_id: bool) -> Result<Order, Error> {
-        todo!()
+    async fn get_order_detail(&self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
+        let res_data = self.request.get_orders_details(order_id.to_string(), custom_id.to_string()).await;
+        if res_data.code == "200" {
+            let res_data_str = &res_data.data;
+            let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
+            println!("{}", res_data_json);
+            let result = parse_order_item(&res_data_json);
+            Ok(result)
+        } else {
+            Err(Error::new(ErrorKind::Other, res_data.message))
+        }
     }
 
     async fn get_orders_list(&self, status: &str) -> Result<Vec<Order>, Error> {
@@ -176,7 +192,7 @@ 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 order_info: Vec<_> = res_data_json.iter().filter(|item| item["contract"].as_str().unwrap_or("") == self.symbol.clone()).collect();
+            let order_info: Vec<&serde_json::Value> = res_data_json.iter().filter(|item| item["contract"].as_str().unwrap_or("") == self.symbol.clone()).collect();
             let result = order_info.iter().map(|item| parse_order_item(item)).collect();
             Ok(result)
         } else {
@@ -196,9 +212,33 @@ impl Platform for KucoinSwap {
         todo!()
     }
 
-    async fn take_order(&self, custom_id: &str, origin_side: &str, _price: Decimal, amount: Decimal) -> Result<Order, Error> {
-        let symbol_format = utils::format_symbol(self.symbol.clone(), "_");
-        let res_data = self.request.swap_bazaar_order(custom_id.to_string(), symbol_format, origin_side.to_string(), amount.to_u64().unwrap(), "10".to_string(), "".to_string(), "".to_string()).await;
+    async fn take_order(&self, custom_id: &str, origin_side: &str, price: Decimal, amount: Decimal) -> Result<Order, Error> {
+        let symbol_format = format!("{}M", utils::format_symbol(self.symbol.clone(), ""));
+        let mut params = json!({
+            "clientOid": custom_id,
+            "symbol": symbol_format,
+            "leverage": "10",
+            "price": price.to_string(),
+        });
+        let size = amount;
+        params["size"] = json!(size);
+        match origin_side {
+            "kd" => {
+                params["side"] = json!("buy");
+            }
+            "pd" => {
+                params["side"] = json!("sell");
+            }
+            "kk" => {
+                params["side"] = json!("sell");
+            }
+            "pk" => {
+                params["side"] = json!("buy");
+            }
+            _ => { println!("下单参数错误"); }
+        };
+
+        let res_data = self.request.swap_order(Default::default()).await;
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
@@ -209,9 +249,8 @@ impl Platform for KucoinSwap {
         }
     }
 
-    async fn cancel_order(&self, order_id: &str, _is_custom_id: bool) -> Result<Order, Error> {
-        let symbol_array: Vec<&str> = self.symbol.split("_").collect();
-        let res_data = self.request.cancel_order(symbol_array[1].to_string().to_lowercase(), order_id.to_string()).await;
+    async fn cancel_order(&self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
+        let res_data = self.request.cancel_order(order_id.to_string(), custom_id.to_string()).await;
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
@@ -233,14 +272,17 @@ impl Platform for KucoinSwap {
 }
 
 fn parse_order_item(order: &serde_json::Value) -> Order {
+    let deal_amount = order["dealSize"].to_string().parse().unwrap_or(dec!(0));
+    let deal_price = order["dealValue"].to_string().parse().unwrap_or(dec!(0));
+    let avg_price = deal_price / deal_amount;
     Order {
-        id: order["id"].to_string(),
-        custom_id: order["text"].to_string(),
+        id: order["id"].as_str().unwrap_or("").parse().unwrap(),
+        custom_id: order["clientOid"].as_str().unwrap_or("").parse().unwrap(),
         price: order["price"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
         amount: order["size"].to_string().parse().unwrap_or(dec!(0)),
-        deal_amount: Default::default(),
-        avg_price: Default::default(),
-        status: "".to_string(),
-        order_type: "".to_string(),
+        deal_amount,
+        avg_price,
+        status: order["status"].as_str().unwrap_or("").parse().unwrap(),
+        order_type: order["type"].as_str().unwrap_or("").parse().unwrap(),
     }
 }

+ 8 - 4
standard/src/lib.rs

@@ -1,6 +1,6 @@
 use std::collections::{BTreeMap, HashMap};
 use std::io::{Error};
-use std::sync::mpsc::Sender;
+use tokio::sync::mpsc::Sender;
 use async_trait::async_trait;
 use rust_decimal::Decimal;
 
@@ -217,6 +217,7 @@ pub struct Market {
 }
 
 /// Position结构体(仓位信息)
+/// - `symbol(String)`: 币对
 /// - `margin_level(String)`: 持仓杆杠大小
 /// - `amount(String)`: 持仓量
 /// - `frozen_amount(String)`: 仓位冻结量
@@ -226,6 +227,7 @@ pub struct Market {
 /// - `margin(Decimal)`: 仓位占用的保证金
 #[derive(Debug)]
 pub struct Position {
+    pub symbol: String,
     pub margin_level: Decimal,
     pub amount: Decimal,
     pub frozen_amount: Decimal,
@@ -333,13 +335,15 @@ pub trait Platform {
     // 获取账号信息
     async fn get_account(&self) -> Result<Account, Error>;
     // 获取持仓信息
-    async fn get_position(&self, mode: PositionModeEnum) -> Result<Position, Error>;
+    async fn get_position(&self) -> Result<Position, Error>;
+    // 获取所有持仓
+    async fn get_positions(&self) -> Result<Vec<Position>, Error>;
     // 获取市场行情
     async fn get_ticker(&self) -> Result<Ticker, Error>;
     // 查询所有的合约信息
     async fn get_market(&self) -> Result<Market, Error>;
     // 查询订单详情
-    async fn get_order_detail(&self, order_id: &str, is_custom_id: bool) -> Result<Order, Error>;
+    async fn get_order_detail(&self, order_id: &str, custom_id: &str) -> Result<Order, Error>;
     // 获取订单列表
     async fn get_orders_list(&self, status: &str) -> Result<Vec<Order>, Error>;
     // 设置持仓模式
@@ -351,7 +355,7 @@ pub trait Platform {
     // 下单接口
     async fn take_order(&self, custom_id: &str, origin_side: &str, price: Decimal, amount: Decimal) -> Result<Order, Error>;
     // 撤销订单
-    async fn cancel_order(&self, order_id: &str, is_custom_id: bool) -> Result<Order, Error>;
+    async fn cancel_order(&self, order_id: &str, custom_id: &str) -> Result<Order, Error>;
     // 批量撤销订单
     async fn cancel_orders(&self) -> Result<Vec<Order>, Error>;
     // 指令下单

+ 6 - 6
standard/tests/libs_test.rs

@@ -2,7 +2,7 @@ use std::collections::BTreeMap;
 use std::env;
 use rust_decimal_macros::dec;
 use exchanges::proxy;
-use standard::{Platform, PositionModeEnum};
+use standard::{Platform};
 use standard::utils;
 use standard::exchange::{Exchange, ExchangeEnum};
 
@@ -125,7 +125,7 @@ async fn test_get_account() {
 #[tokio::test]
 async fn test_gate_swap_get_position() {
     let gate_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::GateSwap);
-    println!("gate_swap get_position:{:?}", gate_swap_exchange.get_position(PositionModeEnum::Both).await);
+    println!("gate_swap get_position:{:?}", gate_swap_exchange.get_position().await);
 }
 
 // 测试Gate获取Ticker信息
@@ -146,7 +146,7 @@ async fn test_gate_swap_get_market() {
 #[tokio::test]
 async fn test_gate_swap_get_order_detail() {
     let gate_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::GateSwap);
-    println!("gate_swap get_order_detail:{:?}", gate_swap_exchange.get_order_detail("336321097375", false).await);
+    println!("gate_swap get_order_detail:{:?}", gate_swap_exchange.get_order_detail("336321097375", "").await);
 }
 
 // 测试Gate获取Order列表信息
@@ -181,14 +181,14 @@ async fn test_take_order() {
 #[tokio::test]
 async fn test_cancel_order() {
     let gate_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::GateSwap);
-    println!("gate_swap cancel_order:{:?}", gate_swap_exchange.cancel_order("337811438982", false).await);
+    println!("gate_swap cancel_order:{:?}", gate_swap_exchange.cancel_order("337811438982", "").await);
 }
 
 // 测试kucoin 获取持仓信息
 #[tokio::test]
 async fn test_kucoin_swap_get_position() {
     let kucoin_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::KucoinSwap);
-    println!("kucoin_swap get_position:{:?}", kucoin_swap_exchange.get_position(PositionModeEnum::Both).await);
+    println!("kucoin_swap get_position:{:?}", kucoin_swap_exchange.get_position().await);
 }
 
 // 测试kucoin 获取Ticker信息
@@ -209,5 +209,5 @@ async fn test_kucoin_swap_get_market() {
 #[tokio::test]
 async fn test_kucoin_swap_get_order_detail() {
     let kucoin_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::KucoinSwap);
-    println!("kucoin_swap get_market:{:?}", kucoin_swap_exchange.get_order_detail("123", false).await);
+    println!("kucoin_swap get_market:{:?}", kucoin_swap_exchange.get_order_detail("123", "").await);
 }