Forráskód Böngészése

币对倍数转换处理

gepangpang 1 éve
szülő
commit
df325dfedc

+ 1 - 0
global/src/lib.rs

@@ -5,3 +5,4 @@ pub mod trace_stack;
 pub mod export_utils;
 pub mod account_info;
 pub mod cci;
+pub mod utils;

+ 15 - 0
global/src/utils.rs

@@ -0,0 +1,15 @@
+use std::str::FromStr;
+use rust_decimal::Decimal;
+
+pub fn get_symbol_multiplier(symbol: String) -> Decimal {
+    let is_multiplier = symbol.starts_with("1000");
+    if is_multiplier {
+        match (symbol.find('1'), symbol.rfind('0')) {
+            (Some(start_pos), Some(end_pos)) if start_pos <= end_pos => {
+                let result = &symbol[start_pos..=end_pos];
+                Decimal::from_str(result).unwrap()
+            }
+            _ => Decimal::ONE
+        }
+    } else { Decimal::ONE }
+}

+ 12 - 11
src/core_libs.rs

@@ -1,4 +1,3 @@
-
 use strategy::core::Core;
 use std::collections::BTreeMap;
 use std::io::Error;
@@ -13,6 +12,7 @@ use tracing::{error, info};
 use global::cci::CentralControlInfo;
 use global::params::Params;
 use global::trace_stack::TraceStack;
+use global::utils::get_symbol_multiplier;
 use standard::Order;
 use strategy::model::OrderInfo;
 
@@ -21,7 +21,7 @@ pub async fn init(params: Params,
                   running: Arc<AtomicBool>,
                   cci_arc: Arc<Mutex<CentralControlInfo>>) -> Arc<Mutex<Core>> {
     // 封装
-    let mut exchange_params:BTreeMap<String, String> = BTreeMap::new();
+    let mut exchange_params: BTreeMap<String, String> = BTreeMap::new();
     exchange_params.insert("access_key".to_string(), params.access_key.clone());
     exchange_params.insert("secret_key".to_string(), params.secret_key.clone());
     exchange_params.insert("pass_key".to_string(), params.pass_key.clone());
@@ -30,19 +30,19 @@ pub async fn init(params: Params,
     let (error_sender, mut error_receiver) = mpsc::channel::<Error>(100);
 
     let mut core_obj = Core::new(params.exchange.clone(),
-                                   params.clone(),
-                                   exchange_params.clone(),
-                                   order_sender.clone(),
-                                   error_sender.clone(),
-                                   running.clone(),
-                                   cci_arc.clone()).await;
+                                 params.clone(),
+                                 exchange_params.clone(),
+                                 order_sender.clone(),
+                                 error_sender.clone(),
+                                 running.clone(),
+                                 cci_arc.clone()).await;
     let ref_name = core_obj.ref_name[0].clone();
     let trade_name = core_obj.trade_name.clone();
 
     info!("core初始化……");
     core_obj.before_trade().await;
     let core_arc = Arc::new(Mutex::new(core_obj));
-
+    let symbol_multiplier = get_symbol_multiplier(params.ref_pair.get(0).unwrap().clone()) / get_symbol_multiplier(params.pair.clone());
     // 参考交易所
     exchange_disguise::run_reference_exchange(ws_running.clone(),
                                               params.ref_exchange.get(0).unwrap().clone(),
@@ -50,6 +50,7 @@ pub async fn init(params: Params,
                                               ref_name,
                                               params.ref_pair.clone(),
                                               params.colo != 0i8,
+                                              symbol_multiplier,
                                               exchange_params.clone()).await;
     // 交易交易所
     exchange_disguise::run_transactional_exchange(ws_running.clone(),
@@ -98,7 +99,7 @@ pub async fn init(params: Params,
 
                         core.update_local_order(order_info.clone(), trace_stack).await;
                     }
-                },
+                }
                 None => {
                     error!("Order channel has been closed!");
                 }
@@ -116,7 +117,7 @@ pub async fn init(params: Params,
                     // let mut core = _error_handler_core_arc.lock().await;
                     // error!("main: 订单出现错误{:?}", _error);
                     // core.strategy._print_summary();
-                },
+                }
                 None => {
                     error!("Error channel has been closed!");
                 }

+ 5 - 5
standard/src/binance_swap_handle.rs

@@ -7,10 +7,10 @@ use crate::{MarketOrder, SpecialDepth, SpecialTicker};
 
 
 // 处理特殊Ticker信息
