Ver código fonte

bitget接入

JiahengHe 2 anos atrás
pai
commit
d76958435f
3 arquivos alterados com 168 adições e 21 exclusões
  1. 136 8
      strategy/src/exchange_disguise.rs
  2. 0 2
      strategy/src/model.rs
  3. 32 11
      strategy/src/quant.rs

+ 136 - 8
strategy/src/exchange_disguise.rs

@@ -12,11 +12,12 @@ use tokio::time::sleep;
 use tracing::{error, info};
 use exchanges::binance_spot_ws::{BinanceSpotSubscribeType, BinanceSpotWs, BinanceSpotWsType};
 use exchanges::binance_swap_ws::{BinanceSubscribeType, BinanceSwapWs, BinanceWsType};
+use exchanges::bitget_spot_ws::{BitgetSpotWs, BitgetSubscribeType};
 use exchanges::gate_swap_rest::GateSwapRest;
 use exchanges::gate_swap_ws::{GateSubscribeType, GateSwapWs, GateWsType};
 use exchanges::kucoin_swap_ws::{KucoinSubscribeType, KucoinSwapWs, KucoinWsType};
 use global::trace_stack::TraceStack;
-use standard::exchange::ExchangeEnum::{BinanceSpot, BinanceSwap, GateSwap, KucoinSwap};
+use standard::exchange::ExchangeEnum::{BinanceSpot, BinanceSwap, BitgetSpot, GateSwap, KucoinSwap};
 use standard::SpecialTicker;
 use crate::model::{OrderInfo, OriginalTicker, OriginalTradeBa, OriginalTradeGa};
 use crate::quant::Quant;
