Selaa lähdekoodia

Merge branch 'master' of http://git.skyfffire.com/skyfffire/as-rust

875428575@qq.com 2 vuotta sitten
vanhempi
commit
18e664f626

+ 18 - 77
standard/src/binance_handle.rs

@@ -1,99 +1,40 @@
-use std::cmp::Ordering;
-use rust_decimal::Decimal;
-use rust_decimal::prelude::FromPrimitive;
 use rust_decimal_macros::dec;
 use exchanges::response_base::ResponseData;
-use global::public_params;
 use crate::{MarketOrder, SpecialDepth, SpecialTicker};
+use crate::exchange::ExchangeEnum;
+use crate::handle_info::HandleSwapInfo;
 
-// 处理特殊Ticket信息
+
+// 处理特殊Ticker信息
 pub fn handle_special_ticker(res_data: ResponseData) -> SpecialDepth {
     let res_data_str = res_data.data;
     let res_data_json: serde_json::Value = serde_json::from_str(&*res_data_str).unwrap();
-    let bp = res_data_json["b"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
-    let bq = res_data_json["B"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
-    let ap = res_data_json["a"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
-    let aq = res_data_json["A"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
+    format_special_ticker(res_data_json, res_data.lable)
+}
+
+pub fn format_special_ticker(data: serde_json::Value, label: String) -> SpecialDepth {
+    let bp = data["b"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
+    let bq = data["B"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
+    let ap = data["a"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
+    let aq = data["A"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
     let mp = (bp + ap) * dec!(0.5);
 
     let ticker_info = SpecialTicker { sell: ap, buy: bp, mid_price: mp };
     let depth_info = vec![bp, bq, ap, aq];
-    let result = SpecialDepth {
-        name: res_data.lable,
+    SpecialDepth {
+        name: label,
         depth: depth_info,
         ticker: ticker_info,
-    };
-    return result;
+    }
 }
 
 // 处理特殊深度数据
 pub fn handle_special_depth(res_data: ResponseData) -> SpecialDepth {
-    let res_data_str = res_data.data;
-    let res_data_json: serde_json::Value = serde_json::from_str(&*res_data_str).unwrap();
-    let mut depth_asks: Vec<MarketOrder> = parse_depth_items(&res_data_json["a"]);
-    let mut depth_bids: Vec<MarketOrder> = parse_depth_items(&res_data_json["b"]);
-    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));
-    let mp = (depth_asks[0].price + depth_bids[0].price) * dec!(0.5);
-    let step = (public_params::EFF_RANGE * mp / Decimal::from_usize(public_params::LEVEL).unwrap()).round_dp(mp.scale());
-    let mut ap = Vec::new();
-    let mut bp = Vec::new();
-    let mut av: Vec<Decimal> = Vec::new();
-    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);
-    }
-    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);
-    }
-    let mut ap_price_tag = depth_asks[0].price + step;
-    let mut ap_index = 0;
-    for item in depth_asks.iter() {
-        let price = item.price;
-        let amount = item.amount;
-        if av.get(ap_index).is_none() { av.push(dec!(0)) };
-        if price < ap_price_tag {
-            av[ap_index] += amount;
-        } else {
-            ap_price_tag += step;
-            ap_index += 1;
-            if ap_index == public_params::LEVEL {
-                break;
-            }
-            av[ap_index] += amount
-        }
-    }
-
-    let mut bp_price_tag = depth_bids[0].price - step;
-    let mut bp_index = 0;
-    for item in depth_bids.iter() {
-        let price = item.price;
-        let amount = item.amount;
-        if bv.get(bp_index).is_none() { bv.push(dec!(0)) };
-        if price > bp_price_tag {
-            bv[bp_index] += amount;
-        } else {
-            bp_price_tag -= step;
-            bp_index += 1;
-            if bp_index == public_params::LEVEL {
-                break;
-            }
-            bv[bp_index] += amount
-        }
-    }
-    let ticker_info = SpecialTicker { sell: depth_asks[0].price, buy: depth_bids[0].price, mid_price: mp };
-    let depth_info = bp.iter().cloned().chain(bv.iter().cloned()).chain(ap.iter().cloned()).chain(av.iter().cloned()).collect();
-    let result = SpecialDepth {
-        name: res_data.lable,
-        depth: depth_info,
-        ticker: ticker_info,
-    };
-    return result;
+    HandleSwapInfo::handle_special_depth(ExchangeEnum::BinanceSwap, res_data)
 }
 
-fn parse_depth_items(value: &serde_json::Value) -> Vec<MarketOrder> {
+// 格式化深度信息
+pub fn format_depth_items(value: serde_json::Value) -> Vec<MarketOrder> {
     let mut depth_items: Vec<MarketOrder> = vec![];
     for value in value.as_array().unwrap() {
         depth_items.push(MarketOrder {

+ 36 - 102
standard/src/gate_handle.rs

@@ -1,20 +1,20 @@
-use std::cmp::Ordering;
 use rust_decimal::Decimal;
-use rust_decimal::prelude::FromPrimitive;
 use rust_decimal_macros::dec;
-use serde_json::json;
 use exchanges::response_base::ResponseData;
-use global::public_params;
-use crate::{Account, MarketOrder, Order, Position, PositionModeEnum, SpecialDepth, SpecialOrder, SpecialTicker};
+use crate::{Account, MarketOrder, Order, Position, PositionModeEnum, SpecialDepth, SpecialOrder};
+use crate::exchange::ExchangeEnum;
+use crate::handle_info::HandleSwapInfo;
 
+// 处理账号信息
 pub fn handle_account_info(res_data: ResponseData, symbol: String) -> Account {
-    let res_data_str = &res_data.data;
-    let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
-    let details = res_data_json;
-    let default_info = json!({"balance": 0,"change": 0,"text": ""});
-    let balance_info = details.iter().find(|&item| item["text"].as_str().unwrap().contains(&symbol)).unwrap_or(&default_info);
-    let balance = balance_info["balance"].to_string().parse().unwrap_or(dec!(0.0));
+    let res_data_str = res_data.data;
+    let res_data_json: Vec<serde_json::Value> = serde_json::from_str(&res_data_str).unwrap();
+    format_account_info(res_data_json, symbol)
+}
 
+pub fn format_account_info(data: Vec<serde_json::Value>, symbol: String) -> Account {
+    let balance_info = data.iter().find(|&item| item["text"].as_str().unwrap().contains(&symbol)).unwrap();
+    let balance = balance_info["balance"].to_string().parse().unwrap_or(dec!(0.0));
     Account {
         balance,
         available_balance: dec!(0),
@@ -29,11 +29,10 @@ pub fn handle_account_info(res_data: ResponseData, symbol: String) -> Account {
 pub fn handle_position(res_data: ResponseData, amount_size: Decimal) -> Vec<Position> {
     let res_data_str = res_data.data;
     let res_data_json: Vec<serde_json::Value> = serde_json::from_str(&res_data_str).unwrap();
-    let result = res_data_json.iter().map(|item| { parse_position_item(item, amount_size) }).collect();
-    return result;
+    res_data_json.iter().map(|item| { format_position_item(item, amount_size) }).collect()
 }
 
-fn parse_position_item(position: &serde_json::Value, amount_size: Decimal) -> Position {
+pub fn format_position_item(position: &serde_json::Value, amount_size: Decimal) -> Position {
     let position_mode = match position["mode"].as_str().unwrap_or("") {
         "single" => PositionModeEnum::Both,
         "dual_long" => PositionModeEnum::Long,
@@ -60,30 +59,7 @@ pub fn handle_order(res_data: ResponseData, amount_size: Decimal) -> SpecialOrde
     let res_data_json: Vec<serde_json::Value> = serde_json::from_str(&*res_data_str).unwrap();
     let mut order_info = Vec::new();
     for item in res_data_json.iter() {
-        let status = item["status"].as_str().unwrap_or("");
-        let id = item["id"].to_string();
-        let text = item["text"].as_str().unwrap_or("");
-        let price = item["price"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
-        let size = item["size"].to_string().parse().unwrap_or(dec!(0));
-        let left = item["left"].to_string().parse().unwrap_or(dec!(0));
-        let fill_price = item["fill_price"].to_string().parse().unwrap_or(dec!(0));
-        let order_type = "limit".to_string();
-
-        let custom_id = text.replace("t-my-custom-id_", "");
-        let amount = size * amount_size;
-        let deal_amount = (amount - left) * amount_size;
-        let custom_status = if status == "finished" { "REMOVE".to_string() } else if status == "open" { "NEW".to_string() } else { "OTHER".to_string() };
-        let order = Order {
-            id,
-            custom_id,
-            price,
-            amount,
-            deal_amount,
-            avg_price: fill_price,
-            status: custom_status,
-            order_type,
-        };
-        order_info.push(order);
+        order_info.push(format_order_item(item.clone(), amount_size));
     };
 
     SpecialOrder {
@@ -92,75 +68,33 @@ pub fn handle_order(res_data: ResponseData, amount_size: Decimal) -> SpecialOrde
     }
 }
 
-// 处理特殊深度数据
-pub fn handle_special_depth(res_data: ResponseData) -> SpecialDepth {
-    let res_data_str = res_data.data;
-    let res_data_json: serde_json::Value = serde_json::from_str(&*res_data_str).unwrap();
-    let mut depth_asks: Vec<MarketOrder> = parse_depth_items(&res_data_json["asks"]);
-    let mut depth_bids: Vec<MarketOrder> = parse_depth_items(&res_data_json["bids"]);
-    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));
-    let mp = (depth_asks[0].price + depth_bids[0].price) * dec!(0.5);
-    let step = (public_params::EFF_RANGE * mp / Decimal::from_usize(public_params::LEVEL).unwrap()).round_dp(mp.scale());
-    let mut ap = Vec::new();
-    let mut bp = Vec::new();
-    let mut av: Vec<Decimal> = Vec::new();
-    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);
-    }
-    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);
-    }
-    let mut ap_price_tag = depth_asks[0].price + step;
-    let mut ap_index = 0;
-    for item in depth_asks.iter() {
-        let price = item.price;
-        let amount = item.amount;
-        if av.get(ap_index).is_none() { av.push(dec!(0)) };
-        if price < ap_price_tag {
-            av[ap_index] += amount;
-        } else {
-            ap_price_tag += step;
-            ap_index += 1;
-            if ap_index == public_params::LEVEL {
-                break;
-            }
-            av[ap_index] += amount
-        }
-    }
+pub fn format_order_item(order: serde_json::Value, amount_size: Decimal) -> Order {
+    let status = order["status"].as_str().unwrap_or("");
+    let text = order["text"].as_str().unwrap_or("");
+    let size = order["size"].to_string().parse().unwrap_or(dec!(0));
+    let left = order["left"].to_string().parse().unwrap_or(dec!(0));
 
-    let mut bp_price_tag = depth_bids[0].price - step;
-    let mut bp_index = 0;
-    for item in depth_bids.iter() {
-        let price = item.price;
-        let amount = item.amount;
-        if bv.get(bp_index).is_none() { bv.push(dec!(0)) };
-        if price > bp_price_tag {
-            bv[bp_index] += amount;
-        } else {
-            bp_price_tag -= step;
-            bp_index += 1;
-            if bp_index == public_params::LEVEL {
-                break;
-            }
-            bv[bp_index] += amount
-        }
+    let amount = size * amount_size;
+    let deal_amount = (amount - left) * amount_size;
+    let custom_status = if "finished" == status { "REMOVE".to_string() } else if status == "open" { "NEW".to_string() } else { "OTHER".to_string() };
+    Order {
+        id: order["id"].to_string(),
+        custom_id: text.replace("t-my-custom-id_", ""),
+        price: order["price"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
+        amount,
+        deal_amount,
+        avg_price: order["fill_price"].to_string().parse().unwrap_or(dec!(0)),
+        status: custom_status,
+        order_type: "limit".to_string(),
     }
+}
 
-    let ticker_info = SpecialTicker { sell: depth_asks[0].price, buy: depth_bids[0].price, mid_price: mp };
-    let depth_info = bp.iter().cloned().chain(bv.iter().cloned()).chain(ap.iter().cloned()).chain(av.iter().cloned()).collect();
-    let result = SpecialDepth {
-        name: res_data.lable,
-        depth: depth_info,
-        ticker: ticker_info,
-    };
-    return result;
+// 处理特殊深度数据
+pub fn handle_special_depth(res_data: ResponseData) -> SpecialDepth {
+    HandleSwapInfo::handle_special_depth(ExchangeEnum::GateSwap, res_data)
 }
 
-fn parse_depth_items(value: &serde_json::Value) -> Vec<MarketOrder> {
+pub fn format_depth_items(value: serde_json::Value) -> Vec<MarketOrder> {
     let mut depth_items: Vec<MarketOrder> = vec![];
     for value in value.as_array().unwrap() {
         depth_items.push(MarketOrder {

+ 8 - 52
standard/src/gate_swap.rs

@@ -10,7 +10,7 @@ use serde_json::{json};
 use futures::stream::FuturesUnordered;
 use futures::{TryStreamExt};
 use tracing::error;
-use crate::{Platform, ExchangeEnum, Account, Position, PositionModeEnum, Ticker, Market, Order, OrderCommand};
+use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, OrderCommand, gate_handle};
 use exchanges::gate_swap_rest::GateSwapRest;
 
 #[allow(dead_code)]
@@ -113,7 +113,7 @@ impl Platform for GateSwap {
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
-            let result = res_data_json.iter().map(|item| { parse_position_item(item, amount_size) }).collect();
+            let result = res_data_json.iter().map(|item| { gate_handle::format_position_item(item, amount_size) }).collect();
             Ok(result)
         } else {
             Err(Error::new(ErrorKind::Other, res_data.message))
@@ -127,7 +127,7 @@ impl Platform for GateSwap {
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
-            let result = res_data_json.iter().map(|item| { parse_position_item(item, amount_size) }).collect();
+            let result = res_data_json.iter().map(|item| { gate_handle::format_position_item(item, amount_size) }).collect();
             Ok(result)
         } else {
             Err(Error::new(ErrorKind::Other, res_data.message))
@@ -198,7 +198,7 @@ impl Platform for GateSwap {
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
-            let result = parse_order_item(&res_data_json, amount_size);
+            let result = gate_handle::format_order_item(res_data_json, amount_size);
             Ok(result)
         } else {
             Err(Error::new(ErrorKind::Other, res_data.message))
@@ -213,7 +213,7 @@ impl Platform for GateSwap {
             let res_data_str = &res_data.data;
             let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
             let order_info: Vec<_> = res_data_json.iter().filter(|item| item["contract"].as_str().unwrap_or("") == self.symbol).collect();
-            let result = order_info.iter().map(|item| parse_order_item(item, amount_size)).collect();
+            let result = order_info.iter().map(|&item| gate_handle::format_order_item(item.clone(), amount_size)).collect();
             Ok(result)
         } else {
             Err(Error::new(ErrorKind::Other, res_data.message))
@@ -291,7 +291,7 @@ impl Platform for GateSwap {
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
-            let result = parse_order_item(&res_data_json, amount_size);
+            let result = gate_handle::format_order_item(res_data_json, amount_size);
             Ok(result)
         } else {
             Err(Error::new(ErrorKind::Other, res_data.message))
@@ -307,7 +307,7 @@ impl Platform for GateSwap {
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
-            let result = parse_order_item(&res_data_json, amount_size);
+            let result = gate_handle::format_order_item(res_data_json, amount_size);
             Ok(result)
         } else {
             Err(Error::new(ErrorKind::Other, res_data.message))
@@ -321,7 +321,7 @@ impl Platform for GateSwap {
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
-            let result = res_data_json.iter().map(|item| parse_order_item(item, amount_size)).collect();
+            let result = res_data_json.iter().map(|item| gate_handle::format_order_item(item.clone(), amount_size)).collect();
             Ok(result)
         } else {
             Err(Error::new(ErrorKind::Other, res_data.message))
@@ -411,47 +411,3 @@ impl Platform for GateSwap {
         let _: Result<Vec<_>, _> = futures.try_collect().await;
     }
 }
-
-fn parse_order_item(order: &serde_json::Value, amount_size: Decimal) -> Order {
-    let text = order["text"].as_str().unwrap_or("");
-    let size = order["size"].to_string().parse().unwrap_or(dec!(0));
-    let left = order["left"].to_string().parse().unwrap_or(dec!(0));
-    let fill_price = order["fill_price"].to_string().parse().unwrap_or(dec!(0));
-    let status = order["status"].as_str().unwrap_or("");
-
-    let custom_id = text.replace("t-my-custom-id_", "");
-    let amount = size * amount_size;
-    let deal_amount = (amount - left) * amount_size;
-    let custom_status = if "finished" == status { "REMOVE".to_string() } else if status == "open" { "NEW".to_string() } else { "OTHER".to_string() };
-    Order {
-        id: order["id"].to_string(),
-        custom_id,
-        price: order["price"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
-        amount: order["size"].to_string().parse().unwrap_or(dec!(0)),
-        deal_amount,
-        avg_price: fill_price,
-        status: custom_status,
-        order_type: "limit".to_string(),
-    }
-}
-
-fn parse_position_item(position: &serde_json::Value, amount_size: Decimal) -> Position {
-    let position_mode = match position["mode"].as_str().unwrap_or("") {
-        "single" => PositionModeEnum::Both,
-        "dual_long" => PositionModeEnum::Long,
-        "dual_short" => PositionModeEnum::Short,
-        _ => PositionModeEnum::Both
-    };
-    let size = position["size"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
-    let amount = size * amount_size;
-    Position {
-        symbol: position["contract"].as_str().unwrap_or("").parse().unwrap(),
-        margin_level: position["leverage"].as_str().unwrap_or("1").parse().unwrap_or(dec!(0)),
-        amount,
-        frozen_amount: dec!(0),
-        price: position["entry_price"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
-        profit: position["unrealised_pnl"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
-        position_mode,
-        margin: position["margin"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
-    }
-}

+ 166 - 0
standard/src/handle_info.rs

@@ -0,0 +1,166 @@
+use std::cmp::Ordering;
+use rust_decimal::{Decimal};
+use rust_decimal::prelude::FromPrimitive;
+use rust_decimal_macros::dec;
+use exchanges::response_base::ResponseData;
+use global::public_params;
+use crate::exchange::ExchangeEnum;
+use crate::{Account, binance_handle, gate_handle, kucoin_handle, MarketOrder, Position, SpecialDepth, SpecialOrder, SpecialTicker};
+
+#[allow(dead_code)]
+pub struct HandleSwapInfo;
+
+#[allow(dead_code)]
+impl HandleSwapInfo {
+    // 处理账号信息
+    pub fn handle_account_info(exchange: ExchangeEnum, res_data: ResponseData, symbol: String) -> Account {
+        match exchange {
+            ExchangeEnum::BinanceSwap => {
+                panic!("暂未提供此交易所方法!")
+            }
+            ExchangeEnum::GateSwap => {
+                gate_handle::handle_account_info(res_data, symbol)
+            }
+            ExchangeEnum::KucoinSwap => {
+                kucoin_handle::handle_account_info(res_data, symbol)
+            }
+            _ => {
+                panic!("参数错误!")
+            }
+        }
+    }
+    // 处理特殊Ticket信息
+    pub fn handle_special_ticker(exchange: ExchangeEnum, res_data: ResponseData) -> SpecialDepth {
+        match exchange {
+            ExchangeEnum::BinanceSwap => {
+                binance_handle::handle_special_ticker(res_data)
+            }
+            ExchangeEnum::GateSwap => {
+                panic!("暂未提供此交易所方法!")
+            }
+            ExchangeEnum::KucoinSwap => {
+                kucoin_handle::handle_special_ticker(res_data)
+            }
+            _ => {
+                panic!("参数错误!")
+            }
+        }
+    }
+    // 处理position信息
+    pub fn handle_position(exchange: ExchangeEnum, res_data: ResponseData, amount_size: Decimal) -> Vec<Position> {
+        match exchange {
+            ExchangeEnum::BinanceSwap => {
+                panic!("暂未提供此交易所方法!")
+            }
+            ExchangeEnum::GateSwap => {
+                gate_handle::handle_position(res_data, amount_size)
+            }
+            ExchangeEnum::KucoinSwap => {
+                kucoin_handle::handle_position(res_data, amount_size)
+            }
+            _ => {
+                panic!("参数错误!")
+            }
+        }
+    }
+    // 处理订单信息
+    pub fn handle_order(exchange: ExchangeEnum, res_data: ResponseData, amount_size: Decimal) -> SpecialOrder {
+        match exchange {
+            ExchangeEnum::BinanceSwap => {
+                panic!("暂未提供此交易所方法!")
+            }
+            ExchangeEnum::GateSwap => {
+                gate_handle::handle_order(res_data, amount_size)
+            }
+            ExchangeEnum::KucoinSwap => {
+                kucoin_handle::handle_order(res_data, amount_size)
+            }
+            _ => {
+                panic!("参数错误!")
+            }
+        }
+    }
+    // 处理深度信息
+    pub fn handle_special_depth(exchange: ExchangeEnum, res_data: ResponseData) -> SpecialDepth {
+        let res_data_str = res_data.data;
+        let res_data_json: serde_json::Value = serde_json::from_str(&*res_data_str).unwrap();
+        let mut depth_asks: Vec<MarketOrder>;
+        let mut depth_bids: Vec<MarketOrder>;
+        match exchange {
+            ExchangeEnum::BinanceSwap => {
+                depth_asks = binance_handle::format_depth_items(res_data_json["a"].clone());
+                depth_bids = binance_handle::format_depth_items(res_data_json["b"].clone());
+            }
+            ExchangeEnum::GateSwap => {
+                depth_asks = gate_handle::format_depth_items(res_data_json["asks"].clone());
+                depth_bids = gate_handle::format_depth_items(res_data_json["bids"].clone());
+            }
+            ExchangeEnum::KucoinSwap => {
+                depth_asks = kucoin_handle::format_depth_items(res_data_json["asks"].clone());
+                depth_bids = kucoin_handle::format_depth_items(res_data_json["bids"].clone());
+            }
+            _ => {
+                panic!("参数错误!")
+            }
+        }
+        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));
+        let mp = (depth_asks[0].price + depth_bids[0].price) * dec!(0.5);
+        let step = (public_params::EFF_RANGE * mp / Decimal::from_usize(public_params::LEVEL).unwrap()).round_dp(mp.scale());
+        let mut ap = Vec::new();
+        let mut bp = Vec::new();
+        let mut av: Vec<Decimal> = Vec::new();
+        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);
+        }
+        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);
+        }
+        let mut ap_price_tag = depth_asks[0].price + step;
+        let mut ap_index = 0;
+        for item in depth_asks.iter() {
+            let price = item.price;
+            let amount = item.amount;
+            if av.get(ap_index).is_none() { av.push(dec!(0)) };
+            if price < ap_price_tag {
+                av[ap_index] += amount;
+            } else {
+                ap_price_tag += step;
+                ap_index += 1;
+                if ap_index == public_params::LEVEL {
+                    break;
+                }
+                av[ap_index] += amount
+            }
+        }
+
+        let mut bp_price_tag = depth_bids[0].price - step;
+        let mut bp_index = 0;
+        for item in depth_bids.iter() {
+            let price = item.price;
+            let amount = item.amount;
+            if bv.get(bp_index).is_none() { bv.push(dec!(0)) };
+            if price > bp_price_tag {
+                bv[bp_index] += amount;
+            } else {
+                bp_price_tag -= step;
+                bp_index += 1;
+                if bp_index == public_params::LEVEL {
+                    break;
+                }
+                bv[bp_index] += amount
+            }
+        }
+
+        let ticker_info = SpecialTicker { sell: depth_asks[0].price, buy: depth_bids[0].price, mid_price: mp };
+        let depth_info = bp.iter().cloned().chain(bv.iter().cloned()).chain(ap.iter().cloned()).chain(av.iter().cloned()).collect();
+        SpecialDepth {
+            name: res_data.lable,
+            depth: depth_info,
+            ticker: ticker_info,
+        }
+    }
+}

+ 60 - 119
standard/src/kucoin_handle.rs

@@ -1,23 +1,25 @@
-use std::cmp::Ordering;
 use rust_decimal::Decimal;
-use rust_decimal::prelude::FromPrimitive;
 use rust_decimal_macros::dec;
-use serde_json::json;
 use exchanges::response_base::ResponseData;
-use global::public_params;
 use crate::{Account, MarketOrder, Order, Position, PositionModeEnum, SpecialDepth, SpecialOrder, SpecialTicker};
+use crate::exchange::ExchangeEnum;
+use crate::handle_info::HandleSwapInfo;
 
+// 处理账号信息
 pub fn handle_account_info(res_data: ResponseData, symbol: String) -> Account {
+    let res_data_str = res_data.data;
+    let res_data_json: serde_json::Value = serde_json::from_str(&res_data_str).unwrap();
+    format_account_info(res_data_json, symbol)
+}
+
+pub fn format_account_info(data: serde_json::Value, symbol: String) -> Account {
     let symbol_array: Vec<&str> = symbol.split("_").collect();
-    let res_data_str = &res_data.data;
-    let default_info = json!({"subject": "","data": {"availableBalance": 0, "holdBalance": 0, "currency":""}});
-    let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap_or(default_info);
     let mut available_balance = dec!(0);
     let mut frozen_balance = dec!(0);
     let mut balance = dec!(0);
-    if res_data_json["data"]["currency"].as_str().unwrap() == symbol_array[1].to_string() && res_data_json["subject"].as_str().unwrap() == "availableBalance.change" {
-        available_balance = res_data_json["data"]["availableBalance"].to_string().parse().unwrap_or(dec!(0));
-        frozen_balance = res_data_json["data"]["holdBalance"].to_string().parse().unwrap_or(dec!(0));
+    if data["data"]["currency"].as_str().unwrap() == symbol_array[1].to_string() && data["subject"].as_str().unwrap() == "availableBalance.change" {
+        available_balance = data["data"]["availableBalance"].to_string().parse().unwrap_or(dec!(0));
+        frozen_balance = data["data"]["holdBalance"].to_string().parse().unwrap_or(dec!(0));
         balance = available_balance + frozen_balance;
     }
     Account {
@@ -30,15 +32,38 @@ pub fn handle_account_info(res_data: ResponseData, symbol: String) -> Account {
     }
 }
 
+// 处理特殊Ticket信息
+pub fn handle_special_ticker(res_data: ResponseData) -> SpecialDepth {
+    let res_data_str = res_data.data;
+    let res_data_json: serde_json::Value = serde_json::from_str(&*res_data_str).unwrap();
+    format_special_ticker(res_data_json, res_data.lable)
+}
+
+pub fn format_special_ticker(data: serde_json::Value, label: String) -> SpecialDepth {
+    let bp = data["bestBidPrice"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
+    let bq = data["bestBidSize"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
+    let ap = data["bestAskPrice"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
+    let aq = data["bestAskSize"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
+    let mp = (bp + ap) * dec!(0.5);
+
+    let ticker_info = SpecialTicker { sell: ap, buy: bp, mid_price: mp };
+    let depth_info = vec![bp, bq, ap, aq];
+    SpecialDepth {
+        name: label,
+        depth: depth_info,
+        ticker: ticker_info,
+    }
+}
+
 // 处理position信息
 pub fn handle_position(res_data: ResponseData, amount_size: Decimal) -> Vec<Position> {
     let res_data_str = res_data.data;
     let res_data_json: Vec<serde_json::Value> = serde_json::from_str(&res_data_str).unwrap();
-    let result = res_data_json.iter().map(|item| { parse_position_item(item, amount_size) }).collect();
+    let result = res_data_json.iter().map(|item| { format_position_item(item, amount_size) }).collect();
     return result;
 }
 
-fn parse_position_item(position: &serde_json::Value, amount_size: Decimal) -> Position {
+pub fn format_position_item(position: &serde_json::Value, amount_size: Decimal) -> Position {
     let symbol = position["symbol"].as_str().unwrap_or("");
     let currency = position["settleCurrency"].as_str().unwrap_or("");
     let coin = &symbol[..symbol.find(currency).unwrap_or(0)];
@@ -64,127 +89,43 @@ pub fn handle_order(res_data: ResponseData, amount_size: Decimal) -> SpecialOrde
     let res_data_json: Vec<serde_json::Value> = serde_json::from_str(&*res_data_str).unwrap();
     let mut order_info = Vec::new();
     for item in res_data_json.iter() {
-        let id = item["id"].as_str().unwrap_or("").parse().unwrap();
-        let custom_id = item["clientOid"].as_str().unwrap_or("").parse().unwrap();
-        let price = item["price"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
-        let status = item["type"].as_str().unwrap_or("");
-        let size = item["size"].to_string().parse().unwrap_or(dec!(0));
-        let order_type = item["orderType"].as_str().unwrap_or("0").parse().unwrap_or("".to_string());
-        let filled_size = item["filledSize"].to_string().parse().unwrap_or(dec!(0));
-        let match_price = item["matchPrice"].to_string().parse().unwrap_or(dec!(0));
-
-        let amount = size * amount_size;
-        let deal_amount = filled_size * amount_size;
-        let avg_price = if status == "match" { match_price } else { price };
-        let custom_status = if ["done", "match"].contains(&status) { "REMOVE".to_string() } else if status == "open" { "NEW".to_string() } else { "OTHER".to_string() };
-        let order = Order {
-            id,
-            custom_id,
-            price,
-            amount,
-            deal_amount,
-            avg_price,
-            status: custom_status,
-            order_type,
-        };
-        order_info.push(order);
+        order_info.push(format_order_item(item.clone(), amount_size));
     }
-
     SpecialOrder {
         name: res_data.lable,
         order: order_info,
     }
 }
 
-// 处理特殊Ticket信息
-pub fn handle_special_ticker(res_data: ResponseData) -> SpecialDepth {
-    let res_data_str = res_data.data;
-    let res_data_json: serde_json::Value = serde_json::from_str(&*res_data_str).unwrap();
-    let bp = res_data_json["bestBidPrice"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
-    let bq = res_data_json["bestBidSize"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
-    let ap = res_data_json["bestAskPrice"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
-    let aq = res_data_json["bestAskSize"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
-    let mp = (bp + ap) * dec!(0.5);
+pub fn format_order_item(order: serde_json::Value, amount_size: Decimal) -> Order {
+    let price = order["price"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
+    let size = order["size"].to_string().parse().unwrap_or(dec!(0));
+    let status = order["status"].as_str().unwrap_or("");
+    let filled_size = order["filledSize"].to_string().parse().unwrap_or(dec!(0));
+    let match_price = order["matchPrice"].to_string().parse().unwrap_or(dec!(0));
 
-    let ticker_info = SpecialTicker { sell: ap, buy: bp, mid_price: mp };
-    let depth_info = vec![bp, bq, ap, aq];
-    let result = SpecialDepth {
-        name: res_data.lable,
-        depth: depth_info,
-        ticker: ticker_info,
-    };
-    return result;
+    let amount = size * amount_size;
+    let deal_amount = filled_size * amount_size;
+    let avg_price = if status == "match" { match_price } else { price };
+    let custom_status = if ["done", "match"].contains(&status) { "REMOVE".to_string() } else if status == "open" { "NEW".to_string() } else { "OTHER".to_string() };
+    Order {
+        id: order["id"].as_str().unwrap_or("").parse().unwrap(),
+        custom_id: order["clientOid"].as_str().unwrap_or("").parse().unwrap(),
+        price,
+        amount,
+        deal_amount,
+        avg_price,
+        status: custom_status,
+        order_type: order["type"].as_str().unwrap_or("").parse().unwrap(),
+    }
 }
 
 // 处理特殊深度数据
 pub fn handle_special_depth(res_data: ResponseData) -> SpecialDepth {
-    let res_data_str = res_data.data;
-    let res_data_json: serde_json::Value = serde_json::from_str(&*res_data_str).unwrap();
-    let mut depth_asks: Vec<MarketOrder> = parse_depth_items(&res_data_json["asks"]);
-    let mut depth_bids: Vec<MarketOrder> = parse_depth_items(&res_data_json["bids"]);
-    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));
-    let mp = (depth_asks[0].price + depth_bids[0].price) * dec!(0.5);
-    let step = (public_params::EFF_RANGE * mp / Decimal::from_usize(public_params::LEVEL).unwrap()).round_dp(mp.scale());
-    let mut ap = Vec::new();
-    let mut bp = Vec::new();
-    let mut av: Vec<Decimal> = Vec::new();
-    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);
-    }
-    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);
-    }
-    let mut ap_price_tag = depth_asks[0].price + step;
-    let mut ap_index = 0;
-    for item in depth_asks.iter() {
-        let price = item.price;
-        let amount = item.amount;
-        if av.get(ap_index).is_none() { av.push(dec!(0)) };
-        if price < ap_price_tag {
-            av[ap_index] += amount;
-        } else {
-            ap_price_tag += step;
-            ap_index += 1;
-            if ap_index == public_params::LEVEL {
-                break;
-            }
-            av[ap_index] += amount
-        }
-    }
-
-    let mut bp_price_tag = depth_bids[0].price - step;
-    let mut bp_index = 0;
-    for item in depth_bids.iter() {
-        let price = item.price;
-        let amount = item.amount;
-        if bv.get(bp_index).is_none() { bv.push(dec!(0)) };
-        if price > bp_price_tag {
-            bv[bp_index] += amount;
-        } else {
-            bp_price_tag -= step;
-            bp_index += 1;
-            if bp_index == public_params::LEVEL {
-                break;
-            }
-            bv[bp_index] += amount
-        }
-    }
-
-    let ticker_info = SpecialTicker { sell: depth_asks[0].price, buy: depth_bids[0].price, mid_price: mp };
-    let depth_info = bp.iter().cloned().chain(bv.iter().cloned()).chain(ap.iter().cloned()).chain(av.iter().cloned()).collect();
-    let result = SpecialDepth {
-        name: res_data.lable,
-        depth: depth_info,
-        ticker: ticker_info,
-    };
-    return result;
+    HandleSwapInfo::handle_special_depth(ExchangeEnum::KucoinSwap, res_data)
 }
 
-fn parse_depth_items(value: &serde_json::Value) -> Vec<MarketOrder> {
+pub fn format_depth_items(value: serde_json::Value) -> Vec<MarketOrder> {
     let mut depth_items: Vec<MarketOrder> = vec![];
     for value in value.as_array().unwrap() {
         depth_items.push(MarketOrder {

+ 17 - 57
standard/src/kucoin_swap.rs

@@ -6,13 +6,13 @@ use async_trait::async_trait;
 use futures::stream::FuturesUnordered;
 use futures::TryStreamExt;
 use rust_decimal::Decimal;
-use rust_decimal::prelude::ToPrimitive;
+use rust_decimal::prelude::{FromPrimitive, ToPrimitive};
 use rust_decimal_macros::dec;
 use serde_json::{json};
-use tracing::{debug, error};
+use tracing::{error};
 use exchanges::kucoin_swap_rest::KucoinSwapRest;
 use crate::exchange::ExchangeEnum;
-use crate::{Account, Market, Order, OrderCommand, Platform, Position, PositionModeEnum, Ticker, utils};
+use crate::{Account, kucoin_handle, Market, Order, OrderCommand, Platform, Position, Ticker, utils};
 
 #[allow(dead_code)]
 #[derive(Clone)]
@@ -67,7 +67,7 @@ impl Platform for KucoinSwap {
     // 获取请求时间
     fn get_request_delays(&self) -> Vec<i64> { self.request.get_delays() }
     // 获取请求平均时间
-    fn get_request_avg_delay(&self) -> Decimal { self.request.get_avg_delay()}
+    fn get_request_avg_delay(&self) -> Decimal { self.request.get_avg_delay() }
     // 获取请求最大时间
     fn get_request_max_delay(&self) -> i64 { self.request.get_max_delay() }
     // 获取服务器时间
@@ -112,7 +112,7 @@ impl Platform for KucoinSwap {
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
-            let result = parse_position_item(&res_data_json, amount_size);
+            let result = kucoin_handle::format_position_item(&res_data_json, amount_size);
             Ok(vec![result])
         } else {
             Err(Error::new(ErrorKind::Other, res_data.message))
@@ -126,7 +126,7 @@ impl Platform for KucoinSwap {
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
-            let result = res_data_json.iter().map(|item| { parse_position_item(item, amount_size) }).collect();
+            let result = res_data_json.iter().map(|item| { kucoin_handle::format_position_item(item, amount_size) }).collect();
             Ok(result)
         } else {
             Err(Error::new(ErrorKind::Other, res_data.message))
@@ -164,16 +164,19 @@ impl Platform for KucoinSwap {
             let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
             let default_info = json!({});
             let market_info = res_data_json.iter().find(|item| item["symbol"].as_str().unwrap() == symbol_format).unwrap_or(&default_info);
-            debug!("{}", market_info);
+            let tick_size = market_info["tickSize"].to_string().parse().unwrap_or(dec!(0));
+            let amount_size = market_info["multiplier"].to_string().parse().unwrap_or(dec!(0));
+            let price_precision = Decimal::from_u32(tick_size.scale()).unwrap();
+            let amount_precision = Decimal::from_u32(amount_size.scale()).unwrap();
 
             let result = Market {
                 symbol: self.symbol.clone(),
                 base_asset: market_info["baseCurrency"].as_str().unwrap_or("").to_string(),
                 quote_asset: market_info["quoteCurrency"].as_str().unwrap_or("").to_string(),
                 tick_size: market_info["tickSize"].to_string().parse().unwrap_or(dec!(0)),
-                amount_size: dec!(0),
-                price_precision: dec!(0),
-                amount_precision: dec!(0),
+                amount_size: market_info["multiplier"].to_string().parse().unwrap_or(dec!(0)),
+                price_precision,
+                amount_precision,
                 min_qty: market_info["lotSize"].to_string().parse().unwrap_or(dec!(0)),
                 max_qty: market_info["maxOrderQty"].to_string().parse().unwrap_or(dec!(0)),
                 min_notional: Default::default(),
@@ -192,7 +195,7 @@ impl Platform for KucoinSwap {
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
-            let result = parse_order_item(&res_data_json, amount_size);
+            let result = kucoin_handle::format_order_item(res_data_json, amount_size);
             Ok(result)
         } else {
             Err(Error::new(ErrorKind::Other, res_data.message))
@@ -207,7 +210,7 @@ impl Platform for KucoinSwap {
             let res_data_str = &res_data.data;
             let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
             let order_info: Vec<&serde_json::Value> = res_data_json.iter().filter(|item| item["contract"].as_str().unwrap_or("") == self.symbol.clone()).collect();
-            let result = order_info.iter().map(|item| parse_order_item(item, amount_size)).collect();
+            let result = order_info.iter().map(|&item| kucoin_handle::format_order_item(item.clone(), amount_size)).collect();
             Ok(result)
         } else {
             Err(Error::new(ErrorKind::Other, res_data.message))
@@ -257,7 +260,7 @@ impl Platform for KucoinSwap {
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
-            let result = parse_order_item(&res_data_json, amount_size);
+            let result = kucoin_handle::format_order_item(res_data_json, amount_size);
             Ok(result)
         } else {
             Err(Error::new(ErrorKind::Other, res_data.message))
@@ -270,7 +273,7 @@ impl Platform for KucoinSwap {
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
-            let result = parse_order_item(&res_data_json, amount_size);
+            let result = kucoin_handle::format_order_item(res_data_json, amount_size);
             Ok(result)
         } else {
             Err(Error::new(ErrorKind::Other, res_data.message))
@@ -365,46 +368,3 @@ impl Platform for KucoinSwap {
         let _: Result<Vec<_>, _> = futures.try_collect().await;
     }
 }
-
-fn parse_order_item(order: &serde_json::Value, amount_size: Decimal) -> Order {
-    let price = order["price"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
-    let size = order["size"].to_string().parse().unwrap_or(dec!(0));
-    let status = order["status"].as_str().unwrap_or("");
-    let filled_size = order["filledSize"].to_string().parse().unwrap_or(dec!(0));
-    let match_price = order["matchPrice"].to_string().parse().unwrap_or(dec!(0));
-
-    let amount = size * amount_size;
-    let deal_amount = filled_size * amount_size;
-    let avg_price = if status == "match" { match_price } else { price };
-    let custom_status = if ["done", "match"].contains(&status) { "REMOVE".to_string() } else if status == "open" { "NEW".to_string() } else { "OTHER".to_string() };
-    Order {
-        id: order["id"].as_str().unwrap_or("").parse().unwrap(),
-        custom_id: order["clientOid"].as_str().unwrap_or("").parse().unwrap(),
-        price,
-        amount,
-        deal_amount,
-        avg_price,
-        status: custom_status,
-        order_type: order["type"].as_str().unwrap_or("").parse().unwrap(),
-    }
-}
-
-fn parse_position_item(position: &serde_json::Value, amount_size: Decimal) -> Position {
-    let symbol = position["symbol"].as_str().unwrap_or("");
-    let currency = position["settleCurrency"].as_str().unwrap_or("");
-    let coin = &symbol[..symbol.find(currency).unwrap_or(0)];
-
-    let current_qty = position["currentQty"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
-    let amount = current_qty * amount_size;
-    let position_mode = if amount > dec!(0) { PositionModeEnum::Long } else { PositionModeEnum::Short };
-    Position {
-        symbol: format!("{}_{}", coin, currency),
-        margin_level: position["realLeverage"].as_str().unwrap_or("1").parse().unwrap_or(dec!(1)),
-        amount: amount.abs(),
-        frozen_amount: dec!(0),
-        price: position["avgEntryPrice"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
-        profit: position["unrealisedPnl"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
-        position_mode,
-        margin: position["posMargin"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
-    }
-}

+ 1 - 0
standard/src/lib.rs

@@ -19,6 +19,7 @@ mod gate_spot;
 pub mod gate_handle;
 mod kucoin_swap;
 pub mod kucoin_handle;
+pub mod handle_info;
 
 ///
 #[derive(Debug, Clone, PartialEq, Eq)]

+ 5 - 2
strategy/src/predictor.rs

@@ -1,7 +1,7 @@
 use std::collections::BTreeMap;
 use rust_decimal::prelude::*;
 use rust_decimal_macros::dec;
-use tracing::debug;
+use tracing::{debug, info};
 use tracing::field::debug;
 use standard::Ticker;
 use global::public_params;
@@ -54,8 +54,9 @@ impl Predictor {
 
         // 更新mid_price
         let bid_price = last_market_info[public_params::BID_PRICE_INDEX];
-        let ask_price = last_market_info[public_params::BID_PRICE_INDEX];
+        let ask_price = last_market_info[public_params::ASK_PRICE_INDEX];
         let mid_price = (bid_price + ask_price) * dec!(0.5);
+        debug!(?last_market_info);
         debug!(?bid_price, ?ask_price, ?mid_price);
         self.mid_price_list.push(mid_price);
 
@@ -69,6 +70,7 @@ impl Predictor {
             // 依照交易所次序添加到ref_mid_price_per_exchange中
             ref_mid_price_per_exchange.push(ref_mid_price);
         }
+        debug!(?ref_mid_price_per_exchange);
         self.ref_mid_price_per_exchange_per_frame.push(ref_mid_price_per_exchange);
 
         // 价差更新
@@ -116,6 +118,7 @@ impl Predictor {
 
     // 市场信息处理器,也是python里的onTime方法
     pub fn market_info_handler(&mut self, new_market_info: &Vec<Decimal>) {
+        debug!(?new_market_info);
         // 空数据不处理
         if new_market_info.len() == 0 {
             return;

+ 10 - 2
strategy/src/quant.rs

@@ -200,6 +200,7 @@ impl Quant {
             let depths_key: String = tickers_key.clone();
             let market_update_time_key = tickers_key.clone();
             let market_update_interval_key = tickers_key.clone();
+            let max_buy_min_sell_cache_key = tickers_key.clone();
 
             quant_obj.tickers.insert(tickers_key, SpecialTicker {
                 sell: Default::default(),
@@ -210,12 +211,14 @@ impl Quant {
             quant_obj.depths.insert(depths_key, Default::default());
             quant_obj.market_update_time.insert(market_update_time_key, Default::default());
             quant_obj.market_update_interval.insert(market_update_interval_key, Default::default());
+            quant_obj.max_buy_min_sell_cache.insert(max_buy_min_sell_cache_key, vec![Decimal::ZERO, Decimal::ZERO]);
         }
         let name = format!("{}{}{}", quant_obj.exchange.clone(), "@", quant_obj.symbol);
         let market_update_time_key = name.clone();
         let market_update_interval_key = name.clone();
         let tickers_key = name.clone();
         let depths_key = name.clone();
+        let max_buy_min_sell_cache_key = name.clone();
         quant_obj.trade_name = name;
         quant_obj.market_update_time.insert(market_update_time_key, Default::default());
         quant_obj.market_update_interval.insert(market_update_interval_key, Default::default());
@@ -225,6 +228,7 @@ impl Quant {
             mid_price: Default::default(),
         });
         quant_obj.depths.insert(depths_key, Default::default());
+        quant_obj.max_buy_min_sell_cache.insert(max_buy_min_sell_cache_key, vec![Decimal::ZERO, Decimal::ZERO]);
         // broker.newWs
         let mut price_alpha: Vec<Decimal> = Vec::new();
         for ref_pair_str in params.ref_pair {
@@ -1109,8 +1113,12 @@ pub fn run_strategy(quant_arc: Arc<Mutex<Quant>>) -> JoinHandle<()>{
             }
             // 计算耗时并进行休眠
             let pass_time = Utc::now().timestamp_millis() - start_time;
-            sleep(Duration::from_millis(quant.interval.to_u64().unwrap() - pass_time.to_u64().unwrap())).await;
-        }
+            let mut delay = 1u64;
+            if pass_time < quant.interval.to_i64().unwrap() {
+                delay = quant.interval.to_u64().unwrap() - pass_time.to_u64().unwrap();
+            }
+            sleep(Duration::from_millis(delay)).await;
+           }
     });
 }
 pub async fn run_transaction(quant_arc: Arc<Mutex<Quant>>, name: String, symbols: Vec<String>, exchange_params: BTreeMap<String, String>) {