소스 검색

gate的止损基础代码已经与3.0.0进行合并,之后的止损在3.0.0上面进行开发。

skyffire 1 년 전
부모
커밋
52c1b1ce0b
6개의 변경된 파일190개의 추가작업 그리고 14개의 파일을 삭제
  1. 17 0
      exchanges/src/gate_swap_rest.rs
  2. 53 0
      exchanges/tests/gate_swap_test.rs
  3. 10 0
      standard/src/binance_swap.rs
  4. 8 0
      standard/src/bybit_swap.rs
  5. 80 1
      standard/src/gate_swap.rs
  6. 22 13
      standard/src/lib.rs

+ 17 - 0
exchanges/src/gate_swap_rest.rs

@@ -231,6 +231,23 @@ impl GateSwapRest {
         ).await;
         data
     }
+    // 提交一个自动订单
+    pub async fn place_price_order(&mut self, settle: String, params: Value) -> ResponseData {
+        self.request("POST".to_string(),
+                     "/api/v4".to_string(),
+                     format!("/futures/{}/price_orders", settle),
+                     true,
+                     params.to_string()).await
+    }
+    // 撤销自动订单
+    pub async fn cancel_price_order(&mut self, settle: String, order_id: String) -> ResponseData {
+        self.request("DELETE".to_string(),
+                     "/api/v4".to_string(),
+                     format!("/futures/{}/price_orders/{}", settle, order_id),
+                     true,
+                     "{}".to_string(),
+        ).await
+    }
     //设置持仓模式
     pub async fn setting_dual_mode(&mut self, settle: String, dual_mode: bool) -> ResponseData {
         let params = serde_json::json!({

+ 53 - 0
exchanges/tests/gate_swap_test.rs

@@ -99,6 +99,59 @@ async fn rest_cancel_order_all_test() {
     println!("okx--设置持仓模式--{:?}", req_data);
 }
 
+//rest-下一个自动单
+#[tokio::test]
+async fn price_order_test() {
+    global::log_utils::init_log_with_info();
+
+    let mut rest = get_rest();
+    let mut params = json!({});
+
+    params["initial"] = json!({
+        "contract": "XRP_USDT",
+        "price": "0",
+        "tif": "ioc",
+        "reduce_only": true,
+        // [平多:close_long, 平空:close_short]
+        "auto_size": "close_long"
+    });
+
+    params["trigger"] = json!({
+        // [平多:close-long-position, 平空:close-short-position]
+        "order_type": "close-long-position",
+        // 一般都默认用0
+        "strategy_type": 0,
+        // [0 - 最新成交价,1 - 标记价格,2 - 指数价格]
+        "price_type": 0,
+        // [1: 引用价格大于等于我们传的价格,2:引用价格小于等于我们传的价格]
+        // 在止损的情况下:
+        //     1 可以理解为向上突破触发价(一般是给空单用)
+        //     2 可以理解为向下突破触发价(一般是给多单用)
+        "rule": 2,
+        // 订单触发价格
+        "price": "0.5600",
+    });
+
+    let response_data = rest.place_price_order("usdt".to_string(), params).await;
+    if response_data.code == "200" {
+        let response_obj: serde_json::Value = serde_json::from_str(response_data.data.as_str()).unwrap();
+
+        info!("resp={:?}", response_obj.as_object().unwrap());
+    } else {
+        error!(?response_data);
+    }
+}
+
+#[tokio::test]
+async fn price_order_cancel_test() {
+    global::log_utils::init_log_with_info();
+
+    let mut rest = get_rest();
+
+    // 这边取消订单只能使用系统返回的
+    let rst = rest.cancel_price_order("usdt".to_string(), "58002898".to_string()).await;
+    info!(?rst);
+}
 
 //rest-查询合约账户变更历史
 #[tokio::test]

+ 10 - 0
standard/src/binance_swap.rs

@@ -6,6 +6,7 @@ use async_trait::async_trait;
 use rust_decimal::Decimal;
 use rust_decimal::prelude::FromPrimitive;
 use rust_decimal_macros::dec;
+use serde_json::Value;
 use tokio::sync::mpsc::Sender;
 use tokio::time::Instant;
 use tracing::{error, warn};
@@ -337,6 +338,15 @@ impl Platform for BinanceSwap {
 
     async fn cancel_orders_all(&mut self) -> Result<Vec<Order>, Error> { Err(Error::new(ErrorKind::NotFound, "binance_swap:该交易所方法未实现".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, "binance_swap:该交易所方法未实现".to_string()))
+    }
+
+    async fn cancel_stop_loss_order(&mut self, _order_id: &str) -> Result<Value, Error> {
+        Err(Error::new(ErrorKind::NotFound, "binance_swap:该交易所方法未实现".to_string()))
+    }
+
     async fn set_dual_mode(&mut self, _coin: &str, _is_dual_mode: bool) -> Result<String, Error> { Err(Error::new(ErrorKind::NotFound, "binance_swap:该交易所方法未实现".to_string())) }
 
     async fn set_dual_leverage(&mut self, _leverage: &str) -> Result<String, Error> { Err(Error::new(ErrorKind::NotFound, "binance_swap:该交易所方法未实现".to_string())) }

+ 8 - 0
standard/src/bybit_swap.rs

@@ -483,6 +483,14 @@ impl Platform for BybitSwap {
         }
     }
 
+    async fn take_stop_loss_order(&mut self, _stop_price: Decimal, _price: Decimal, _side: &str) -> Result<Value, Error> {
+        Err(Error::new(ErrorKind::NotFound, "bybit_swap:该交易所方法未实现".to_string()))
+    }
+
+    async fn cancel_stop_loss_order(&mut self, _order_id: &str) -> Result<Value, Error> {
+        Err(Error::new(ErrorKind::NotFound, "bybit_swap:该交易所方法未实现".to_string()))
+    }
+
     // 设置持仓模式
     async fn set_dual_mode(&mut self, _coin: &str, is_dual_mode: bool) -> Result<String, Error> {
         let coin_format = self.symbol_uppercase.clone();

+ 80 - 1
standard/src/gate_swap.rs

@@ -7,7 +7,7 @@ use futures::stream::FuturesUnordered;
 use futures::TryStreamExt;
 use rust_decimal::Decimal;
 use rust_decimal::prelude::{FromPrimitive, ToPrimitive};
-use serde_json::json;
+use serde_json::{json, Value};
 use tokio::spawn;
 use tokio::time::Instant;
 use tracing::{error, trace};
@@ -469,6 +469,85 @@ impl Platform for GateSwap {
         }
     }
 
+    async fn take_stop_loss_order(&mut self, stop_price: Decimal, price: Decimal, side: &str) -> Result<Value, Error>
+    {
+        let mut params = json!({});
+        let mut initial = json!({
+            "contract": "XRP_USDT",
+
+            "price": price.to_string(),
+
+            "tif": "ioc",
+
+            // 是否只减仓
+            "reduce_only": true,
+
+            // [平多:close_long, 平空:close_short]
+            // "auto_size": "close_long"
+        });
+        let mut trigger = json!({
+            // [平多:close-long-position, 平空:close-short-position]
+            // "order_type": "close-long-position",
+
+            // 一般都默认用0
+            "strategy_type": 0,
+
+            // [0 - 最新成交价,1 - 标记价格,2 - 指数价格]
+            "price_type": 0,
+
+            // [1: 引用价格大于等于我们传的价格,2:引用价格小于等于我们传的价格]
+            // 在止损的情况下:
+            //     1 可以理解为向上突破触发价(一般是给空单用)
+            //     2 可以理解为向下突破触发价(一般是给多单用)
+            // "rule": 2,
+
+            // 订单触发价格
+            "price": stop_price.to_string(),
+        });
+
+        match side {
+            "kd" => {
+                initial["auto_size"] = json!("close_long");
+                trigger["order_type"] = json!("close-long-position");
+                trigger["rule"] = json!(2);
+            },
+            "kk" => {
+                initial["auto_size"] = json!("close_short");
+                trigger["order_type"] = json!("close-short-position");
+                trigger["rule"] = json!(1);
+            },
+            _ => {
+                error!("gate swap 止损单side错误: {}", side);
+            }
+        }
+
+        params["initial"] = initial;
+        params["trigger"] = trigger;
+
+        let binding = self.symbol.clone().to_lowercase();
+        let symbol_split: Vec<&str> = binding.split("_").collect();
+        let base_coin = symbol_split[1].to_string();
+        let response_data = self.request.place_price_order(base_coin, params).await;
+        if response_data.code == "200" {
+            Ok(response_data.data)
+        } else {
+            Err(Error::new(ErrorKind::Other, response_data.to_string()))
+        }
+    }
+
+    async fn cancel_stop_loss_order(&mut self, order_id: &str) -> Result<Value, Error> {
+        let binding = self.symbol.clone().to_lowercase();
+        let symbol_split: Vec<&str> = binding.split("_").collect();
+        let base_coin = symbol_split[1].to_string();
+
+        let response_data = self.request.cancel_price_order(base_coin, order_id.to_string()).await;
+        if response_data.code == "200" {
+            Ok(response_data.data)
+        } else {
+            Err(Error::new(ErrorKind::Other, response_data.to_string()))
+        }
+    }
+
     // 设置持仓模式
     async fn set_dual_mode(&mut self, coin: &str, is_dual_mode: bool) -> Result<String, Error> {
         let coin_format = coin.to_string().to_lowercase();

+ 22 - 13
standard/src/lib.rs

@@ -4,6 +4,7 @@ use std::fmt::Formatter;
 use std::io::{Error};
 use async_trait::async_trait;
 use rust_decimal::Decimal;
+use serde_json::Value;
 use tokio::time::Instant;
 use global::trace_stack::TraceStack;
 
@@ -427,7 +428,7 @@ impl Position {
 /// let mut params:BTreeMap<String,String> = BTreeMap::new();
 /// params.insert("access_key".to_string(), "your_access_key".to_string());
 /// params.insert("access_key".to_string(), "your_secret_key".to_string());
-/// let exchange = Exchange::new(ExchangeEnum::BinanceSwap, "BTC_USDT".to_string(), true, params);
+/// // let exchange = Exchange::new(ExchangeEnum::BinanceSwap, "BTC_USDT".to_string(), true, params);
 /// ```
 /// 获取当前交易所交易模式
 /// - fn get_self_exchange(&self) -> ExchangeEnum;
@@ -437,9 +438,9 @@ impl Position {
 /// # let mut params:BTreeMap<String,String> = BTreeMap::new();
 /// # params.insert("access_key".to_string(), "your_access_key".to_string());
 /// # params.insert("access_key".to_string(), "your_secret_key".to_string());
-/// # let exchange = Exchange::new(ExchangeEnum::BinanceSwap, "BTC_USDT".to_string(), true, params);
+/// # // let exchange = Exchange::new(ExchangeEnum::BinanceSwap, "BTC_USDT".to_string(), true, params);
 ///
-/// exchange.get_self_exchange();
+/// // exchange.get_self_exchange();
 /// ```
 /// 获取当前是否使用高速模式
 /// - fn get_self_is_colo(&self) -> bool;
@@ -449,9 +450,9 @@ impl Position {
 /// # let mut params:BTreeMap<String,String> = BTreeMap::new();
 /// # params.insert("access_key".to_string(), "your_access_key".to_string());
 /// # params.insert("access_key".to_string(), "your_secret_key".to_string());
-/// # let exchange = Exchange::new(ExchangeEnum::BinanceSwap, "BTC_USDT".to_string(), true, params);
+/// # // let exchange = Exchange::new(ExchangeEnum::BinanceSwap, "BTC_USDT".to_string(), true, params);
 ///
-/// exchange.get_self_is_colo();
+/// // exchange.get_self_is_colo();
 /// ```
 /// 获取当前是否使用登录
 /// - fn get_self_is_login(&self) -> bool;
@@ -461,9 +462,9 @@ impl Position {
 /// # let mut params:BTreeMap<String,String> = BTreeMap::new();
 /// # params.insert("access_key".to_string(), "your_access_key".to_string());
 /// # params.insert("access_key".to_string(), "your_secret_key".to_string());
-/// # let exchange = Exchange::new(ExchangeEnum::BinanceSwap, "BTC_USDT".to_string(), true, params);
+/// # // let exchange = Exchange::new(ExchangeEnum::BinanceSwap, "BTC_USDT".to_string(), true, params);
 ///
-/// exchange.get_self_is_login();
+/// // exchange.get_self_is_login();
 /// ```
 /// 获取登录params信息
 /// - fn get_self_params(&self) -> BTreeMap<String, String>;
@@ -473,9 +474,9 @@ impl Position {
 /// # let mut params:BTreeMap<String,String> = BTreeMap::new();
 /// # params.insert("access_key".to_string(), "your_access_key".to_string());
 /// # params.insert("access_key".to_string(), "your_secret_key".to_string());
-/// # let exchange = Exchange::new(ExchangeEnum::BinanceSwap, "BTC_USDT".to_string(), true, params);
+/// # // let exchange = Exchange::new(ExchangeEnum::BinanceSwap, "BTC_USDT".to_string(), true, params);
 ///
-/// exchange.get_self_params();
+/// // exchange.get_self_params();
 /// ```
 /// 获取账号信息
 /// - async fn get_account(&self, symbol: &str) -> Result<Account, Error>;
@@ -485,9 +486,9 @@ impl Position {
 /// # let mut params:BTreeMap<String,String> = BTreeMap::new();
 /// # params.insert("access_key".to_string(), "your_access_key".to_string());
 /// # params.insert("access_key".to_string(), "your_secret_key".to_string());
-/// # let exchange = Exchange::new(ExchangeEnum::BinanceSwap, "BTC_USDT".to_string(), true, params);
+/// # // let exchange = Exchange::new(ExchangeEnum::BinanceSwap, "BTC_USDT".to_string(), true, params);
 ///
-/// exchange.get_account()
+/// // exchange.get_account()
 /// ```
 /// 订阅账号信息
 /// ```rust
@@ -496,9 +497,9 @@ impl Position {
 /// # let mut params:BTreeMap<String,String> = BTreeMap::new();
 /// # params.insert("access_key".to_string(), "your_access_key".to_string());
 /// # params.insert("access_key".to_string(), "your_secret_key".to_string());
-/// # let exchange = Exchange::new(ExchangeEnum::BinanceSwap, "BTC_USDT".to_string(), true, params);
+/// # // let exchange = Exchange::new(ExchangeEnum::BinanceSwap, "BTC_USDT".to_string(), true, params);
 ///
-/// exchange.subscribe_account();
+/// // exchange.subscribe_account();
 /// ```
 #[async_trait]
 pub trait Platform {
@@ -551,6 +552,14 @@ pub trait Platform {
     async fn cancel_orders(&mut self) -> Result<Vec<Order>, Error>;
     // 撤销所有订单
     async fn cancel_orders_all(&mut self) -> Result<Vec<Order>, Error>;
+    /// 下一个止损单
+    /// - stop_price: 触发价
+    /// - price: 委托价,0就市价委托
+    /// - side: 止损哪个方向[long多单,short空单]
+    async fn take_stop_loss_order(&mut self, stop_price: Decimal, price: Decimal, side: &str) -> Result<Value, Error>;
+    /// 撤销止损订单
+    /// - order_id: 需要撤销的id
+    async fn cancel_stop_loss_order(&mut self, order_id: &str) -> Result<Value, Error>;
     // 设置持仓模式
     async fn set_dual_mode(&mut self, coin: &str, is_dual_mode: bool) -> Result<String, Error>;
     // 更新双持仓模式下杠杆