@@ -29,6 +30,9 @@ pub async fn run_transactional_exchange(bool_v1 :Arc<AtomicBool>, exchange_name:
         }
         "kucoin_usdt_swap" => {
             kucoin_swap_run(bool_v1, 1i8, quant_arc, name, symbols, exchange_params).await;
+        },
+        "bitget_usdt_spot" => {
+            bitget_spot_run(bool_v1,1i8, quant_arc, name, symbols, exchange_params).await;
         }
         _ => {
             error!("交易交易所启动失败,参数错误!")
@@ -50,6 +54,9 @@ pub async fn run_reference_exchange(bool_v1 :Arc<AtomicBool>, exchange_name: Str
         }
         "kucoin_usdt_swap" => {
             kucoin_swap_run(bool_v1,0i8, quant_arc, name, symbols, exchange_params).await;
+        },
+        "bitget_usdt_spot" => {
+            bitget_spot_run(bool_v1,0i8, quant_arc, name, symbols, exchange_params).await;
         }
         _ => {
             error!("参考交易所启动失败,参数错误!")
@@ -61,13 +68,17 @@ pub async fn run_reference_exchange(bool_v1 :Arc<AtomicBool>, exchange_name: Str
 async fn gate_swap_run(bool_v1 :Arc<AtomicBool>, type_num: i8, quant_arc: Arc<Mutex<Quant>>, name: String, symbols: Vec<String>, exchange_params: BTreeMap<String, String>){
     let (tx, mut rx) = channel(100);
     let mut gate_exc = GateSwapRest::new(false, exchange_params.clone());
-    // 获取user_id
-    let res_data = gate_exc.wallet_fee().await;
-    assert_eq!(res_data.code, "200", "获取gate交易所参数 user_id 失败, 启动失败!");
+    let user_id;
+    if type_num == 1{
+        // 获取user_id
+        let res_data = gate_exc.wallet_fee().await;
+        assert_eq!(res_data.code, "200", "获取gate交易所参数 user_id 失败, 启动失败!");
+
+        let wallet_obj :Value = serde_json::from_str(&res_data.data).unwrap();
+        info!(?wallet_obj);
+        user_id = wallet_obj["user_id"].to_string();
+    }
 
-    let wallet_obj :Value = serde_json::from_str(&res_data.data).unwrap();
-    info!(?wallet_obj);
-    let user_id = wallet_obj["user_id"].to_string();
     let symbols_one = symbols.clone();
     // 获取乘数(计价货币兑换为结算货币的乘数)
     let response = gate_exc.get_market_details("usdt".to_string()).await;
@@ -208,7 +219,7 @@ async fn kucoin_swap_run(bool_v1 :Arc<AtomicBool>, type_num: i8, quant_arc: Arc<
     let symbols_clone = symbols.clone();
     let mut symbol_arr = Vec::new();
     for symbol in symbols_clone{
-       let new_symbol = symbol.replace("_", "").to_uppercase() + "M";
+        let new_symbol = symbol.replace("_", "").to_uppercase() + "M";
         symbol_arr.push(new_symbol);
     }
     spawn( async move {
@@ -535,6 +546,123 @@ async fn reference_binance_swap_run(bool_v1 :Arc<AtomicBool>, quant_arc: Arc<Mut
     });
 }
 
+async fn bitget_spot_run(bool_v1 :Arc<AtomicBool>, type_num: i8, quant_arc: Arc<Mutex<Quant>>, name: String, symbols: Vec<String>, exchange_params: BTreeMap<String, String>) {
+    let (tx, mut rx) = channel(100);
+    spawn( async move {
+        let mut bit_exc = BitgetSpotWs::new_label(name, false, exchange_params, BitgetSpot::PublicAndPrivate, tx);
+        // 交易
+        if type_num == 1 {
+            bit_exc.set_subscribe(vec![
+                BitgetSubscribeType::PuTrade,
+                BitgetSubscribeType::PuBooks5,
+                BitgetSubscribeType::PrAccount,
+                BitgetSubscribeType::PrOrders
+            ]);
+        } else { // 参考
+            bit_exc.set_subscribe(vec![
+                BitgetSubscribeType::PuTrade,
+                BitgetSubscribeType::PuBooks5
+            ]);
+        }
+        bit_exc.custom_subscribe(bool_v1, symbols.clone()).await;
+    });
+    spawn(async move {
+        let bot_arc_clone = Arc::clone(&quant_arc);
+        let multiplier = bot_arc_clone.lock().await.platform_rest.get_self_market().amount_size;
+        // trade
+        let mut max_buy = Decimal::ZERO;
+        let mut min_sell = Decimal::ZERO;
+        let run_symbol = symbols.clone()[0].clone();
+
+        loop {
+            sleep(Duration::from_millis(1)).await;
+            let mut trace_stack = TraceStack::default();
+
+            match rx.recv().await {
+                Some(data) => {
+                    trace_stack.on_network(data.time);
+                    trace_stack.on_before_quant();
+
+                    if data.code != "200".to_string() {
+                        continue;
+                    }
+                    if data.channel == "books5" {
+                        trace_stack.on_before_format();
+                        let depth = standard::handle_info::HandleSwapInfo::handle_special_depth(BitgetSpot, data);
+                        trace_stack.on_after_format();
+                        {
+                            let mut quant = bot_arc_clone.lock().await;
+                            quant._update_ticker(depth.ticker.clone(), depth.name.clone());
+                            quant._update_depth(depth.depth.clone(), depth.name.clone(), &mut trace_stack);
+                            quant.local_depths.insert(depth.name, depth.depth);
+                        }
+                    } else if data.channel == "trade" {
+                        let mut quant = bot_arc_clone.lock().await;
+                        let str = data.label.clone();
+                        if quant.is_update.contains_key(&data.label) && *quant.is_update.get(str.as_str()).unwrap(){
+                            max_buy = Decimal::ZERO;
+                            min_sell = Decimal::ZERO;
+                            quant.is_update.remove(str.as_str());
+                        }
+                        let trades: Vec<OriginalTradeGa> = serde_json::from_str(data.data.as_str()).unwrap();
+                        for trade in trades {
+                            if trade.price > max_buy || max_buy == Decimal::ZERO{
+                                max_buy = trade.price
+                            }
+                            if trade.price < min_sell || min_sell == Decimal::ZERO{
+                                min_sell = trade.price
+                            }
+                        }
+                        quant.max_buy_min_sell_cache.insert(data.label, vec![max_buy, min_sell]);
+                    } else if data.channel == "orders" {
+                        trace_stack.on_before_format();
+                        let orders = standard::handle_info::HandleSwapInfo::handle_order(BitgetSpot, data.clone(), multiplier);
+                        trace_stack.on_after_format();
+                        let mut order_infos:Vec<OrderInfo> = Vec::new();
+                        for order in orders.order {
+                            if order.status == "NULL" {
+                                continue;
+                            }
+                            let order_info = OrderInfo {
+                                symbol: "".to_string(),
+                                amount: order.amount.abs(),
+                                side: "".to_string(),
+                                price: order.price,
+                                client_id: order.custom_id,
+                                filled_price: order.avg_price,
+                                filled: order.deal_amount.abs(),
+                                order_id: order.id,
+                                local_time: 0,
+                                create_time: 0,
+                                status: order.status,
+                                fee: Default::default(),
+                                trace_stack: Default::default(),
+                            };
+                            order_infos.push(order_info);
+                        }
+                        {
+                            let mut quant = bot_arc_clone.lock().await;
+                            quant.update_order(order_infos, trace_stack);
+                        }
+                    } else if data.channel == "account" { // _update_account
+                        // TODO: 此处应有两个余额,交易币和本位币余额(由于quant中现货的更新账户没有做任何操作,所以此处可暂不处理)
+                        let account = standard::handle_info::HandleSwapInfo::handle_account_info(BitgetSpot, data, run_symbol.clone());
+                        {
+                            let mut quant = bot_arc_clone.lock().await;
+                            quant.update_equity(account);
+                        }
+                    }
+                },
+                None => {
+                    error!("参考交易所通道错误");
+                    break;
+                }
+            }
+        }
+    });
+}
+
+
 
 fn parse_json_array(json: &str) -> serde_json::Result<Vec<Value>> {
     serde_json::from_str(json)

+ 0 - 2
strategy/src/model.rs

@@ -96,9 +96,7 @@ pub struct OriginalTradeBa {
 
 #[derive(Serialize, Deserialize)]
 pub struct OriginalTradeGa {
-    // 成交价格
     pub size: Decimal,
-    // 买方是否是做市方。如true,则此次成交是一个主动卖出单,否则是一个主动买入单。
     pub price: Decimal
 }
 

+ 32 - 11
strategy/src/quant.rs

@@ -969,27 +969,48 @@ impl Quant {
 
     pub async fn check_position(&mut self){
         info!("清空挂单!");
-        match self.platform_rest.cancel_orders().await{
-            Ok(val)=>{
-                info!(?val);
-            },
-            Err(e)=>{
-                error!("清空挂单异常: {}", e);
-            }
-        };
         match self.platform_rest.cancel_orders_all().await {
             Ok(val)=>{
                 info!("清空所有挂单,{:?}", val);
             },
             Err(err)=>{
-                error!("取消所有订单异常: {}",err)
+                error!("取消所有订单异常: {}",err);
+                match self.platform_rest.cancel_orders() {
+                    Ok(val) => {
+                        info!("清空当前币对挂单,{:?}", val);
+                    },
+                    Err(exc) => {
+                        error!("清空当前币对订单异常: {}",exc);
+                    }
+                }
+            }
+        }
+        if self.exchange.contains("spot") { // 现货
+            self.check_position_spot().await;
+        } else { // 合约
+            self.check_position_swap().await;
+        }
+    }
+
+    pub async fn check_position_spot(&mut self){
+        info!("检查遗漏仓位!");
+        match self.platform_rest.get_spot_account().await {
+            Ok(val) => {
+                for account in val {
+
+                }
+            },
+            Err(err) => {
+                error!("获取仓位信息异常: {}", error);
             }
         }
+    }
+
+    pub async fn check_position_swap(&mut self){
         info!("检查遗漏仓位!");
         match self.platform_rest.get_positions().await {
             Ok(val)=>{
                 for position in val {
-
                     if position.amount.eq(&Decimal::ZERO) {
                         continue;
                     }
@@ -1136,7 +1157,7 @@ impl Quant {
         self.strategy.equity = self.strategy.start_equity.clone();
         self.strategy.total_amount = self.strategy.equity * self.strategy.lever_rate / self.strategy.mp;
         // 获取数量精度
-        self.strategy.step_size = self.market.ct_val.clone();
+        self.strategy.step_size = self.market.amount_size.clone();
         if self.strategy.step_size > Decimal::ONE {
             self.strategy.step_size = self.strategy.step_size.trunc();
         }