-pub fn handle_book_ticker(res_data: &ResponseData) -> SpecialDepth {
-    let bp = Decimal::from_str((*res_data).data["b"].as_str().unwrap()).unwrap();
+pub fn handle_book_ticker(res_data: &ResponseData, symbol_multiplier: Decimal) -> SpecialDepth {
+    let bp = Decimal::from_str((*res_data).data["b"].as_str().unwrap()).unwrap() / symbol_multiplier;
     let bq = Decimal::from_str((*res_data).data["B"].as_str().unwrap()).unwrap();
-    let ap = Decimal::from_str((*res_data).data["a"].as_str().unwrap()).unwrap();
+    let ap = Decimal::from_str((*res_data).data["a"].as_str().unwrap()).unwrap() / symbol_multiplier;
     let aq = Decimal::from_str((*res_data).data["A"].as_str().unwrap()).unwrap();
     let mp = (bp + ap) * dec!(0.5);
     let t = Decimal::from_str(&(*res_data).data["u"].to_string()).unwrap();
@@ -28,11 +28,11 @@ pub fn handle_book_ticker(res_data: &ResponseData) -> SpecialDepth {
 }
 
 // 格式化深度信息
-pub fn format_depth_items(value: Value) -> Vec<MarketOrder> {
+pub fn format_depth_items(value: Value, symbol_multiplier: Decimal) -> Vec<MarketOrder> {
     let mut depth_items: Vec<MarketOrder> = vec![];
     for value in value.as_array().unwrap() {
         depth_items.push(MarketOrder {
-            price: Decimal::from_str(value[0].as_str().unwrap()).unwrap(),
+            price: Decimal::from_str(value[0].as_str().unwrap()).unwrap() / symbol_multiplier,
             amount: Decimal::from_str(value[1].as_str().unwrap()).unwrap(),
         })
     }

+ 6 - 6
standard/src/bitget_swap_handle.rs

@@ -13,7 +13,7 @@ pub fn handle_account_info(response: &ResponseData, _symbol: &String) -> Account
 
     for data in response.data.as_array().unwrap() {
         if data["marginCoin"].as_str().unwrap() != "USDT" {
-            continue
+            continue;
         }
 
         // 格式化account信息
@@ -88,11 +88,11 @@ pub fn format_order_item(order: Value, ct_val: Decimal) -> Order {
 }
 
 // 格式化深度信息
-pub fn format_depth_items(value: Value) -> Vec<MarketOrder> {
+pub fn format_depth_items(value: Value, symbol_multiplier: Decimal) -> Vec<MarketOrder> {
     let mut depth_items: Vec<MarketOrder> = vec![];
     for value in value.as_array().unwrap() {
         depth_items.push(MarketOrder {
-            price: Decimal::from_str(value[0].as_str().unwrap()).unwrap(),
+            price: Decimal::from_str(value[0].as_str().unwrap()).unwrap() / symbol_multiplier,
             amount: Decimal::from_str(value[1].as_str().unwrap()).unwrap(),
         })
     }
@@ -120,16 +120,16 @@ 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())
         }

+ 9 - 9
standard/src/bybit_swap_handle.rs

@@ -15,13 +15,13 @@ pub fn handle_account_info(res_data: &ResponseData, symbol: &String) -> Account
 }
 
 pub fn format_account_info(data: Vec<Value>, symbol: &String) -> Account {
-    let account = data.iter().find(| &item | item["accountType"] == "UNIFIED");
+    let account = data.iter().find(|&item| item["accountType"] == "UNIFIED");
     match account {
         None => {
             error!("Bybit:格式化统一账户信息错误!\nformat_account_info: data={:?}", data);
             panic!("Bybit:格式化统一账户信息错误!\nformat_account_info: data={:?}", data)
         }
-        Some(val) =>{
+        Some(val) => {
             let arr: Vec<Value> = from_value(val["coin"].clone()).unwrap();
             let upper_str = symbol.to_uppercase();
             let symbol_array: Vec<&str> = upper_str.split("_").collect();
@@ -64,7 +64,7 @@ pub fn format_position_item(position: &Value, ct_val: &Decimal) -> Position {
             panic!("bybit_swap:格式化持仓模式错误!\nformat_position_item:position={:?}", position)
         }
     };
-    let symbol_mapper =  position["symbol"].as_str().unwrap().to_string();
+    let symbol_mapper = position["symbol"].as_str().unwrap().to_string();
     let currency = "USDT";
     let coin = &symbol_mapper[..symbol_mapper.find(currency).unwrap_or(0)];
     let size_str: String = from_value(position["size"].clone()).unwrap();
@@ -81,7 +81,7 @@ pub fn format_position_item(position: &Value, ct_val: &Decimal) -> Position {
         _ => {}
     }
     Position {
-        symbol: format!{"{}_{}", coin, currency},
+        symbol: format! {"{}_{}", coin, currency},
         margin_level: Decimal::from_str(position["leverage"].as_str().unwrap()).unwrap(),
         amount,
         frozen_amount: Decimal::ZERO,
@@ -138,9 +138,9 @@ pub fn format_order_item(order: Value, ct_val: Decimal) -> Order {
 }
 
 // 处理特殊Ticket信息
-pub fn handle_ticker(res_data: &ResponseData) -> SpecialDepth {
-    let ap = Decimal::from_str(res_data.data["ask1Price"].as_str().unwrap()).unwrap();
-    let bp = Decimal::from_str(res_data.data["bid1Price"].as_str().unwrap()).unwrap();
+pub fn handle_ticker(res_data: &ResponseData, symbol_multiplier: Decimal) -> SpecialDepth {
+    let ap = Decimal::from_str(res_data.data["ask1Price"].as_str().unwrap()).unwrap() / symbol_multiplier;
+    let bp = Decimal::from_str(res_data.data["bid1Price"].as_str().unwrap()).unwrap() / symbol_multiplier;
     let aq = Decimal::from_str(res_data.data["ask1Size"].as_str().unwrap()).unwrap();
     let bq = Decimal::from_str(res_data.data["bid1Size"].as_str().unwrap()).unwrap();
     let mp = (bp + ap) * dec!(0.5);
@@ -159,12 +159,12 @@ pub fn handle_ticker(res_data: &ResponseData) -> SpecialDepth {
     }
 }
 
-pub fn format_depth_items(value: serde_json::Value) -> Vec<MarketOrder> {
+pub fn format_depth_items(value: Value, symbol_multiplier: Decimal) -> Vec<MarketOrder> {
     let mut depth_items: Vec<MarketOrder> = vec![];
     for val in value.as_array().unwrap() {
         let arr = val.as_array().unwrap();
         depth_items.push(MarketOrder {
-            price: Decimal::from_str(arr[0].as_str().unwrap()).unwrap(),
+            price: Decimal::from_str(arr[0].as_str().unwrap()).unwrap() / symbol_multiplier,
             amount: Decimal::from_str(arr[1].as_str().unwrap()).unwrap(),
         })
     }

+ 9 - 9
standard/src/coinex_swap_handle.rs

@@ -26,7 +26,7 @@ pub fn format_account_info(data: &Vec<Value>, symbol: &String) -> Account {
             panic!("Coinex:格式化账号信息错误!\nformat_account_info: data={:?}", data)
         }
         Some(value) => {
-            let frozen_balance= Decimal::from_str(&value["frozen"].as_str().unwrap()).unwrap();
+            let frozen_balance = Decimal::from_str(&value["frozen"].as_str().unwrap()).unwrap();
             let available_balance = Decimal::from_str(&value["available"].as_str().unwrap()).unwrap();
             let margin = Decimal::from_str(&value["margin"].as_str().unwrap()).unwrap();
             // let profit_unreal = Decimal::from_str(&value["unrealized_pnl"].as_str().unwrap()).unwrap();
@@ -47,7 +47,7 @@ pub fn format_account_info(data: &Vec<Value>, symbol: &String) -> Account {
 // 处理position信息
 pub fn handle_position(res_data: &ResponseData, ct_val: &Decimal) -> Vec<Position> {
     let res_data_json = &res_data.data["position"];
-    let position =  format_position_item(res_data_json, ct_val);
+    let position = format_position_item(res_data_json, ct_val);
     vec![position]
 }
 
@@ -96,8 +96,8 @@ pub fn format_order_item(order: &Value, ct_val: Decimal, status: &str) -> Order
     let filled_value = Decimal::from_str(order["filled_value"].as_str().unwrap()).unwrap();
     // 成交均价
     let mut avg_price = Decimal::ZERO;
-    if filled_amount > Decimal::ZERO{
-        avg_price = filled_value/filled_amount;
+    if filled_amount > Decimal::ZERO {
+        avg_price = filled_value / filled_amount;
     }
     let amount = size * ct_val;
     let deal_amount = filled_amount * ct_val;
@@ -119,12 +119,12 @@ pub fn format_order_item(order: &Value, ct_val: Decimal, status: &str) -> Order
 }
 
 // 处理特殊Ticket信息
-pub fn handle_ticker(res_data: &ResponseData) -> SpecialDepth {
+pub fn handle_ticker(res_data: &ResponseData, symbol_multiplier: Decimal) -> SpecialDepth {
     let depth = &res_data.data["depth"];
 
-    let bp = Decimal::from_str(depth["bids"][0][0].as_str().unwrap()).unwrap();
+    let bp = Decimal::from_str(depth["bids"][0][0].as_str().unwrap()).unwrap() / symbol_multiplier;
     let bq = Decimal::from_str(depth["bids"][0][1].as_str().unwrap()).unwrap();
-    let ap = Decimal::from_str(depth["asks"][0][0].as_str().unwrap()).unwrap();
+    let ap = Decimal::from_str(depth["asks"][0][0].as_str().unwrap()).unwrap() / symbol_multiplier;
     let aq = Decimal::from_str(depth["asks"][0][1].as_str().unwrap()).unwrap();
     let mp = (bp + ap) * dec!(0.5);
     let t = Decimal::from_i64(depth.get("checksum").unwrap().as_i64().unwrap_or(0i64)).unwrap();
@@ -142,7 +142,7 @@ pub fn handle_ticker(res_data: &ResponseData) -> SpecialDepth {
     }
 }
 
-pub fn format_depth_items(value: &Value) -> Vec<MarketOrder> {
+pub fn format_depth_items(value: &Value, symbol_multiplier: Decimal) -> Vec<MarketOrder> {
     if value.is_null() {
         return vec![];
     }
@@ -150,7 +150,7 @@ pub fn format_depth_items(value: &Value) -> Vec<MarketOrder> {
     for value in value.as_array().unwrap() {
         let values = value.as_array().unwrap();
         depth_items.push(MarketOrder {
-            price: Decimal::from_str(values[0].as_str().unwrap()).unwrap(),
+            price: Decimal::from_str(values[0].as_str().unwrap()).unwrap() / symbol_multiplier,
             amount: Decimal::from_str(values[1].as_str().unwrap()).unwrap(),
         })
     }

+ 5 - 5
standard/src/gate_swap_handle.rs

@@ -120,10 +120,10 @@ pub fn format_order_item(order: serde_json::Value, ct_val: Decimal) -> Order {
     return rst_order;
 }
 // 处理特殊Ticket信息
-pub fn handle_book_ticker(res_data: &ResponseData) -> SpecialDepth {
-    let bp = Decimal::from_str((*res_data).data["b"].as_str().unwrap_or("0")).unwrap();
+pub fn handle_book_ticker(res_data: &ResponseData, symbol_multiplier: Decimal) -> SpecialDepth {
+    let bp = Decimal::from_str((*res_data).data["b"].as_str().unwrap_or("0")).unwrap() / symbol_multiplier;
     let bq = Decimal::from_f64((*res_data).data["B"].as_f64().unwrap()).unwrap();
-    let ap = Decimal::from_str((*res_data).data["a"].as_str().unwrap_or("0")).unwrap();
+    let ap = Decimal::from_str((*res_data).data["a"].as_str().unwrap_or("0")).unwrap() / symbol_multiplier;
     let aq = Decimal::from_f64((*res_data).data["A"].as_f64().unwrap()).unwrap();
     let mp = (bp + ap) * dec!(0.5);
     let t = Decimal::from_u64((*res_data).data["u"].as_u64().unwrap()).unwrap();
@@ -141,11 +141,11 @@ pub fn handle_book_ticker(res_data: &ResponseData) -> SpecialDepth {
     }
 }
 
-pub fn format_depth_items(value: &Value) -> Vec<MarketOrder> {
+pub fn format_depth_items(value: &Value, symbol_multiplier: Decimal) -> Vec<MarketOrder> {
     let mut depth_items: Vec<MarketOrder> = vec![];
     for value in value.as_array().unwrap() {
         depth_items.push(MarketOrder {
-            price: Decimal::from_str(value["p"].as_str().unwrap()).unwrap(),
+            price: Decimal::from_str(value["p"].as_str().unwrap()).unwrap() / symbol_multiplier,
             amount: Decimal::from_f64(value["s"].as_f64().unwrap()).unwrap(),
         })
     }

+ 35 - 35
standard/src/handle_info.rs

@@ -18,7 +18,7 @@ pub struct DepthParam {
     pub depth_asks: Vec<MarketOrder>,
     pub depth_bids: Vec<MarketOrder>,
     pub t: Decimal,
-    pub create_at: i64
+    pub create_at: i64,
 }
 
 #[allow(dead_code)]
@@ -47,7 +47,7 @@ impl HandleSwapInfo {
             // },
             ExchangeEnum::BitgetSwap => {
                 bitget_swap_handle::handle_account_info(res_data, symbol)
-            },
+            }
             ExchangeEnum::BybitSwap => {
                 bybit_swap_handle::handle_account_info(res_data, symbol)
             }
@@ -64,19 +64,19 @@ impl HandleSwapInfo {
         }
     }
     // 处理特殊Ticket信息
-    pub fn handle_book_ticker(exchange: ExchangeEnum, res_data: &ResponseData) -> SpecialDepth {
+    pub fn handle_book_ticker(exchange: ExchangeEnum, res_data: &ResponseData, symbol_multiplier: Decimal) -> SpecialDepth {
         match exchange {
             // ExchangeEnum::BinanceSpot => {
             //     binance_spot_handle::handle_special_ticker(res_data)
             // }
             ExchangeEnum::BinanceSwap => {
-                binance_swap_handle::handle_book_ticker(res_data)
+                binance_swap_handle::handle_book_ticker(res_data, symbol_multiplier)
             }
             ExchangeEnum::GateSwap => {
-                gate_swap_handle::handle_book_ticker(res_data)
+                gate_swap_handle::handle_book_ticker(res_data, symbol_multiplier)
             }
             ExchangeEnum::KucoinSwap => {
-                kucoin_handle::handle_book_ticker(res_data)
+                kucoin_handle::handle_book_ticker(res_data, symbol_multiplier)
             }
             // ExchangeEnum::KucoinSpot => {
             //     kucoin_spot_handle::handle_special_ticker(res_data)
@@ -94,12 +94,12 @@ impl HandleSwapInfo {
                 info!(?res_data);
                 panic!("BitgetSwap 85 未实现格式化");
                 // bitget_swap_handle::handle_special_ticker(res_data)
-            },
+            }
             ExchangeEnum::BybitSwap => {
-                bybit_swap_handle::handle_ticker(res_data)
+                bybit_swap_handle::handle_ticker(res_data, symbol_multiplier)
             }
             ExchangeEnum::CoinexSwap => {
-                coinex_swap_handle::handle_ticker(res_data)
+                coinex_swap_handle::handle_ticker(res_data, symbol_multiplier)
             }
             ExchangeEnum::HtxSwap => {
                 SpecialDepth::new()
@@ -133,7 +133,7 @@ impl HandleSwapInfo {
             // },
             ExchangeEnum::BitgetSwap => {
                 bitget_swap_handle::handle_position(res_data, ct_val)
-            },
+            }
             ExchangeEnum::BybitSwap => {
                 bybit_swap_handle::handle_position(res_data, ct_val)
             }
@@ -169,7 +169,7 @@ impl HandleSwapInfo {
             // },
             ExchangeEnum::BitgetSwap => {
                 bitget_swap_handle::handle_order(res_data, ct_val)
-            },
+            }
             ExchangeEnum::BybitSwap => {
                 bybit_swap_handle::handle_order(res_data, ct_val)
             }
@@ -183,17 +183,17 @@ impl HandleSwapInfo {
     }
 
     // 处理深度信息
-    pub fn handle_special_depth(exchange: ExchangeEnum, res_data: &ResponseData) -> SpecialDepth {
+    pub fn handle_special_depth(exchange: ExchangeEnum, res_data: &ResponseData, symbol_multiplier: Decimal) -> SpecialDepth {
         let label = res_data.label.clone();
         // 格式化
-        let mut format_depth = format_depth(exchange, res_data);
+        let mut format_depth = format_depth(exchange, res_data, symbol_multiplier);
         // 运算、组装
-        make_special_depth(label, &mut format_depth.depth_asks, &mut format_depth.depth_bids, format_depth.t, format_depth.create_at)
+        make_special_depth(label, &mut format_depth.depth_asks, &mut format_depth.depth_bids, format_depth.t, format_depth.create_at, symbol_multiplier)
     }
 }
 
 
-pub fn make_special_depth(label: String, depth_asks: &mut Vec<MarketOrder>, depth_bids: &mut Vec<MarketOrder>, t: Decimal, create_at: i64) -> SpecialDepth {
+pub fn make_special_depth(label: String, depth_asks: &mut Vec<MarketOrder>, depth_bids: &mut Vec<MarketOrder>, t: Decimal, create_at: i64, symbol_multiplier: Decimal) -> SpecialDepth {
     depth_asks.sort_by(|a, b| a.price.partial_cmp(&b.price).unwrap_or(Ordering::Equal));
     depth_bids.sort_by(|a, b| b.price.partial_cmp(&a.price).unwrap_or(Ordering::Equal));
     // TODO 不排序的话,有4us可以省下来。
@@ -205,11 +205,11 @@ pub fn make_special_depth(label: String, depth_asks: &mut Vec<MarketOrder>, dept
     let mut bv: Vec<Decimal> = Vec::new();
     for i in 0..public_params::LEVEL {
         let price = (depth_asks[0].price + step * Decimal::from_f64(i as f64).unwrap()).round_dp(depth_asks[0].price.scale());
-        ap.push(price);
+        ap.push(price / symbol_multiplier);
     }
     for i in 0..public_params::LEVEL {
         let price = (depth_bids[0].price - step * Decimal::from_f64(i as f64).unwrap()).round_dp(depth_bids[0].price.scale());
-        bp.push(price);
+        bp.push(price / symbol_multiplier);
     }
     let mut ap_price_tag = depth_asks[0].price + step;
     let mut ap_index = 0;
@@ -247,7 +247,7 @@ pub fn make_special_depth(label: String, depth_asks: &mut Vec<MarketOrder>, dept
         }
     }
 
-    let ticker_info = SpecialTicker { sell: depth_asks[0].price, buy: depth_bids[0].price, mid_price: mp, t, create_at };
+    let ticker_info = SpecialTicker { sell: depth_asks[0].price / symbol_multiplier, buy: depth_bids[0].price / symbol_multiplier, mid_price: mp / symbol_multiplier, t, create_at };
     let depth_info = bp.iter().cloned().chain(bv.iter().cloned()).chain(ap.iter().cloned()).chain(av.iter().cloned()).collect();
     SpecialDepth {
         name: label,
@@ -258,7 +258,7 @@ pub fn make_special_depth(label: String, depth_asks: &mut Vec<MarketOrder>, dept
     }
 }
 
-pub fn format_depth(exchange: ExchangeEnum, res_data: &ResponseData) -> DepthParam {
+pub fn format_depth(exchange: ExchangeEnum, res_data: &ResponseData, symbol_multiplier: Decimal) -> DepthParam {
     let depth_asks: Vec<MarketOrder>;
     let depth_bids: Vec<MarketOrder>;
     let t: Decimal;
@@ -271,21 +271,21 @@ pub fn format_depth(exchange: ExchangeEnum, res_data: &ResponseData) -> DepthPar
         //     create_at = 0;
         // }
         ExchangeEnum::BinanceSwap => {
-            depth_asks = binance_swap_handle::format_depth_items(res_data.data["a"].clone());
-            depth_bids = binance_swap_handle::format_depth_items(res_data.data["b"].clone());
+            depth_asks = binance_swap_handle::format_depth_items(res_data.data["a"].clone(), symbol_multiplier);
+            depth_bids = binance_swap_handle::format_depth_items(res_data.data["b"].clone(), symbol_multiplier);
             t = Decimal::from_str(&res_data.data["u"].to_string()).unwrap();
             create_at = res_data.data["E"].as_i64().unwrap() * 1000;
         }
         ExchangeEnum::GateSwap => {
-            depth_asks = gate_swap_handle::format_depth_items(&res_data.data["asks"]);
-            depth_bids = gate_swap_handle::format_depth_items(&res_data.data["bids"]);
+            depth_asks = gate_swap_handle::format_depth_items(&res_data.data["asks"], symbol_multiplier);
+            depth_bids = gate_swap_handle::format_depth_items(&res_data.data["bids"], symbol_multiplier);
             // todo! 有id可以取 保证与py一致
             t = Decimal::from_str(&res_data.data["t"].to_string()).unwrap();
             create_at = res_data.data["t"].as_i64().unwrap() * 1000;
         }
         ExchangeEnum::KucoinSwap => {
-            depth_asks = kucoin_handle::format_depth_items(res_data.data["asks"].clone());
-            depth_bids = kucoin_handle::format_depth_items(res_data.data["bids"].clone());
+            depth_asks = kucoin_handle::format_depth_items(res_data.data["asks"].clone(), symbol_multiplier);
+            depth_bids = kucoin_handle::format_depth_items(res_data.data["bids"].clone(), symbol_multiplier);
             t = Decimal::from_str(&res_data.data["sequence"].to_string()).unwrap();
             create_at = res_data.data["ts"].as_i64().unwrap() * 1000;
         }
@@ -308,29 +308,29 @@ pub fn format_depth(exchange: ExchangeEnum, res_data: &ResponseData) -> DepthPar
         //     create_at = res_data_json[0]["ts"].as_str().unwrap().parse::<i64>().unwrap() * 1000;
         // }
         ExchangeEnum::BitgetSwap => {
-            depth_asks = bitget_swap_handle::format_depth_items(res_data.data[0]["asks"].clone());
-            depth_bids = bitget_swap_handle::format_depth_items(res_data.data[0]["bids"].clone());
+            depth_asks = bitget_swap_handle::format_depth_items(res_data.data[0]["asks"].clone(), symbol_multiplier);
+            depth_bids = bitget_swap_handle::format_depth_items(res_data.data[0]["bids"].clone(), symbol_multiplier);
             t = Decimal::from_str(res_data.data[0]["ts"].as_str().unwrap()).unwrap();
             create_at = res_data.data[0]["ts"].as_str().unwrap().parse::<i64>().unwrap() * 1000;
         }
         ExchangeEnum::BybitSwap => {
-            depth_asks = bybit_swap_handle::format_depth_items(res_data.data["a"].clone());
-            depth_bids = bybit_swap_handle::format_depth_items(res_data.data["b"].clone());
+            depth_asks = bybit_swap_handle::format_depth_items(res_data.data["a"].clone(), symbol_multiplier);
+            depth_bids = bybit_swap_handle::format_depth_items(res_data.data["b"].clone(), symbol_multiplier);
             t = Decimal::from_i64(res_data.reach_time).unwrap();
             create_at = res_data.reach_time * 1000;
-        },
+        }
         ExchangeEnum::CoinexSwap => {
             let depth = &res_data.data["depth"];
-            depth_asks = coinex_swap_handle::format_depth_items(&depth["asks"].clone());
-            depth_bids = coinex_swap_handle::format_depth_items(&depth["bids"].clone());
+            depth_asks = coinex_swap_handle::format_depth_items(&depth["asks"].clone(), symbol_multiplier);
+            depth_bids = coinex_swap_handle::format_depth_items(&depth["bids"].clone(), symbol_multiplier);
             let time = depth.get("updated_at").unwrap().as_i64().unwrap_or(0i64);
             t = Decimal::from_i64(time).unwrap();
             create_at = time * 1000;
         }
         ExchangeEnum::HtxSwap => {
             let depth = &res_data.data;
-            depth_asks = htx_swap_handle::format_depth_items(depth["asks"].clone());
-            depth_bids = htx_swap_handle::format_depth_items(depth["bids"].clone());
+            depth_asks = htx_swap_handle::format_depth_items(depth["asks"].clone(), symbol_multiplier);
+            depth_bids = htx_swap_handle::format_depth_items(depth["bids"].clone(), symbol_multiplier);
             let time = depth["ts"].to_string().parse::<i64>().unwrap();
             t = Decimal::from_i64(time).unwrap();
             create_at = time * 1000;
@@ -341,7 +341,7 @@ pub fn format_depth(exchange: ExchangeEnum, res_data: &ResponseData) -> DepthPar
         depth_asks,
         depth_bids,
         t,
-        create_at
+        create_at,
     }
 }
 

+ 2 - 2
standard/src/htx_swap_handle.rs

@@ -73,11 +73,11 @@ pub fn format_order_item(order: serde_json::Value, ct_val: Decimal) -> Order {
 }
 
 // 格式化深度信息
-pub fn format_depth_items(value: serde_json::Value) -> Vec<MarketOrder> {
+pub fn format_depth_items(value: serde_json::Value, symbol_multiplier: Decimal) -> Vec<MarketOrder> {
     let mut depth_items: Vec<MarketOrder> = vec![];
     for value in value.as_array().unwrap() {
         depth_items.push(MarketOrder {
-            price: Decimal::from_f64(value[0].as_f64().unwrap()).unwrap(),
+            price: Decimal::from_f64(value[0].as_f64().unwrap()).unwrap() / symbol_multiplier,
             amount: Decimal::from_f64(value[1].as_f64().unwrap()).unwrap(),
         })
     }

+ 9 - 9
standard/src/kucoin_handle.rs

@@ -33,14 +33,14 @@ pub fn format_account_info(data: &Value, symbol: &String) -> Account {
 }
 
 // 处理特殊Ticket信息
-pub fn handle_book_ticker(res_data: &ResponseData) -> SpecialDepth {
-    format_special_ticker(&res_data.data, &res_data.label)
+pub fn handle_book_ticker(res_data: &ResponseData, symbol_multiplier: Decimal) -> SpecialDepth {
+    format_special_ticker(&res_data.data, &res_data.label, symbol_multiplier)
 }
 
-pub fn format_special_ticker(data: &Value, label: &String) -> SpecialDepth {
-    let bp = Decimal::from_str(&data["bestBidPrice"].as_str().unwrap()).unwrap();
+pub fn format_special_ticker(data: &Value, label: &String, symbol_multiplier: Decimal) -> SpecialDepth {
+    let bp = Decimal::from_str(&data["bestBidPrice"].as_str().unwrap()).unwrap() / symbol_multiplier;
     let bq = Decimal::from_f64(data["bestBidSize"].as_f64().unwrap()).unwrap();
-    let ap = Decimal::from_str(&data["bestAskPrice"].as_str().unwrap()).unwrap();
+    let ap = Decimal::from_str(&data["bestAskPrice"].as_str().unwrap()).unwrap() / symbol_multiplier;
     let aq = Decimal::from_f64(data["bestAskSize"].as_f64().unwrap()).unwrap();
     let mp = (bp + ap) * dec!(0.5);
     let t = Decimal::from_str(&data["sequence"].to_string()).unwrap();
@@ -139,15 +139,15 @@ pub fn format_order_item(order: &Value, ct_val: Decimal) -> Order {
 }
 
 // 处理特殊深度数据
-pub fn handle_special_depth(res_data: ResponseData) -> SpecialDepth {
-    HandleSwapInfo::handle_special_depth(ExchangeEnum::KucoinSwap, &res_data)
+pub fn handle_special_depth(res_data: ResponseData, symbol_multiplier: Decimal) -> SpecialDepth {
+    HandleSwapInfo::handle_special_depth(ExchangeEnum::KucoinSwap, &res_data, symbol_multiplier)
 }
 
-pub fn format_depth_items(value: serde_json::Value) -> Vec<MarketOrder> {
+pub fn format_depth_items(value: Value, symbol_multiplier: Decimal) -> Vec<MarketOrder> {
     let mut depth_items: Vec<MarketOrder> = vec![];
     for value in value.as_array().unwrap() {
         depth_items.push(MarketOrder {
-            price: Decimal::from_str(value[0].as_str().unwrap()).unwrap(),
+            price: Decimal::from_str(value[0].as_str().unwrap()).unwrap() / symbol_multiplier,
             amount: Decimal::from_f64(value[1].as_f64().unwrap()).unwrap(),
         })
     }

+ 7 - 3
strategy/src/binance_usdt_swap.rs

@@ -18,6 +18,7 @@ pub(crate) async fn reference_binance_swap_run(is_shutdown_arc: Arc<AtomicBool>,
                                                name: String,
                                                symbols: Vec<String>,
                                                is_colo: bool,
+                                               symbol_multiplier: Decimal,
                                                _exchange_params: BTreeMap<String, String>) {
     tokio::spawn(async move {
         //创建读写通道
@@ -40,7 +41,9 @@ pub(crate) async fn reference_binance_swap_run(is_shutdown_arc: Arc<AtomicBool>,
                 // 使用克隆后的 Arc,避免 move 语义
                 on_data(core_arc_cc,
                         &mut update_flag_u,
-                        data).await
+                        symbol_multiplier,
+                        data,
+                ).await
             }
         };
 
@@ -52,6 +55,7 @@ pub(crate) async fn reference_binance_swap_run(is_shutdown_arc: Arc<AtomicBool>,
 
 async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
                  update_flag_u: &mut Decimal,
+                 symbol_multiplier: Decimal,
                  response: ResponseData) {
     let mut trace_stack = TraceStack::new(response.time, response.ins);
     trace_stack.on_after_span_line();
@@ -83,7 +87,7 @@ async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
         "bookTicker" => {
             trace_stack.set_source("binance_usdt_swap.bookTicker".to_string());
             // 将ticker数据转换为模拟深度
-            let special_depth = standard::handle_info::HandleSwapInfo::handle_book_ticker(BinanceSwap, &response);
+            let special_depth = standard::handle_info::HandleSwapInfo::handle_book_ticker(BinanceSwap, &response, symbol_multiplier);
             trace_stack.on_after_format();
 
             on_special_depth(core_arc_clone, update_flag_u, &response.label, &mut trace_stack, &special_depth).await;
@@ -91,7 +95,7 @@ async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
         "depth" => {
             trace_stack.set_source("binance_usdt_swap.depth".to_string());
             // 将depth数据转换为模拟深度
-            let special_depth = standard::handle_info::HandleSwapInfo::handle_special_depth(BinanceSwap, &response);
+            let special_depth = standard::handle_info::HandleSwapInfo::handle_special_depth(BinanceSwap, &response, symbol_multiplier);
             trace_stack.on_after_format();
 
             on_special_depth(core_arc_clone, update_flag_u, &response.label, &mut trace_stack, &special_depth).await;

+ 12 - 10
strategy/src/bitget_usdt_swap.rs

@@ -14,12 +14,13 @@ 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>,
+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,
+                                  symbol_multiplier: Decimal,
                                   exchange_params: BTreeMap<String, String>) {
     // 开启公共频道
     let (write_tx_public, write_rx_public) = futures_channel::mpsc::unbounded();
@@ -43,7 +44,7 @@ pub async fn bitget_usdt_swap_run(is_shutdown_arc :Arc<AtomicBool>,
             let core_arc_cc = core_arc_clone.clone();
 
             async move {
-                on_public_data(core_arc_cc, &mut update_flag_u, data).await
+                on_public_data(core_arc_cc, &mut update_flag_u, symbol_multiplier, data).await
             }
         };
 
@@ -88,7 +89,7 @@ pub async fn bitget_usdt_swap_run(is_shutdown_arc :Arc<AtomicBool>,
         bg_private.set_subscribe(vec![
             BitgetSwapSubscribeType::PrOrders,
             BitgetSwapSubscribeType::PrAccount,
-            BitgetSwapSubscribeType::PrPosition
+            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 链接有异常")
@@ -108,7 +109,7 @@ async fn on_private_data(core_arc_clone: Arc<Mutex<Core>>,
             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);
 
@@ -128,12 +129,12 @@ async fn on_private_data(core_arc_clone: Arc<Mutex<Core>>,
 
             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();
+            let mut order_infos: Vec<OrderInfo> = Vec::new();
             for mut order in orders.order {
                 if order.status == "NULL" {
                     error!("bitget_usdt_swap 未识别的订单状态:{:?}", response);
@@ -149,7 +150,7 @@ async fn on_private_data(core_arc_clone: Arc<Mutex<Core>>,
                 let mut core = core_arc_clone.lock().await;
                 core.update_order(order_infos, trace_stack).await;
             }
-        },
+        }
         "pong" => {}
         _ => {
             info!("bitget_usdt_swap 113 未知的订阅数据: {:?}", response);
@@ -159,6 +160,7 @@ async fn on_private_data(core_arc_clone: Arc<Mutex<Core>>,
 
 async fn on_public_data(core_arc_clone: Arc<Mutex<Core>>,
                         update_flag_u: &mut Decimal,
+                        symbol_multiplier: Decimal,
                         response: ResponseData) {
     let mut trace_stack = TraceStack::new(response.time, response.ins);
     trace_stack.on_after_span_line();
@@ -167,12 +169,12 @@ async fn on_public_data(core_arc_clone: Arc<Mutex<Core>>,
     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);
+            let special_depth = standard::handle_info::HandleSwapInfo::handle_special_depth(BitgetSwap, &response, symbol_multiplier);
             trace_stack.on_after_format();
 
             on_special_depth(core_arc_clone, update_flag_u, &response.label, &mut trace_stack, &special_depth).await;
-        },
-        "pong" => {},
+        }
+        "pong" => {}
         _ => {
             info!("bitget_usdt_swap 125 未知的订阅数据");
             info!(?response)

+ 6 - 4
strategy/src/bybit_usdt_swap.rs

@@ -20,6 +20,7 @@ pub async fn bybit_swap_run(is_shutdown_arc: Arc<AtomicBool>,
                             name: String,
                             symbols: Vec<String>,
                             is_colo: bool,
+                            symbol_multiplier: Decimal,
                             exchange_params: BTreeMap<String, String>) {
     // 启动公共频道
     let (write_tx_public, write_rx_public) = futures_channel::mpsc::unbounded();
@@ -48,6 +49,7 @@ pub async fn bybit_swap_run(is_shutdown_arc: Arc<AtomicBool>,
             async move {
                 on_public_data(core_arc,
                                &mut update_flag_u,
+                               symbol_multiplier,
                                data).await;
             }
         };
@@ -68,7 +70,7 @@ pub async fn bybit_swap_run(is_shutdown_arc: Arc<AtomicBool>,
         ws_private.set_subscribe(vec![
             BybitSwapSubscribeType::PrPosition,
             BybitSwapSubscribeType::PrOrder,
-            BybitSwapSubscribeType::PrWallet
+            BybitSwapSubscribeType::PrWallet,
         ]);
 
         // 挂起私有ws
@@ -110,7 +112,7 @@ async fn on_private_data(core_arc_clone: Arc<Mutex<Core>>, ct_val: &Decimal, run
             let orders = standard::handle_info::HandleSwapInfo::handle_order(BybitSwap, response.clone(), ct_val.clone());
             trace_stack.on_after_format();
 
-            let mut order_infos:Vec<OrderInfo> = Vec::new();
+            let mut order_infos: Vec<OrderInfo> = Vec::new();
             for mut order in orders.order {
                 if order.status == "NULL" {
                     error!("bybit_usdt_swap 未识别的订单状态:{:?}", response);
@@ -141,7 +143,7 @@ async fn on_private_data(core_arc_clone: Arc<Mutex<Core>>, ct_val: &Decimal, run
     }
 }
 
-async fn on_public_data(core_arc_clone: Arc<Mutex<Core>>, update_flag_u: &mut Decimal, response: ResponseData) {
+async fn on_public_data(core_arc_clone: Arc<Mutex<Core>>, update_flag_u: &mut Decimal, symbol_multiplier: Decimal, response: ResponseData) {
     if response.code != 200 {
         return;
     }
@@ -154,7 +156,7 @@ async fn on_public_data(core_arc_clone: Arc<Mutex<Core>>, update_flag_u: &mut De
             trace_stack.set_source("bybit_usdt_swap.tickers".to_string());
 
             // 处理ticker信息
-            let special_depth = standard::handle_info::HandleSwapInfo::handle_book_ticker(BybitSwap, &response);
+            let special_depth = standard::handle_info::HandleSwapInfo::handle_book_ticker(BybitSwap, &response, symbol_multiplier);
             trace_stack.on_after_format();
 
             on_special_depth(core_arc_clone, update_flag_u, &response.label, &mut trace_stack, &special_depth).await;

+ 15 - 13
strategy/src/coinex_usdt_swap.rs

@@ -15,12 +15,13 @@ use crate::exchange_disguise::on_special_depth;
 
 // 1交易、0参考 coinex 合约 启动
 pub async fn coinex_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>) {
+                             is_trade: bool,
+                             core_arc: Arc<Mutex<Core>>,
+                             name: String,
+                             symbols: Vec<String>,
+                             _is_colo: bool,
+                             symbol_multiplier: Decimal,
+                             exchange_params: BTreeMap<String, String>) {
     let (write_tx, write_rx) = futures_channel::mpsc::unbounded();
 
     let write_tx_am = Arc::new(Mutex::new(write_tx));
@@ -34,7 +35,6 @@ pub async fn coinex_swap_run(is_shutdown_arc: Arc<AtomicBool>,
             ws.set_subscribe(vec![
                 // CoinexSwapSubscribeType::PuFuturesDeals,
                 CoinexSwapSubscribeType::PuFuturesDepth,
-
                 CoinexSwapSubscribeType::PrFuturesOrders,
                 CoinexSwapSubscribeType::PrFuturesPositions,
                 CoinexSwapSubscribeType::PrFuturesBalances,
@@ -64,6 +64,7 @@ pub async fn coinex_swap_run(is_shutdown_arc: Arc<AtomicBool>,
                         &mut update_flag_u,
                         &mul,
                         &rs,
+                        symbol_multiplier,
                         data,
                 ).await
             }
@@ -79,6 +80,7 @@ async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
                  update_flag_u: &mut Decimal,
                  multiplier: &Decimal,
                  run_symbol: &String,
+                 symbol_multiplier: Decimal,
                  response: ResponseData) {
     let mut trace_stack = TraceStack::new(response.time, response.ins);
     trace_stack.on_after_span_line();
@@ -86,7 +88,7 @@ async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
     match response.channel.as_str() {
         "depth.update" => {
             trace_stack.set_source("coinex_usdt_swap.order_book".to_string());
-            let special_depth = standard::handle_info::HandleSwapInfo::handle_special_depth(CoinexSwap, &response);
+            let special_depth = standard::handle_info::HandleSwapInfo::handle_special_depth(CoinexSwap, &response, symbol_multiplier);
             trace_stack.on_after_format();
 
             on_special_depth(core_arc_clone, update_flag_u, &response.label, &mut trace_stack, &special_depth).await;
@@ -99,7 +101,7 @@ async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
         "order.update" => {
             trace_stack.set_source("coinex_swap.orders".to_string());
             let orders = standard::handle_info::HandleSwapInfo::handle_order(CoinexSwap, response.clone(), multiplier.clone());
-            let mut order_infos:Vec<OrderInfo> = Vec::new();
+            let mut order_infos: Vec<OrderInfo> = Vec::new();
             for mut order in orders.order {
                 if order.status == "NULL" {
                     error!("coinex_usdt_swap 未识别的订单状态:{:?}", response);
@@ -112,13 +114,13 @@ async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
 
             if order_infos.is_empty() {
                 error!("coinex_usdt_swap 未识别的订单 格式化失败:{:?}", response);
-                return
+                return;
             }
             let mut new_order = order_infos[0].clone();
             let mut core = core_arc_clone.lock().await;
             // 本地订单缓存判断
             if !core.local_orders_backup.contains_key(&new_order.client_id) {
-                return
+                return;
             }
 
             // 获取订单目的
@@ -131,7 +133,7 @@ async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
             // 部分成交和新订单的处理,不用走下面的逻辑
             if new_order.status != "REMOVE" || new_order.filled == Decimal::ZERO {
                 core.update_order(order_infos, trace_stack).await;
-                return
+                return;
             }
 
             // 单向持仓的处理
@@ -265,6 +267,6 @@ async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
 fn parse_btree_map_to_coinex_swap_login(exchange_params: BTreeMap<String, String>) -> CoinexSwapLogin {
     CoinexSwapLogin {
         api_key: exchange_params.get("access_key").unwrap().clone(),
-        secret: exchange_params.get("secret_key").unwrap().clone()
+        secret: exchange_params.get("secret_key").unwrap().clone(),
     }
 }

+ 22 - 22
strategy/src/exchange_disguise.rs

@@ -21,7 +21,7 @@ use crate::core::Core;
 use crate::htx_usdt_swap::htx_swap_run;
 
 // 交易交易所启动
-pub async fn run_transactional_exchange(is_shutdown_arc :Arc<AtomicBool>,
+pub async fn run_transactional_exchange(is_shutdown_arc: Arc<AtomicBool>,
                                         exchange_name: String,
                                         core_arc: Arc<Mutex<Core>>,
                                         name: String,
@@ -30,11 +30,11 @@ pub async fn run_transactional_exchange(is_shutdown_arc :Arc<AtomicBool>,
                                         exchange_params: BTreeMap<String, String>) {
     match exchange_name.as_str() {
         "gate_usdt_swap" => {
-            gate_swap_run(is_shutdown_arc, true, core_arc, name, symbols, is_colo, exchange_params).await;
+            gate_swap_run(is_shutdown_arc, true, core_arc, name, symbols, is_colo, Decimal::ONE, exchange_params).await;
         }
         "kucoin_usdt_swap" => {
-            kucoin_swap_run(is_shutdown_arc, true, core_arc, name, symbols, is_colo, exchange_params).await;
-        },
+            kucoin_swap_run(is_shutdown_arc, true, core_arc, name, symbols, is_colo, Decimal::ONE, exchange_params).await;
+        }
         // "okex_usdt_swap" => {
         //     okex_swap_run(is_shutdown_arc,true, core_arc, name, symbols, is_colo, exchange_params).await;
         // },
@@ -42,17 +42,17 @@ pub async fn run_transactional_exchange(is_shutdown_arc :Arc<AtomicBool>,
         //     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_run(is_shutdown_arc, true, core_arc, name, symbols, is_colo, Decimal::ONE, exchange_params).await;
         }
         "bybit_usdt_swap" => {
-            bybit_swap_run(is_shutdown_arc,true, core_arc, name, symbols, is_colo, exchange_params).await;
+            bybit_swap_run(is_shutdown_arc, true, core_arc, name, symbols, is_colo, Decimal::ONE, exchange_params).await;
         }
         "coinex_usdt_swap" => {
             tokio::time::sleep(Duration::from_secs(1)).await;
-            coinex_swap_run(is_shutdown_arc,true, core_arc, name, symbols, is_colo, exchange_params).await;
+            coinex_swap_run(is_shutdown_arc, true, core_arc, name, symbols, is_colo, Decimal::ONE, exchange_params).await;
         }
-        "htx_usdt_swap" =>{
-            htx_swap_run(is_shutdown_arc,true, core_arc, name, symbols, is_colo, exchange_params).await;
+        "htx_usdt_swap" => {
+            htx_swap_run(is_shutdown_arc, true, core_arc, name, symbols, is_colo, Decimal::ONE, exchange_params).await;
         }
         _ => {
             let msg = format!("不支持的交易交易所:{}", exchange_name);
@@ -68,23 +68,24 @@ pub async fn run_reference_exchange(is_shutdown_arc: Arc<AtomicBool>,
                                     name: String,
                                     symbols: Vec<String>,
                                     is_colo: bool,
+                                    symbol_multiplier: Decimal,
                                     exchange_params: BTreeMap<String, String>) {
     match exchange_name.as_str() {
         "binance_usdt_swap" => {
-            reference_binance_swap_run(is_shutdown_arc, core_arc, name, symbols, is_colo, exchange_params).await;
-        },
+            reference_binance_swap_run(is_shutdown_arc, core_arc, name, symbols, is_colo, symbol_multiplier, exchange_params).await;
+        }
         // "binance_spot" => {
         //     reference_binance_spot_run(is_shutdown_arc, core_arc, name, symbols, is_colo, exchange_params).await;
         // },
         "gate_usdt_swap" => {
-            gate_swap_run(is_shutdown_arc, false, core_arc, name, symbols, is_colo, exchange_params).await;
-        },
+            gate_swap_run(is_shutdown_arc, false, core_arc, name, symbols, is_colo, symbol_multiplier, exchange_params).await;
+        }
         // "okex_usdt_swap" => {
         //     okex_swap_run(is_shutdown_arc, false, core_arc, name, symbols, is_colo, exchange_params).await;
         // },
         "kucoin_usdt_swap" => {
-            kucoin_swap_run(is_shutdown_arc, false, core_arc, name, symbols, is_colo, exchange_params).await;
-        },
+            kucoin_swap_run(is_shutdown_arc, false, core_arc, name, symbols, is_colo, symbol_multiplier, exchange_params).await;
+        }
         // "kucoin_spot" => {
         //     kucoin_spot_run(is_shutdown_arc, false, core_arc, name, symbols, is_colo, exchange_params).await;
         // },
@@ -92,17 +93,16 @@ pub async fn run_reference_exchange(is_shutdown_arc: Arc<AtomicBool>,
         //     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_run(is_shutdown_arc, false, core_arc, name, symbols, is_colo, symbol_multiplier, exchange_params).await;
         }
         "bybit_usdt_swap" => {
-            bybit_swap_run(is_shutdown_arc, false, core_arc, name, symbols, is_colo, exchange_params).await;
-        },
+            bybit_swap_run(is_shutdown_arc, false, core_arc, name, symbols, is_colo, symbol_multiplier, exchange_params).await;
+        }
         "coinex_usdt_swap" => {
-            coinex_swap_run(is_shutdown_arc,false, core_arc, name, symbols, is_colo, exchange_params).await;
-
+            coinex_swap_run(is_shutdown_arc, false, core_arc, name, symbols, is_colo, symbol_multiplier, exchange_params).await;
         }
-        "htx_usdt_swap" =>{
-            htx_swap_run(is_shutdown_arc, false, core_arc, name, symbols, is_colo, exchange_params).await;
+        "htx_usdt_swap" => {
+            htx_swap_run(is_shutdown_arc, false, core_arc, name, symbols, is_colo, symbol_multiplier, exchange_params).await;
         }
         _ => {
             let msg = format!("不支持的参考交易所:{}", exchange_name);

+ 9 - 7
strategy/src/gate_swap.rs

@@ -21,11 +21,12 @@ pub async fn gate_swap_run(is_shutdown_arc: Arc<AtomicBool>,
                            name: String,
                            symbols: Vec<String>,
                            is_colo: bool,
+                           symbol_multiplier: Decimal,
                            exchange_params: BTreeMap<String, String>) {
     let (write_tx, write_rx) = futures_channel::mpsc::unbounded();
 
     let mut gate_exc = GateSwapRest::new(is_colo, exchange_params.clone());
-    let mut user_id= "".to_string();
+    let mut user_id = "".to_string();
 
     // 交易
     if is_trade {
@@ -50,7 +51,6 @@ pub async fn gate_swap_run(is_shutdown_arc: Arc<AtomicBool>,
             ws.set_subscribe(vec![
                 // GateSwapSubscribeType::PuFuturesTrades,
                 GateSwapSubscribeType::PuFuturesBookTicker,
-
                 GateSwapSubscribeType::PrFuturesOrders(user_id.clone()),
                 GateSwapSubscribeType::PrFuturesPositions(user_id.clone()),
                 GateSwapSubscribeType::PrFuturesBalances(user_id.clone()),
@@ -60,7 +60,7 @@ pub async fn gate_swap_run(is_shutdown_arc: Arc<AtomicBool>,
                                        GateSwapWsType::PublicAndPrivate("usdt".to_string()));
             ws.set_subscribe(vec![
                 GateSwapSubscribeType::PuFuturesTrades,
-                GateSwapSubscribeType::PuFuturesBookTicker
+                GateSwapSubscribeType::PuFuturesBookTicker,
             ]);
         }
 
@@ -81,6 +81,7 @@ pub async fn gate_swap_run(is_shutdown_arc: Arc<AtomicBool>,
                         &mut update_flag_u,
                         &mul,
                         &rs,
+                        symbol_multiplier,
                         data,
                 ).await
             }
@@ -96,6 +97,7 @@ async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
                  update_flag_u: &mut Decimal,
                  multiplier: &Decimal,
                  run_symbol: &String,
+                 symbol_multiplier: Decimal,
                  response: ResponseData) {
     let mut trace_stack = TraceStack::new(response.time, response.ins);
     trace_stack.on_after_span_line();
@@ -103,7 +105,7 @@ async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
     match response.channel.as_str() {
         "futures.order_book" => {
             trace_stack.set_source("gate_usdt_swap.order_book".to_string());
-            let special_depth = standard::handle_info::HandleSwapInfo::handle_special_depth(GateSwap, &response);
+            let special_depth = standard::handle_info::HandleSwapInfo::handle_special_depth(GateSwap, &response, symbol_multiplier);
             trace_stack.on_after_format();
 
             on_special_depth(core_arc_clone, update_flag_u, &response.label, &mut trace_stack, &special_depth).await;
@@ -111,7 +113,7 @@ async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
         "futures.book_ticker" => {
             trace_stack.set_source("gate_usdt_swap.book_ticker".to_string());
             // 将ticker数据转换为模拟深度
-            let special_depth = standard::handle_info::HandleSwapInfo::handle_book_ticker(GateSwap, &response);
+            let special_depth = standard::handle_info::HandleSwapInfo::handle_book_ticker(GateSwap, &response, symbol_multiplier);
             trace_stack.on_after_format();
 
             on_special_depth(core_arc_clone, update_flag_u, &response.label, &mut trace_stack, &special_depth).await;
@@ -125,7 +127,7 @@ async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
             trace_stack.set_source("gate_swap.orders".to_string());
             let orders = standard::handle_info::HandleSwapInfo::handle_order(GateSwap, response.clone(), multiplier.clone());
 
-            let mut order_infos:Vec<OrderInfo> = Vec::new();
+            let mut order_infos: Vec<OrderInfo> = Vec::new();
             for mut order in orders.order {
                 if order.status == "NULL" {
                     error!("gate_usdt_swap 未识别的订单状态:{:?}", response);
@@ -176,6 +178,6 @@ async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
 fn parse_btree_map_to_gate_swap_login(exchange_params: BTreeMap<String, String>) -> GateSwapLogin {
     GateSwapLogin {
         api_key: exchange_params.get("access_key").unwrap().clone(),
-        secret: exchange_params.get("secret_key").unwrap().clone()
+        secret: exchange_params.get("secret_key").unwrap().clone(),
     }
 }

+ 16 - 14
strategy/src/htx_usdt_swap.rs

@@ -15,12 +15,13 @@ use crate::exchange_disguise::on_special_depth;
 
 // 1交易、0参考 htx 合约 启动
 pub async fn htx_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>) {
+                          is_trade: bool,
+                          core_arc: Arc<Mutex<Core>>,
+                          name: String,
+                          symbols: Vec<String>,
+                          _is_colo: bool,
+                          symbol_multiplier: Decimal,
+                          exchange_params: BTreeMap<String, String>) {
     // 开启公共频道
     let (write_tx_public, write_rx_public) = futures_channel::mpsc::unbounded();
 
@@ -34,7 +35,7 @@ pub async fn htx_swap_run(is_shutdown_arc: Arc<AtomicBool>,
     spawn(async move {
         // 构建链接ws
         let mut bg_public = HtxSwapWs::new_label(name_clone.clone(),
-                                                    None,
+                                                 None,
                                                  HtxSwapWsType::Public);
 
         // 消费数据的函数
@@ -43,7 +44,7 @@ pub async fn htx_swap_run(is_shutdown_arc: Arc<AtomicBool>,
             let core_arc_cc = core_arc_clone.clone();
             let rs = symbol.clone();
             async move {
-                on_public_data(core_arc_cc, &mut update_flag_u, rs, data).await
+                on_public_data(core_arc_cc, &mut update_flag_u, rs, symbol_multiplier, data).await
             }
         };
 
@@ -68,7 +69,7 @@ pub async fn htx_swap_run(is_shutdown_arc: Arc<AtomicBool>,
         let login_param = parse_btree_map_to_htx_swap_login(exchange_params);
         // 构建链接ws
         let mut bg_private = HtxSwapWs::new_label(name.clone(),
-                                                     Some(login_param),
+                                                  Some(login_param),
                                                   HtxSwapWsType::Private);
 
         // 消费数据的函数
@@ -88,7 +89,7 @@ pub async fn htx_swap_run(is_shutdown_arc: Arc<AtomicBool>,
         bg_private.set_subscribe(vec![
             HtxSwapSubscribeType::PrFuturesOrders,
             HtxSwapSubscribeType::PrFuturesBalances,
-            HtxSwapSubscribeType::PrFuturesPositions
+            HtxSwapSubscribeType::PrFuturesPositions,
         ]);
         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("htx_usdt_swap 链接有异常")
@@ -108,7 +109,7 @@ async fn on_private_data(core_arc_clone: Arc<Mutex<Core>>,
     if response.channel.contains(order_channel) { // 订单频道
         trace_stack.set_source("htx_swap.orders".to_string());
         let orders = standard::handle_info::HandleSwapInfo::handle_order(HtxSwap, response.clone(), ct_val.clone());
-        let mut order_infos:Vec<OrderInfo> = Vec::new();
+        let mut order_infos: Vec<OrderInfo> = Vec::new();
         for mut order in orders.order {
             if order.status == "NULL" {
                 error!("htx_usdt_swap 未识别的订单状态:{:?}", response);
@@ -128,7 +129,7 @@ async fn on_private_data(core_arc_clone: Arc<Mutex<Core>>,
         let mut core = core_arc_clone.lock().await;
 
         core.update_position(positions).await;
-    } else if response.channel.contains(balance_channel)  { // 余额频道
+    } else if response.channel.contains(balance_channel) { // 余额频道
         let account = standard::handle_info::HandleSwapInfo::handle_account_info(HtxSwap, &response, run_symbol);
         let mut core = core_arc_clone.lock().await;
 
@@ -142,6 +143,7 @@ async fn on_private_data(core_arc_clone: Arc<Mutex<Core>>,
 async fn on_public_data(core_arc_clone: Arc<Mutex<Core>>,
                         update_flag_u: &mut Decimal,
                         run_symbol: String,
+                        symbol_multiplier: Decimal,
                         response: ResponseData) {
     let mut trace_stack = TraceStack::new(response.time, response.ins);
     trace_stack.on_after_span_line();
@@ -150,7 +152,7 @@ async fn on_public_data(core_arc_clone: Arc<Mutex<Core>>,
     // public类型,目前只考虑订单流数据
     if response.channel == depth_channel { // 深度频道
         trace_stack.set_source("htx_usdt_swap.depth".to_string());
-        let special_depth = standard::handle_info::HandleSwapInfo::handle_special_depth(HtxSwap, &response);
+        let special_depth = standard::handle_info::HandleSwapInfo::handle_special_depth(HtxSwap, &response, symbol_multiplier);
         trace_stack.on_after_format();
 
         on_special_depth(core_arc_clone, update_flag_u, &response.label, &mut trace_stack, &special_depth).await;
@@ -163,6 +165,6 @@ async fn on_public_data(core_arc_clone: Arc<Mutex<Core>>,
 fn parse_btree_map_to_htx_swap_login(exchange_params: BTreeMap<String, String>) -> HtxSwapLogin {
     HtxSwapLogin {
         api_key: exchange_params.get("access_key").unwrap().clone(),
-        secret: exchange_params.get("secret_key").unwrap().clone()
+        secret: exchange_params.get("secret_key").unwrap().clone(),
     }
 }

+ 10 - 8
strategy/src/kucoin_swap.rs

@@ -19,16 +19,17 @@ use crate::model::{OrderInfo};
 use crate::core::Core;
 
 // 1交易、0参考 kucoin 合约 启动
-pub async fn kucoin_swap_run(is_shutdown_arc :Arc<AtomicBool>,
+pub async fn kucoin_swap_run(is_shutdown_arc: Arc<AtomicBool>,
                              is_trade: bool,
                              core_arc: Arc<Mutex<Core>>,
                              name: String,
                              symbols: Vec<String>,
                              is_colo: bool,
+                             symbol_multiplier: Decimal,
                              exchange_params: BTreeMap<String, String>) {
     let mut symbol_arr = Vec::new();
     for symbol in &symbols {
-        let symbol_mapper = standard::utils::symbol_enter_mapper(KucoinSwap,symbol.as_str());
+        let symbol_mapper = standard::utils::symbol_enter_mapper(KucoinSwap, symbol.as_str());
         let new_symbol = symbol_mapper.replace("_", "").to_uppercase() + "M";
         symbol_arr.push(new_symbol);
     }
@@ -51,7 +52,7 @@ pub async fn kucoin_swap_run(is_shutdown_arc :Arc<AtomicBool>,
     let write_tx_am = Arc::new(Mutex::new(write_tx));
     spawn(async move {
         //创建读写通道
-        spawn( async move {
+        spawn(async move {
             let mut ws;
             // 交易
             if is_trade {
@@ -59,9 +60,8 @@ pub async fn kucoin_swap_run(is_shutdown_arc :Arc<AtomicBool>,
                 ws = KucoinSwapWs::new_label(name.clone(), is_colo, Option::from(login_params), KucoinSwapWsType::Private).await;
                 ws.set_subscribe(vec![
                     KucoinSwapSubscribeType::PuContractMarketLevel2Depth50,
-
                     KucoinSwapSubscribeType::PrContractPosition,
-                    KucoinSwapSubscribeType::PrContractMarketTradeOrders
+                    KucoinSwapSubscribeType::PrContractMarketTradeOrders,
                 ]);
             } else { // 参考
                 ws = KucoinSwapWs::new_label(name.clone(), is_colo, None, KucoinSwapWsType::Public).await;
@@ -89,6 +89,7 @@ pub async fn kucoin_swap_run(is_shutdown_arc :Arc<AtomicBool>,
                     on_data(core_arc_cc,
                             &mut update_flag_u,
                             &mul,
+                            symbol_multiplier,
                             // &mut max_buy,
                             // &mut min_sell,
                             data).await
@@ -105,6 +106,7 @@ pub async fn kucoin_swap_run(is_shutdown_arc :Arc<AtomicBool>,
 async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
                  update_flag_u: &mut Decimal,
                  multiplier: &Decimal,
+                 symbol_multiplier: Decimal,
                  // max_buy: &mut Decimal,
                  // min_sell: &mut Decimal,
                  response: ResponseData) {
@@ -114,7 +116,7 @@ async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
     match response.channel.as_str() {
         "level2" => {
             trace_stack.set_source("kucoin_usdt_swap.level2".to_string());
-            let special_depth = standard::handle_info::HandleSwapInfo::handle_special_depth(KucoinSwap, &response);
+            let special_depth = standard::handle_info::HandleSwapInfo::handle_special_depth(KucoinSwap, &response, symbol_multiplier);
             trace_stack.on_after_format();
 
             on_special_depth(core_arc_clone, update_flag_u, &response.label, &mut trace_stack, &special_depth).await
@@ -122,7 +124,7 @@ async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
         "tickerV2" => {
             trace_stack.set_source("kucoin_swap.tickerV2".to_string());
 
-            let special_depth = standard::handle_info::HandleSwapInfo::handle_book_ticker(KucoinSwap, &response);
+            let special_depth = standard::handle_info::HandleSwapInfo::handle_book_ticker(KucoinSwap, &response, symbol_multiplier);
             trace_stack.on_before_network(special_depth.create_at.clone());
 
             on_special_depth(core_arc_clone, update_flag_u, &response.label, &mut trace_stack, &special_depth).await
@@ -131,7 +133,7 @@ async fn on_data(core_arc_clone: Arc<Mutex<Core>>,
             trace_stack.set_source("kucoin_swap.symbolOrderChange".to_string());
 
             let orders = standard::handle_info::HandleSwapInfo::handle_order(KucoinSwap, response, multiplier.clone());
-            let mut order_infos:Vec<OrderInfo> = Vec::new();
+            let mut order_infos: Vec<OrderInfo> = Vec::new();
             for mut order in orders.order {
                 if order.status == "NULL" {
                     continue;