Procházet zdrojové kódy

完成bitget初版

gepangpang před 1 rokem
rodič
revize
b8432fb576

+ 56 - 21
exchanges/src/bitget_swap_ws.rs

@@ -19,6 +19,7 @@ pub enum BitgetSwapWsType {
 pub enum BitgetSwapSubscribeType {
     PuTrade,
     PuBooks1,
+    PuKline(String),
 
     PrAccount,
     PrPosition,
@@ -70,7 +71,7 @@ impl BitgetSwapWs {
             login_param,
             symbol_s: vec![],
             subscribe_types: vec![],
-            heartbeat_time: 1000 * 10
+            heartbeat_time: 1000 * 10,
         }
     }
 
@@ -97,6 +98,7 @@ impl BitgetSwapWs {
             if match t {
                 BitgetSwapSubscribeType::PuTrade => false,
                 BitgetSwapSubscribeType::PuBooks1 => false,
+                BitgetSwapSubscribeType::PuKline(_) => false,
 
                 BitgetSwapSubscribeType::PrAccount => true,
                 BitgetSwapSubscribeType::PrOrders => true,
@@ -121,14 +123,21 @@ impl BitgetSwapWs {
                     "channel": "trade",
                     "instId": symbol,
                 })
-            },
+            }
             BitgetSwapSubscribeType::PuBooks1 => {
                 json!({
                     "instType": "USDT-FUTURES",
                     "channel": "books1",
                     "instId": symbol,
                 })
-            },
+            }
+            BitgetSwapSubscribeType::PuKline(t) => {
+                json!({
+                    "instType": "USDT-FUTURES",
+                    "channel": format!("candle{}m", t),
+                    "instId": symbol,
+                })
+            }
 
             // 私有订阅
             BitgetSwapSubscribeType::PrAccount => {
@@ -137,21 +146,21 @@ impl BitgetSwapWs {
                     "channel": "account",
                     "coin": "default",
                 })
-            },
+            }
             BitgetSwapSubscribeType::PrPosition => {
                 json!({
                     "instType": "USDT-FUTURES",
                     "channel": "positions",
                     "instId": "default"
                 })
-            },
+            }
             BitgetSwapSubscribeType::PrOrders => {
                 json!({
                     "instType": "USDT-FUTURES",
                     "channel": "orders",
                     "instId": "default"
                 })
-            },
+            }
         }
     }
 
@@ -176,13 +185,13 @@ impl BitgetSwapWs {
     /*****************************************socket基本*****************************************************/
     /*******************************************************************************************************/
     pub async fn ws_connect_async<F, Future>(&mut self,
-                                            is_shutdown_arc: Arc<AtomicBool>,
-                                            handle_function: F,
-                                            write_tx_am: &Arc<Mutex<UnboundedSender<Message>>>,
-                                            write_to_socket_rx: UnboundedReceiver<Message>) -> Result<(), Error>
-        where
-            F: Fn(ResponseData) -> Future + Clone + Send + 'static + Sync,
-            Future: std::future::Future<Output=()> + Send + 'static, // 确保 Fut 是一个 Future,且输出类型为 ()
+                                             is_shutdown_arc: Arc<AtomicBool>,
+                                             handle_function: F,
+                                             write_tx_am: &Arc<Mutex<UnboundedSender<Message>>>,
+                                             write_to_socket_rx: UnboundedReceiver<Message>) -> Result<(), Error>
+    where
+        F: Fn(ResponseData) -> Future + Clone + Send + 'static + Sync,
+        Future: std::future::Future<Output=()> + Send + 'static, // 确保 Fut 是一个 Future,且输出类型为 ()
     {
         let login_is = self.contains_pr();
         let address_url = self.address_url.clone();
@@ -279,7 +288,7 @@ impl BitgetSwapWs {
                 res_data.code = -301;
                 res_data.channel = "pong".to_string();
                 res_data.message = "success".to_string();
-            },
+            }
             _ => {
                 let json_value: Value = serde_json::from_str(&text).unwrap();
 
@@ -298,15 +307,41 @@ impl BitgetSwapWs {
                     res_data.channel = format!("{}", json_value["arg"]["channel"].as_str().unwrap());
                     res_data.message = "success".to_string();
                 } else if json_value.get("action").is_some() {
-                    res_data.data = json_value["data"].clone();
-                    if res_data.data == "[]" {
-                        res_data.code = -1;
+                    let channel = format!("{}", json_value["arg"]["channel"].as_str().unwrap());
+                    res_data.data = json_value.clone();
+                    res_data.reach_time = json_value["ts"].as_i64().unwrap() * 1000;
+                    res_data.message = "success".to_string();
+
+                    res_data.code = 200;
+
+                    if channel.contains("books1") {
+                        res_data.channel = "orderbook".to_string();
+                        res_data.data_type = json_value["action"].as_str().unwrap().to_string();
+                        // bybit 时间在data块外
+                        res_data.reach_time = json_value.get("ts").unwrap().as_i64().unwrap_or(0i64);
+                    } else if channel.contains("trade") {
+                        res_data.channel = "trade".to_string();
+                        res_data.data_type = json_value["action"].as_str().unwrap().to_string();
+                    } else if channel.contains("ticker") {
+                        res_data.channel = "tickers".to_string();
+                        res_data.data["ts"] = json_value["ts"].clone();
+                        res_data.data_type = json_value["action"].as_str().unwrap().to_string();
+                    } else if channel.contains("candle") {
+                        res_data.channel = "kline".to_string();
+                        res_data.data_type = json_value["action"].as_str().unwrap().to_string();
+                    } else if channel.contains("positions") {
+                        res_data.channel = "position".to_string();
+                        res_data.data_type = json_value["action"].as_str().unwrap().to_string();
+                    } else if channel.contains("orders") {
+                        res_data.channel = "order".to_string();
+                        res_data.data_type = json_value["action"].as_str().unwrap().to_string();
+                    } else if channel.contains("account") {
+                        res_data.channel = "wallet".to_string();
+                        res_data.data_type = json_value["action"].as_str().unwrap().to_string();
                     } else {
-                        res_data.code = 200;
+                        res_data.code = -1;
+                        res_data.channel = "未知的频道".to_string();
                     }
-                    res_data.message = "success".to_string();
-                    res_data.channel = format!("{}", json_value["arg"]["channel"].as_str().unwrap());
-                    res_data.reach_time = json_value["ts"].as_i64().unwrap() * 1000;
                 }
             }
         }

+ 0 - 2
standard/src/binance_swap.rs

@@ -439,7 +439,6 @@ impl Platform for BinanceSwap {
         });
         if order_id != "" { params["orderId"] = json!(order_id) }
         if custom_id != "" { params["origClientOrderId"] = json!(custom_id) }
-        // println!("{}", params);
         let res_data = self.request.cancel_order(params).await;
         if res_data.code == 200 {
             let res_data_json = &res_data.data;
@@ -473,7 +472,6 @@ impl Platform for BinanceSwap {
             "symbol": symbol_format.clone(),
         });
         let res_data = self.request.cancel_order_all(params).await;
-        println!("{:?}", res_data);
         if res_data.code == 200 {
             let result = vec![Order {
                 id: "".to_string(),

+ 36 - 14
standard/src/bitget_swap.rs

@@ -7,7 +7,6 @@ use async_trait::async_trait;
 use futures::stream::FuturesUnordered;
 use futures::TryStreamExt;
 use rust_decimal::{Decimal, MathematicalOps};
-use rust_decimal::prelude::ToPrimitive;
 use rust_decimal_macros::dec;
 use serde_json::{json, Value};
 use tokio::spawn;
@@ -16,7 +15,6 @@ use tracing::{error, info};
 use global::trace_stack::TraceStack;
 use crate::exchange::ExchangeEnum;
 use crate::{Account, Market, Order, OrderCommand, Platform, Position, PositionModeEnum, Record, Ticker, utils};
-use crate::bybit_swap::format_position_item;
 
 #[allow(dead_code)]
 #[derive(Clone)]
@@ -148,10 +146,8 @@ impl Platform for BitgetSwap {
             "marginCoin": "USDT",
             "symbol": symbol_format
         });
-        let ct_val = self.market.multiplier;
-        println!("{:?}", params.clone());
+        let multiplier = self.market.multiplier;
         let response = self.request.get_single_position(params).await;
-        println!("{:?}", response);
         if response.code != 200 {
             return Err(Error::new(ErrorKind::NotFound, format!("bitget_swap 获取仓位异常{:?}", response).to_string()));
         }
@@ -166,11 +162,11 @@ impl Platform for BitgetSwap {
         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 amount = Decimal::from_str(position_json["total"].as_str().unwrap()).unwrap() * multiplier;
             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() {
+            let mut position_mode = match position_json["posMode"].as_str().unwrap() {
                 "hedge_mode" => {
                     match position_json["holdSide"].as_str().unwrap() {
                         "short" => {
@@ -194,6 +190,18 @@ impl Platform for BitgetSwap {
             };
             let margin = Decimal::from_str(position_json["marginSize"].as_str().unwrap()).unwrap();
 
+            let side = position_json["holdSide"].as_str().unwrap();
+            match position_mode {
+                PositionModeEnum::Both => {
+                    position_mode = match side {
+                        "long" => PositionModeEnum::Long,
+                        "short" => PositionModeEnum::Short,
+                        _ => { PositionModeEnum::Both }
+                    }
+                }
+                _ => {}
+            }
+
             positions.push(Position {
                 symbol,
                 margin_level,
@@ -215,7 +223,6 @@ impl Platform for BitgetSwap {
             "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()));
@@ -235,7 +242,7 @@ impl Platform for BitgetSwap {
             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() {
+            let mut position_mode = match position_json["posMode"].as_str().unwrap() {
                 "hedge_mode" => {
                     match position_json["holdSide"].as_str().unwrap() {
                         "short" => {
@@ -259,6 +266,18 @@ impl Platform for BitgetSwap {
             };
             let margin = Decimal::from_str(position_json["marginSize"].as_str().unwrap()).unwrap();
 
+            let side = position_json["holdSide"].as_str().unwrap();
+            match position_mode {
+                PositionModeEnum::Both => {
+                    position_mode = match side {
+                        "long" => PositionModeEnum::Long,
+                        "short" => PositionModeEnum::Short,
+                        _ => { PositionModeEnum::Both }
+                    }
+                }
+                _ => {}
+            }
+
             positions.push(Position {
                 symbol,
                 margin_level,
@@ -356,8 +375,10 @@ impl Platform for BitgetSwap {
             let tick_size = Decimal::TEN.powd(Decimal::NEGATIVE_ONE * price_precision);
             let amount_precision = Decimal::from_str(market_info["volumePlace"].as_str().unwrap()).unwrap();
             let amount_size = Decimal::TEN.powd(Decimal::NEGATIVE_ONE * amount_precision);
-            let min_qty = Decimal::NEGATIVE_ONE;
+            let min_qty = Decimal::from_str(market_info["minTradeNum"].as_str().unwrap()).unwrap();
             let max_qty = Decimal::NEGATIVE_ONE;
+            let min_notional = Decimal::from_str(market_info["minTradeUSDT"].as_str().unwrap()).unwrap();
+            let max_notional = Decimal::NEGATIVE_ONE;
             // let multiplier = Decimal::from_str(&market_info["sizeMultiplier"].as_str().unwrap()).unwrap();
             let multiplier = Decimal::ONE;
 
@@ -371,8 +392,8 @@ impl Platform for BitgetSwap {
                 amount_precision,
                 min_qty,
                 max_qty,
-                min_notional: min_qty,
-                max_notional: max_qty,
+                min_notional,
+                max_notional,
                 multiplier,
             };
             Ok(result)
@@ -418,7 +439,6 @@ impl Platform for BitgetSwap {
 
     async fn take_order(&mut self, custom_id: &str, origin_side: &str, price: Decimal, amount: Decimal) -> Result<Order, Error> {
         let multiplier = self.market.multiplier;
-
         return self.take_order_symbol(self.symbol.clone(), multiplier, custom_id, origin_side, price, amount).await;
     }
 
@@ -460,6 +480,8 @@ impl Platform for BitgetSwap {
             }
             _ => { panic!("bitget_usdt_swap 下单参数错误"); }
         };
+
+        info!(?params);
         let res_data = self.request.swap_order(params).await;
         if res_data.code != 200 {
             return Err(Error::new(ErrorKind::Other, res_data.to_string()));
@@ -643,7 +665,7 @@ impl Platform for BitgetSwap {
                         self_clone.order_sender.send(result).await.unwrap();
                     }
                     Err(error) => {
-                        info!(?error);
+                        error!(?error);
                         let mut err_order = Order::new();
                         err_order.custom_id = cid.clone();
                         err_order.status = "REMOVE".to_string();

+ 70 - 23
standard/src/bitget_swap_handle.rs

@@ -11,10 +11,10 @@ use crate::{Account, OrderBook, Order, Position, PositionModeEnum, SpecialOrder,
 // 处理账号信息
 pub fn handle_account_info(response: &ResponseData, _symbol: &String) -> Account {
     let mut rst = Account::new();
-
-    for data in response.data.as_array().unwrap() {
+    let data_info = response.data["data"].clone();
+    for data in data_info.as_array().unwrap() {
         if data["marginCoin"].as_str().unwrap() != "USDT" {
-            continue
+            continue;
         }
 
         // 格式化account信息
@@ -36,14 +36,15 @@ pub fn handle_account_info(response: &ResponseData, _symbol: &String) -> Account
 }
 
 // 处理order信息
-pub fn handle_order(res_data: ResponseData, ct_val: Decimal) -> SpecialOrder {
-    let res_data_json = res_data.data.as_array().unwrap();
+pub fn handle_order(res_data: &ResponseData, ct_val: &Decimal) -> SpecialOrder {
+    let data_info = res_data.data["data"].clone();
+    let res_data_json = data_info.as_array().unwrap();
     let mut order_info = Vec::new();
     for item in res_data_json.iter() {
-        order_info.push(format_order_item(item.clone(), ct_val));
+        order_info.push(format_order_item(item.clone(), ct_val.clone()));
     }
     SpecialOrder {
-        name: res_data.label,
+        name: res_data.label.clone(),
         order: order_info,
     }
 }
@@ -105,8 +106,9 @@ pub fn format_depth_items(value: Value, mul: &Decimal) -> Vec<OrderBook> {
 
 // 处理position信息
 pub fn handle_position(res_data: &ResponseData, ct_val: &Decimal) -> Vec<Position> {
-    let res_data_json = res_data.data.as_array().unwrap();
-    res_data_json.iter().map(|item| { format_position_item(item, ct_val) }).collect()
+    let data_info = res_data.data["data"].clone();
+    let data_info_json = data_info.as_array().unwrap();
+    data_info_json.iter().map(|item| { format_position_item(item, ct_val) }).collect()
 }
 
 pub fn format_position_item(position_json: &Value, ct_val: &Decimal) -> Position {
@@ -116,7 +118,7 @@ pub fn format_position_item(position_json: &Value, ct_val: &Decimal) -> Position
     let frozen_amount = Decimal::from_str(position_json["frozen"].as_str().unwrap()).unwrap() * ct_val;
     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() {
+    let mut position_mode = match position_json["posMode"].as_str().unwrap() {
         "hedge_mode" => {
             match position_json["holdSide"].as_str().unwrap() {
                 "short" => {
@@ -124,22 +126,34 @@ pub fn format_position_item(position_json: &Value, ct_val: &Decimal) -> Position
                 }
                 "long" => {
                     PositionModeEnum::Long
-                },
+                }
                 _ => {
                     panic!("bitget_usdt_swap: 未知的持仓模式与持仓方向: {}, {}",
                            position_json["posMode"].as_str().unwrap(), position_json["holdSide"].as_str().unwrap())
                 }
             }
-        },
+        }
         "one_way_mode" => {
             PositionModeEnum::Both
-        },
+        }
         _ => {
             panic!("bitget_usdt_swap: 未知的持仓模式: {}", position_json["posMode"].as_str().unwrap())
         }
     };
     let margin = Decimal::from_str(position_json["marginSize"].as_str().unwrap()).unwrap();
 
+    let side = position_json["holdSide"].as_str().unwrap();
+    match position_mode {
+        PositionModeEnum::Both => {
+            position_mode = match side {
+                "long" => PositionModeEnum::Long,
+                "short" => PositionModeEnum::Short,
+                _ => { PositionModeEnum::Both }
+            }
+        }
+        _ => {}
+    }
+
     Position {
         symbol,
         margin_level,
@@ -153,19 +167,20 @@ pub fn format_position_item(position_json: &Value, ct_val: &Decimal) -> Position
 }
 
 pub fn format_trade_items(response: &ResponseData) -> Vec<Trade> {
-    let result = response.data.as_array().unwrap();
+    let data_info = response.data["data"].clone();
+    let result = data_info.as_array().unwrap();
     let mut trades = vec![];
 
     for item in result {
         // 因为gate的量都是张数,所以要进行真实交易量处理
-        let mut size = Decimal::from_str(item["v"].as_str().unwrap()).unwrap();
-        let price = Decimal::from_str(item["p"].as_str().unwrap().to_string().as_str()).unwrap();
-        let side = item["S"].as_str().unwrap().to_string();
+        let mut size = Decimal::from_str(item["size"].as_str().unwrap()).unwrap();
+        let price = Decimal::from_str(item["price"].as_str().unwrap().to_string().as_str()).unwrap();
+        let side = item["side"].as_str().unwrap().to_string();
         size = match side.as_str() {
-            "Buy" => {
+            "buy" => {
                 size
             }
-            "Sell" => {
+            "sell" => {
                 -size
             }
             _ => {
@@ -176,16 +191,48 @@ pub fn format_trade_items(response: &ResponseData) -> Vec<Trade> {
         let value = (size * price).abs();
 
         trades.push(Trade {
-            id: item["i"].as_str().unwrap().to_string(),
-            time: Decimal::from_i64(item["T"].as_i64().unwrap()).unwrap(),
+            id: item["tradeId"].as_str().unwrap().to_string(),
+            time: Decimal::from_str(item["ts"].as_str().unwrap()).unwrap(),
             size,
             price,
             value,
-            symbol: item["s"].as_str().unwrap().to_string(),
+            symbol: response.data["arg"]["instId"].as_str().unwrap().replace("USDT", "_USDT"),
         })
     }
 
-    return trades
+    return trades;
+}
+pub fn handle_book_ticker(res_data: &ResponseData, mul: &Decimal) -> Depth {
+    let data_info = res_data.data["data"].clone();
+    let asks = format_depth_items(data_info[0]["asks"].clone(), mul);
+    let bids = format_depth_items(data_info[0]["bids"].clone(), mul);
+    let t = Decimal::from_i64(res_data.reach_time).unwrap();
+    let s = res_data.data["arg"]["instId"].as_str().unwrap().replace("USDT", "_USDT");
+
+    Depth {
+        time: t,
+        symbol: s.to_string(),
+        asks,
+        bids,
+    }
+}
+
+pub fn handle_records(value: &Value) -> Vec<Record> {
+    let data_info = value["data"].clone();
+    let mut records = vec![];
+    for record_value in data_info.as_array().unwrap() {
+        records.push(Record {
+            time: Decimal::from_str(record_value[0].as_str().unwrap()).unwrap(),
+            open: Decimal::from_str(record_value[1].as_str().unwrap()).unwrap(),
+            high: Decimal::from_str(record_value[2].as_str().unwrap()).unwrap(),
+            low: Decimal::from_str(record_value[3].as_str().unwrap()).unwrap(),
+            close: Decimal::from_str(record_value[4].as_str().unwrap()).unwrap(),
+            volume: Decimal::from_str(record_value[6].as_str().unwrap()).unwrap(),
+            symbol: value["arg"]["instId"].as_str().unwrap().replace("USDT", "_USDT"),
+        });
+    }
+
+    return records;
 }
 
 // 处理特殊深度数据

+ 15 - 12
standard/src/exchange_struct_handler.rs

@@ -166,6 +166,9 @@ impl ExchangeStructHandler {
             ExchangeEnum::BinanceSwap => {
                 binance_swap_handle::handle_book_ticker(&res_data, mul)
             }
+            ExchangeEnum::BitgetSwap => {
+                bitget_swap_handle::handle_book_ticker(&res_data, mul)
+            }
             ExchangeEnum::BybitSwap => {
                 bybit_swap_handle::handle_book_ticker(&res_data, mul)
             }
@@ -184,12 +187,12 @@ impl ExchangeStructHandler {
             // ExchangeEnum::GateSpot => {
             //     gate_spot_handle::handle_records(&res_data.data)
             // }
-            // ExchangeEnum::BitgetSwap => {
-            //     bitget_swap_handle::handle_records(&res_data.data)
-            // }
             ExchangeEnum::BinanceSwap => {
                 binance_swap_handle::handle_records(&res_data.data)
             }
+            ExchangeEnum::BitgetSwap => {
+                bitget_swap_handle::handle_records(&res_data.data)
+            }
             ExchangeEnum::BybitSwap => { // 未使用暂不实现
                 bybit_swap_handle::handle_records(&res_data.data)
             }
@@ -250,9 +253,9 @@ impl ExchangeStructHandler {
             ExchangeEnum::BinanceSwap => {
                 binance_swap_handle::handle_account_info(res_data, symbol)
             }
-            // ExchangeEnum::BitgetSwap => {
-            //     bitget_swap_handle::handle_account_info(res_data, symbol)
-            // }
+            ExchangeEnum::BitgetSwap => {
+                bitget_swap_handle::handle_account_info(res_data, symbol)
+            }
             ExchangeEnum::BybitSwap => {
                 bybit_swap_handle::handle_account_info(res_data, symbol)
             }
@@ -274,9 +277,9 @@ impl ExchangeStructHandler {
             // ExchangeEnum::KucoinSwap => {
             //     kucoin_swap_handle::handle_position(res_data, ct_val)
             // }
-            // ExchangeEnum::BitgetSwap => {
-            //     bitget_swap_handle::handle_position(res_data, ct_val)
-            // }
+            ExchangeEnum::BitgetSwap => {
+                bitget_swap_handle::handle_position(res_data, mul)
+            }
             ExchangeEnum::BybitSwap => {
                 bybit_swap_handle::handle_position(res_data, mul)
             }
@@ -298,9 +301,9 @@ impl ExchangeStructHandler {
             // ExchangeEnum::KucoinSwap => {
             //     kucoin_swap_handle::handle_order(res_data, ct_val)
             // }
-            // ExchangeEnum::BitgetSwap => {
-            //     bitget_swap_handle::handle_order(res_data, ct_val)
-            // }
+            ExchangeEnum::BitgetSwap => {
+                bitget_swap_handle::handle_order(res_data, ct_val)
+            }
             ExchangeEnum::BybitSwap => {
                 bybit_swap_handle::handle_order(res_data, ct_val)
             }

+ 247 - 190
strategy/src/bitget_usdt_swap.rs

@@ -1,190 +1,247 @@
-// use std::collections::BTreeMap;
-// use std::sync::Arc;
-// use std::sync::atomic::AtomicBool;
-// use rust_decimal::Decimal;
-// use tokio::spawn;
-// use tokio::sync::Mutex;
-// use tracing::{error, info};
-// use tokio_tungstenite::tungstenite::Message;
-// use exchanges::bitget_swap_ws::{BitgetSwapLogin, BitgetSwapSubscribeType, BitgetSwapWs, BitgetSwapWsType};
-// use exchanges::response_base::ResponseData;
-// use global::trace_stack::TraceStack;
-// use standard::exchange::ExchangeEnum::{BitgetSwap};
-// use standard::{Position, PositionModeEnum};
-// use crate::core::Core;
-// use crate::exchange_disguise::on_special_depth;
-// use crate::model::OrderInfo;
-//
-// pub async fn bitget_usdt_swap_run(is_shutdown_arc :Arc<AtomicBool>,
-//                                   is_trade: bool,
-//                                   core_arc: Arc<Mutex<Core>>,
-//                                   name: String,
-//                                   symbols: Vec<String>,
-//                                   is_colo: bool,
-//                                   exchange_params: BTreeMap<String, String>) {
-//     // 开启公共频道
-//     let (write_tx_public, write_rx_public) = futures_channel::mpsc::unbounded::<Message>();
-//
-//     // 开启公共连接
-//     let is_shutdown_arc_c1 = is_shutdown_arc.clone();
-//     let write_tx_am_public = Arc::new(Mutex::new(write_tx_public));
-//     let name_clone = name.clone();
-//     let core_arc_clone = core_arc.clone();
-//     let symbols_clone = symbols.clone();
-//     spawn(async move {
-//         // 构建链接ws
-//         let mut bg_public = BitgetSwapWs::new_label(name_clone.clone(),
-//                                                     is_colo,
-//                                                     None,
-//                                                     BitgetSwapWsType::Public);
-//
-//         // 消费数据的函数
-//         let mut update_flag_u = Decimal::ZERO;
-//         let fun = move |data: ResponseData| {
-//             let core_arc_cc = core_arc_clone.clone();
-//
-//             async move {
-//                 on_public_data(core_arc_cc, &mut update_flag_u, data).await
-//             }
-//         };
-//
-//         // 准备链接
-//         bg_public.set_subscribe(vec![BitgetSwapSubscribeType::PuBooks1]); // 只用订阅深度数据
-//         bg_public.set_symbols(symbols_clone);
-//         // bg_public.ws_connect_async(is_shutdown_arc_c1, fun, &write_tx_am_public, write_rx_public).await.expect("bitget_usdt_swap 链接有异常")
-//     });
-//
-//     // 不需要交易就不用开启私有频道了
-//     if !is_trade {
-//         return;
-//     }
-//
-//     // 开启私有频道
-//     let (write_tx_private, write_rx_private) = futures_channel::mpsc::unbounded();
-//
-//     // 开启公共连接
-//     let is_shutdown_arc_c1 = is_shutdown_arc.clone();
-//     let write_tx_am_private = Arc::new(Mutex::new(write_tx_private));
-//     spawn(async move {
-//         // 构建链接ws
-//         let mut bg_private = BitgetSwapWs::new_label(name.clone(),
-//                                                      is_colo,
-//                                                      Some(parse_btree_map_to_bitget_swap_login(exchange_params)),
-//                                                      BitgetSwapWsType::Private);
-//
-//         // 消费数据的函数
-//         let core_arc_clone = core_arc.clone();
-//         let run_symbol = symbols[0].clone();
-//         let ct_val = core_arc_clone.lock().await.platform_rest.get_self_market().ct_val;
-//         let fun = move |data: ResponseData| {
-//             let core_arc_cc = core_arc_clone.clone();
-//             let run_symbol_c = run_symbol.clone();
-//
-//             async move {
-//                 on_private_data(core_arc_cc, ct_val, data, &run_symbol_c).await
-//             }
-//         };
-//
-//         // 准备链接
-//         bg_private.set_subscribe(vec![
-//             BitgetSwapSubscribeType::PrOrders,
-//             BitgetSwapSubscribeType::PrAccount,
-//             BitgetSwapSubscribeType::PrPosition
-//         ]);
-//         bg_private.set_symbols(symbols.clone());
-//         bg_private.ws_connect_async(is_shutdown_arc_c1, fun, &write_tx_am_private, write_rx_private).await.expect("bitget_usdt_swap 链接有异常")
-//     });
-// }
-//
-// async fn on_private_data(core_arc_clone: Arc<Mutex<Core>>,
-//                          ct_val: Decimal,
-//                          response: ResponseData,
-//                          run_symbol: &String) {
-//     let mut trace_stack = TraceStack::new(response.time, response.ins);
-//     trace_stack.on_after_span_line();
-//
-//     // public类型,目前只考虑订单流数据
-//     match response.channel.as_str() {
-//         // "account" => {
-//         //     let account = standard::handle_info::HandleSwapInfo::handle_account_info(BitgetSwap, &response, run_symbol);
-//         //     let mut core = core_arc_clone.lock().await;
-//         //     core.update_equity(account).await;
-//         // },
-//         // "positions" => {
-//         //     let mut positions = standard::handle_info::HandleSwapInfo::handle_position(BitgetSwap, &response, &ct_val);
-//         //
-//         //     // bitget如果没有仓位不会给0,会给个空数组
-//         //     if positions.is_empty() {
-//         //         positions.push(Position {
-//         //             symbol: run_symbol.replace("_", "").to_uppercase(),
-//         //             margin_level: Default::default(),
-//         //             amount: Default::default(),
-//         //             frozen_amount: Default::default(),
-//         //             price: Default::default(),
-//         //             profit: Default::default(),
-//         //             position_mode: PositionModeEnum::Both,
-//         //             margin: Default::default(),
-//         //         });
-//         //     }
-//         //
-//         //     let mut core = core_arc_clone.lock().await;
-//         //     core.update_position(positions).await;
-//         // },
-//         // "orders" => {
-//         //     trace_stack.set_source("gate_swap.orders".to_string());
-//         //     let orders = standard::handle_info::HandleSwapInfo::handle_order(BitgetSwap, response.clone(), ct_val.clone());
-//         //
-//         //     let mut order_infos:Vec<OrderInfo> = Vec::new();
-//         //     for mut order in orders.order {
-//         //         if order.status == "NULL" {
-//         //             error!("bitget_usdt_swap 未识别的订单状态:{:?}", response);
-//         //
-//         //             continue;
-//         //         }
-//         //
-//         //         let order_info = OrderInfo::parse_order_to_order_info(&mut order);
-//         //         order_infos.push(order_info);
-//         //     }
-//         //
-//         //     {
-//         //         let mut core = core_arc_clone.lock().await;
-//         //         core.update_order(order_infos, trace_stack).await;
-//         //     }
-//         // },
-//         "pong" => {}
-//         _ => {
-//             info!("bitget_usdt_swap 113 未知的订阅数据: {:?}", response);
-//         }
-//     }
-// }
-//
-// async fn on_public_data(_core_arc_clone: Arc<Mutex<Core>>,
-//                         _update_flag_u: &mut Decimal,
-//                         response: ResponseData) {
-//     let mut trace_stack = TraceStack::new(response.time, response.ins);
-//     trace_stack.on_after_span_line();
-//
-//     // public类型,目前只考虑订单流数据
-//     match response.channel.as_str() {
-//         "books1" => {
-//             // trace_stack.set_source("bitget_usdt_swap.books1".to_string());
-//             // let special_depth = standard::handle_info::HandleSwapInfo::handle_special_depth(BitgetSwap, &response);
-//             // trace_stack.on_after_format();
-//             //
-//             // on_special_depth(core_arc_clone, update_flag_u, &response.label, &mut trace_stack, &special_depth).await;
-//         },
-//         "pong" => {},
-//         _ => {
-//             info!("bitget_usdt_swap 125 未知的订阅数据");
-//             info!(?response)
-//         }
-//     }
-// }
-//
-// fn parse_btree_map_to_bitget_swap_login(exchange_params: BTreeMap<String, String>) -> BitgetSwapLogin {
-//     BitgetSwapLogin {
-//         api_key: exchange_params.get("access_key").unwrap().clone(),
-//         secret_key: exchange_params.get("secret_key").unwrap().clone(),
-//         passphrase_key: exchange_params.get("pass_key").unwrap().clone(),
-//     }
-// }
+use std::collections::BTreeMap;
+use std::sync::Arc;
+use std::sync::atomic::AtomicBool;
+use rust_decimal::Decimal;
+use tokio::spawn;
+use tokio::sync::Mutex;
+use tracing::{error, info};
+use tokio_tungstenite::tungstenite::Message;
+use exchanges::bitget_swap_ws::{BitgetSwapLogin, BitgetSwapSubscribeType, BitgetSwapWs, BitgetSwapWsType};
+use exchanges::response_base::ResponseData;
+use global::trace_stack::TraceStack;
+use standard::exchange::ExchangeEnum::BitgetSwap;
+use standard::exchange_struct_handler::ExchangeStructHandler;
+use standard::{Depth, OrderBook};
+use crate::core::Core;
+use crate::exchange_disguise::{on_depth, on_record, on_ticker, on_trade};
+use crate::model::OrderInfo;
+
+pub async fn reference_bitget_swap_run(is_shutdown_arc: Arc<AtomicBool>,
+                                       core_arc: Arc<Mutex<Core>>,
+                                       name: String,
+                                       symbols: Vec<String>,
+                                       is_colo: bool) {
+    spawn(async move {
+        // 开启公共频道
+        let (write_tx, write_rx) = futures_channel::mpsc::unbounded::<Message>();
+        let mut ws = BitgetSwapWs::new_label(name, is_colo, None, BitgetSwapWsType::Public);
+        ws.set_subscribe(vec![
+            BitgetSwapSubscribeType::PuBooks1,
+            BitgetSwapSubscribeType::PuTrade,
+            BitgetSwapSubscribeType::PuKline("1".to_string()),
+        ]);
+
+
+        // 读取数据
+        let core_arc_clone = Arc::clone(&core_arc);
+        let mut rest = core_arc_clone.lock().await.platform_rest.clone_box();
+        let multiplier = rest.get_self_market().multiplier;
+        let mut records = rest.get_record("1".to_string()).await.unwrap();
+        for record in records.iter_mut() {
+            let core_arc_clone = core_arc.clone();
+
+            on_record(core_arc_clone, record).await
+        }
+
+        let depth_asks = Arc::new(Mutex::new(Vec::new()));
+        let depth_bids = Arc::new(Mutex::new(Vec::new()));
+
+        let fun = move |data: ResponseData| {
+            // 在 async 块之前克隆 Arc
+            let core_arc_cc = core_arc_clone.clone();
+            let mul = multiplier.clone();
+
+            let depth_asks = Arc::clone(&depth_asks);
+            let depth_bids = Arc::clone(&depth_bids);
+
+            async move {
+                let mut depth_asks = depth_asks.lock().await;
+                let mut depth_bids = depth_bids.lock().await;
+                // 使用克隆后的 Arc,避免 move 语义
+                on_public_data(core_arc_cc, &mul, &data, &mut depth_asks, &mut depth_bids).await
+            }
+        };
+
+        // 链接
+        let write_tx_am = Arc::new(Mutex::new(write_tx));
+        ws.set_symbols(symbols);
+        ws.ws_connect_async(is_shutdown_arc, fun, &write_tx_am, write_rx).await.expect("bitget_usdt_swap 链接有异常");
+    });
+}
+
+// 交易 bybit 合约 启动
+pub(crate) async fn bitget_swap_run(is_shutdown_arc: Arc<AtomicBool>,
+                                    core_arc: Arc<Mutex<Core>>,
+                                    name: String,
+                                    symbols: Vec<String>,
+                                    is_colo: bool,
+                                    exchange_params: BTreeMap<String, String>) {
+    spawn(async move {
+        let (write_tx, write_rx) = futures_channel::mpsc::unbounded();
+        let auth = Some(parse_btree_map_to_bitget_swap_login(exchange_params));
+        let mut ws = BitgetSwapWs::new_label(name.clone(), is_colo, auth, BitgetSwapWsType::Private);
+        ws.set_subscribe(vec![
+            BitgetSwapSubscribeType::PrOrders,
+            BitgetSwapSubscribeType::PrAccount,
+            BitgetSwapSubscribeType::PrPosition,
+        ]);
+
+        let core_arc_clone_private = core_arc.clone();
+        let multiplier = core_arc_clone_private.lock().await.platform_rest.get_self_market().multiplier;
+        let run_symbol = symbols.clone()[0].clone();
+
+        // 挂起私有ws
+        let fun = move |data: ResponseData| {
+            // 在 async 块之前克隆 Arc
+            let core_arc_cc = core_arc_clone_private.clone();
+            let mul = multiplier.clone();
+            let rs = run_symbol.clone();
+
+            async move {
+                // 使用克隆后的 Arc,避免 move 语义
+                on_private_data(core_arc_cc, &mul, &rs, &data).await;
+            }
+        };
+
+        // 链接
+        let write_tx_am = Arc::new(Mutex::new(write_tx));
+        ws.set_symbols(symbols);
+        ws.ws_connect_async(is_shutdown_arc, fun, &write_tx_am, write_rx).await.expect("bitget_usdt_swap 链接有异常");
+    });
+}
+
+async fn on_private_data(core_arc_clone: Arc<Mutex<Core>>, ct_val: &Decimal, run_symbol: &String, response: &ResponseData) {
+    let mut trace_stack = TraceStack::new(response.time, response.ins);
+    trace_stack.on_after_span_line();
+
+    match response.channel.as_str() {
+        "wallet" => {
+            let account = ExchangeStructHandler::account_info_handle(BitgetSwap, response, run_symbol);
+            let mut core = core_arc_clone.lock().await;
+            core.update_equity(account).await;
+        }
+        "order" => {
+            let orders = ExchangeStructHandler::order_handle(BitgetSwap, response, ct_val);
+            trace_stack.on_after_format();
+
+            let mut order_infos: Vec<OrderInfo> = Vec::new();
+            for mut order in orders.order {
+                if order.status == "NULL" {
+                    error!("bitget_usdt_swap 未识别的订单状态:{:?}", response);
+                    continue;
+                }
+
+                if order.deal_amount != Decimal::ZERO {
+                    info!("bitget order 消息原文:{:?}", response);
+                }
+
+                let order_info = OrderInfo::parse_order_to_order_info(&mut order);
+                order_infos.push(order_info);
+            }
+
+            let mut core = core_arc_clone.lock().await;
+            core.update_order(order_infos, trace_stack).await;
+        }
+        "position" => {
+            let positions = ExchangeStructHandler::position_handle(BitgetSwap, response, ct_val);
+            let mut core = core_arc_clone.lock().await;
+            core.update_position(positions).await;
+        }
+        _ => {
+            error!("未知推送类型");
+            error!(?response);
+        }
+    }
+}
+
+async fn on_public_data(core_arc: Arc<Mutex<Core>>, mul: &Decimal, response: &ResponseData, depth_asks: &mut Vec<OrderBook>, depth_bids: &mut Vec<OrderBook>) {
+    let mut trace_stack = TraceStack::new(response.time, response.ins);
+    trace_stack.on_after_span_line();
+
+    match response.channel.as_str() {
+        "orderbook" => {
+            trace_stack.set_source("bitget_usdt_swap.bookTicker".to_string());
+
+            let mut is_update = false;
+            if response.data_type == "delta" {
+                is_update = true;
+            }
+            let mut depth = ExchangeStructHandler::book_ticker_handle(BitgetSwap, &response, mul);
+            // 是增量更新
+            if is_update {
+                if depth.asks.len() != 0 {
+                    depth_asks.clear();
+                    depth_asks.append(&mut depth.asks);
+                } else if depth.bids.len() != 0 {
+                    depth_bids.clear();
+                    depth_bids.append(&mut depth.bids);
+                }
+
+                let result_depth = Depth {
+                    time: depth.time,
+                    symbol: depth.symbol,
+                    asks: depth_asks.clone(),
+                    bids: depth_bids.clone(),
+                };
+
+                trace_stack.on_after_format();
+                on_depth(core_arc, &response.label, &mut trace_stack, &result_depth).await;
+            }
+            // 全量
+            else {
+                trace_stack.on_after_format();
+                on_depth(core_arc, &response.label, &mut trace_stack, &depth).await;
+
+                depth_asks.clear();
+                depth_asks.append(&mut depth.asks);
+                depth_bids.clear();
+                depth_bids.append(&mut depth.bids);
+            }
+        }
+        "trade" => {
+            trace_stack.set_source("bitget_usdt_swap.trade".to_string());
+
+            let mut trades = ExchangeStructHandler::trades_handle(BitgetSwap, response, mul);
+            trace_stack.on_after_format();
+
+            for trade in trades.iter_mut() {
+                let core_arc_clone = core_arc.clone();
+
+                on_trade(core_arc_clone, &response.label, &mut trace_stack, &trade).await;
+            }
+        }
+        "tickers" => {
+            trace_stack.set_source("bitget_usdt_swap.tickers".to_string());
+            let ticker = ExchangeStructHandler::ticker_handle(BitgetSwap, response).await;
+            trace_stack.on_after_format();
+
+            on_ticker(core_arc, &mut trace_stack, &ticker).await;
+        }
+        // k线数据
+        "kline" => {
+            let mut records = ExchangeStructHandler::records_handle(BitgetSwap, &response);
+
+            if records.is_empty() {
+                return;
+            }
+
+            for record in records.iter_mut() {
+                let core_arc_clone = core_arc.clone();
+
+                on_record(core_arc_clone, record).await
+            }
+        }
+        _ => {
+            error!("未知推送类型");
+            error!(?response);
+        }
+    }
+}
+
+fn parse_btree_map_to_bitget_swap_login(exchange_params: BTreeMap<String, String>) -> BitgetSwapLogin {
+    BitgetSwapLogin {
+        api_key: exchange_params.get("access_key").unwrap().clone(),
+        secret_key: exchange_params.get("secret_key").unwrap().clone(),
+        passphrase_key: exchange_params.get("pass_key").unwrap().clone(),
+    }
+}

+ 10 - 11
strategy/src/clear_core.rs

@@ -18,7 +18,7 @@ use global::params::Params;
 use global::trace_stack::TraceStack;
 use standard::{Account, Market, Order, Platform, Position, PositionModeEnum, SpecialTicker};
 use standard::exchange::{Exchange};
-use standard::exchange::ExchangeEnum::{BinanceSwap, GateSwap};
+use standard::exchange::ExchangeEnum::{BinanceSwap, GateSwap, BitgetSwap};
 
 use crate::model::{LocalPosition, OrderInfo};
 use crate::avellaneda_stoikov::AvellanedaStoikov;
@@ -207,9 +207,9 @@ impl ClearCore {
                 // "bitget_spot" => {
                 //     Exchange::new(BitgetSpot, symbol, params.colo != 0i8, exchange_params, order_sender, error_sender).await
                 // }
-                // "bitget_usdt_swap" => {
-                //     Exchange::new(BitgetSwap, symbol, params.colo != 0i8, exchange_params, order_sender, error_sender).await
-                // }
+                "bitget_usdt_swap" => {
+                    Exchange::new(BitgetSwap, symbol, params.colo != 0i8, exchange_params, order_sender, error_sender).await
+                }
                 // "okex_usdt_swap" => {
                 //     Exchange::new(OkxSwap, symbol, params.colo != 0i8, exchange_params, order_sender, error_sender).await
                 // }
@@ -413,7 +413,7 @@ impl ClearCore {
                 let length = val.len();
                 result.clear_order_num = length.to_string();
                 result.clear_order_str = format!("清空所有挂单:{:?}", val);
-                if length > 0{
+                if length > 0 {
                     info!("已清空所有挂单({}条)", length);
                     for o in val {
                         info!("    {:?}", o);
@@ -427,7 +427,7 @@ impl ClearCore {
                         let length = val.len();
                         result.clear_order_num = length.to_string();
                         result.clear_order_str = format!("清空所有挂单(备用):{:?}", val);
-                        if length > 0{
+                        if length > 0 {
                             info!("清空所有挂单({}条):{:?}", length, val);
                         }
                     }
@@ -485,14 +485,14 @@ impl ClearCore {
                         Ok(order) => {
                             ts.on_after_send();
                             info!("    {}仓位清除市价下单成功 {:?}, {}", position.symbol.clone(), order, ts.to_string());
-                            result.clear_position_str = format!("{} >仓位信息:{:?} 下单信息: {:?}",result.clear_position_str, position, order);
+                            result.clear_position_str = format!("{} >仓位信息:{:?} 下单信息: {:?}", result.clear_position_str, position, order);
                             // 执行完当前币对  结束循环
                             continue;
                         }
                         Err(error) => {
                             // ts.on_after_send();
                             error!("    {}仓位清除市价下单异常 {}, {}", position.symbol.clone(), error, ts.to_string());
-                            result.clear_other_str = format!("{} >仓位信息:{:?} 下单异常信息: {:?}",result.clear_other_str, position, error);
+                            result.clear_other_str = format!("{} >仓位信息:{:?} 下单异常信息: {:?}", result.clear_other_str, position, error);
                             // 执行完当前币对  结束循环
                             continue;
                         }
@@ -520,7 +520,7 @@ impl ClearCore {
         result.r_id = r_id;
         info!("清仓程序结果 {:?}", result);
         // 判断是否有清仓,是否有异常
-        if result.clear_position_num != "0" || result.clear_order_num != "0" || result.clear_other_err{
+        if result.clear_position_num != "0" || result.clear_order_num != "0" || result.clear_other_err {
             info!("上报了清仓信息!!!");
             send_clear_msg_request(&result).await;
             // 上报清仓日志
@@ -601,7 +601,6 @@ impl ClearCore {
 
         // 买入平台币
         if self.exchange.contains("spot") { // 现货
-
         }
 
         // 清空挂单和仓位
@@ -639,7 +638,7 @@ pub async fn send_clear_msg_request(body_params: &ClearPositionResult) {
             } else {
                 println!("清仓结果上报中控,请求失败: 响应异常码 {},响应文本 {}", status, response_text);
             }
-        },
+        }
         Err(e) => {
             error!("清仓结果上报中控,请求发送失败,异常:{}", e)
         }

+ 13 - 13
strategy/src/core.rs

@@ -20,7 +20,7 @@ use global::params::Params;
 use global::trace_stack::TraceStack;
 use standard::{Account, Depth, Market, Order, OrderCommand, Platform, Position, PositionModeEnum, Record, SpecialTicker, Ticker, Trade};
 use standard::exchange::{Exchange};
-use standard::exchange::ExchangeEnum::{BinanceSwap, BybitSwap, GateSwap};
+use standard::exchange::ExchangeEnum::{BinanceSwap, BybitSwap, BitgetSwap, GateSwap};
 
 use crate::model::{LocalPosition, OrderInfo, TokenParam};
 use crate::avellaneda_stoikov::AvellanedaStoikov;
@@ -209,9 +209,9 @@ impl Core {
                 // "bitget_spot" => {
                 //     Exchange::new(BitgetSpot, symbol, params.colo != 0i8, exchange_params, order_sender, error_sender).await
                 // }
-                // "bitget_usdt_swap" => {
-                //     Exchange::new(BitgetSwap, symbol, params.colo != 0i8, exchange_params, order_sender, error_sender).await
-                // }
+                "bitget_usdt_swap" => {
+                    Exchange::new(BitgetSwap, symbol, params.colo != 0i8, exchange_params, order_sender, error_sender).await
+                }
                 // "okex_usdt_swap" => {
                 //     Exchange::new(OkxSwap, symbol, params.colo != 0i8, exchange_params, order_sender, error_sender).await
                 // }
@@ -383,7 +383,7 @@ impl Core {
                                 self.local_cash -= filled * filled_price;
                                 self.local_coin = filled - fee;
 
-                            // sell 平多
+                                // sell 平多
                             } else if side == "pd" {
                                 self.local_sell_amount += filled;
                                 self.local_sell_value += filled * filled_price;
@@ -398,7 +398,7 @@ impl Core {
                                 self.local_cash += filled * filled_price - fee;
                                 self.local_coin -= filled;
 
-                            // buy 平空
+                                // buy 平空
                             } else if side == "pk" {
                                 self.local_buy_amount += filled - fee;
                                 self.local_buy_value += (filled - fee) * filled_price;
@@ -413,7 +413,7 @@ impl Core {
                                 self.local_cash -= filled * filled_price;
                                 self.local_coin += filled - fee;
 
-                            // sell 开空
+                                // sell 开空
                             } else if side == "kk" {
                                 self.local_sell_amount += filled;
                                 self.local_sell_value += filled * filled_price;
@@ -432,7 +432,7 @@ impl Core {
                                 info!("错误的仓位方向{}", side);
                             }
 
-                        // 合约订单流仓位计算
+                            // 合约订单流仓位计算
                         } else {
                             // buy 开多
                             if side == "kd" {
@@ -448,7 +448,7 @@ impl Core {
                                     self.local_position_by_orders.long_pos = self.local_position_by_orders.long_pos + filled;
                                 }
 
-                            // sell 开空
+                                // sell 开空
                             } else if side == "kk" {
                                 self.local_sell_amount += filled;
                                 self.local_sell_value += filled * filled_price;
@@ -461,7 +461,7 @@ impl Core {
                                     self.local_position_by_orders.short_pos = self.local_position_by_orders.short_pos + filled;
                                 }
 
-                            // sell 平多
+                                // sell 平多
                             } else if side == "pd" {
                                 self.local_sell_amount += filled;
                                 self.local_sell_value += filled * filled_price;
@@ -470,7 +470,7 @@ impl Core {
                                     self.local_position_by_orders.long_avg = Decimal::ZERO;
                                 }
 
-                            // buy 平空
+                                // buy 平空
                             } else if side == "pk" {
                                 self.local_buy_amount += filled;
                                 self.local_buy_value += filled * filled_price;
@@ -1579,14 +1579,14 @@ impl Core {
             if clear_count >= 1 {
                 info!("连续{}次清理完成。", clear_count);
                 info!("");
-                break
+                break;
             }
 
             // 最大次数判定
             if total_clear_count >= 500 {
                 info!("清理次数达到上限:{}次,不再执行清理。", total_clear_count);
                 info!("");
-                break
+                break;
             }
 
             clear_count += 1;

+ 7 - 6
strategy/src/exchange_disguise.rs

@@ -6,6 +6,7 @@ use global::trace_stack::TraceStack;
 use standard::{Depth, Record, Ticker, Trade};
 use crate::binance_usdt_swap::{binance_swap_run, reference_binance_swap_run};
 use crate::bybit_usdt_swap::{bybit_swap_run, reference_bybit_swap_run};
+use crate::bitget_usdt_swap::{bitget_swap_run, reference_bitget_swap_run};
 use crate::coinex_usdt_swap::coinex_swap_run;
 use crate::gate_usdt_swap::gate_swap_run;
 use crate::core::Core;
@@ -34,9 +35,9 @@ pub async fn run_transactional_exchange(is_shutdown_arc :Arc<AtomicBool>,
         // "bitget_spot" => {
         //     bitget_spot_run(is_shutdown_arc,true, core_arc, name, symbols, is_colo, exchange_params).await;
         // },
-        // "bitget_usdt_swap" => {
-        //     bitget_usdt_swap_run(is_shutdown_arc, true, core_arc, name, symbols, is_colo, exchange_params).await;
-        // }
+        "bitget_usdt_swap" => {
+            bitget_swap_run(is_shutdown_arc, core_arc, name, symbols, is_colo, exchange_params).await;
+        }
         "bybit_usdt_swap" => {
             bybit_swap_run(is_shutdown_arc, core_arc, name, symbols, is_colo, exchange_params).await;
         }
@@ -83,9 +84,9 @@ pub async fn run_reference_exchange(is_shutdown_arc: Arc<AtomicBool>,
         // "bitget_spot" => {
         //     bitget_spot_run(is_shutdown_arc, false, core_arc, name, symbols, is_colo, exchange_params).await;
         // },
-        // "bitget_usdt_swap" => {
-        //     bitget_usdt_swap_run(is_shutdown_arc, false, core_arc, name, symbols, is_colo, exchange_params).await;
-        // }
+        "bitget_usdt_swap" => {
+            reference_bitget_swap_run(is_shutdown_arc, core_arc, name, symbols, is_colo).await;
+        }
         "bybit_usdt_swap" => {
             reference_bybit_swap_run(is_shutdown_arc,  core_arc, name, symbols, is_colo).await;
         },

+ 3 - 1
strategy/src/strategy.rs

@@ -862,7 +862,6 @@ impl Strategy {
     pub fn _check_local_orders(&mut self,
                                command: &mut OrderCommand,
                                local_orders: &HashMap<String, OrderInfo>) {
-        // debug!(?command);
         // 超时检测
         if self.local_time - self._check_local_orders_time < self._check_local_orders_interval {
             return;
@@ -996,6 +995,9 @@ impl Strategy {
             // target_sell_price = utils::clip(target_sell_price, self.bp * dec!(0.9995), self.ap * dec!(1.03));
             // 取消大小限制
             target_sell_price = utils::fix_price(target_sell_price, self.tick_size);
+
+
+            println!("-0000000000000000000000000000        {},{},{}",self.min_amount_value,target_sell_price,self.step_size);
             let amount = if predictor.inventory >= dec!(3) {
                 utils::get_amount_by_min_amount_value(self.min_amount_value * predictor.inventory.abs(), target_sell_price, self.step_size)
             } else {