Explorar el Código

Merge branch 'master' of http://git.skyfffire.com/skyfffire/as-market-binance-okx-spot

875428575@qq.com hace 2 años
padre
commit
5cd5a02ad4
Se han modificado 3 ficheros con 172 adiciones y 114 borrados
  1. 73 70
      src/exchange_middle_ware.rs
  2. 92 42
      src/main.rs
  3. 7 2
      tests/hook_test.rs

+ 73 - 70
src/exchange_middle_ware.rs

@@ -1,7 +1,7 @@
-use std::io::{Error, ErrorKind};
+use std::io::{ Error, ErrorKind};
 use std::collections::{BTreeMap};
 use serde_json::json;
-use crate::exchange_libs::{BinanceExc, OkxExc, SocketTool};
+use crate::exchange_libs::{BinanceExc, OkxExc, ReqData, SocketTool};
 
 // 深度结构体
 #[derive(Debug)]
@@ -119,23 +119,24 @@ impl Exchange {
     // 获取币安深度信息
     // symbol: 交易币对, "BTC_USDT"
     // limit: 返回条数, 最大 5000. 可选值:[5, 10, 20, 50, 100, 500, 1000, 5000]
-    pub async fn get_binance_depth(&self, symbol: &String, limit: i32) -> Result<Depth, Error> {
+    pub async fn get_binance_depth(&self, symbol: &String, limit: i32, callback: fn(Depth)) {
         let real_symbol = self.get_real_symbol(symbol, "".to_string());
-        // SocketTool::binance_run_depth(vec![symbol], limit.to_string(), aa);
-        let req_data = self.binance_exc.binance_depth(&real_symbol, &limit.to_string()).await;
-        if req_data.code == "0" {
-            let req_data_str = req_data.data;
-            let req_data_json: serde_json::Value = serde_json::from_str(&*req_data_str).unwrap();
-            let depth_asks: Vec<DepthItem> = parse_depth_items(&req_data_json["asks"]);
-            let depth_bids: Vec<DepthItem> = parse_depth_items(&req_data_json["bids"]);
-            let result = Depth {
-                asks: depth_asks,
-                bids: depth_bids,
-            };
-            Ok(result)
-        } else {
-            Err(Error::new(ErrorKind::Other, req_data.message))
-        }
+        let get_res_data =|res_data:ReqData|{
+            if res_data.code == "0" {
+                let res_data_str = res_data.data;
+                let res_data_json: serde_json::Value = serde_json::from_str(&*res_data_str).unwrap();
+                let depth_asks: Vec<DepthItem> = parse_depth_items(&res_data_json["asks"]);
+                let depth_bids: Vec<DepthItem> = parse_depth_items(&res_data_json["bids"]);
+                let result = Depth {
+                    asks: depth_asks,
+                    bids: depth_bids,
+                };
+                callback(result)
+            } else {
+                panic!("get_binance_depth: {}",res_data.message);
+            }
+        };
+        SocketTool::binance_run_depth(vec![&real_symbol], limit.to_string(), get_res_data)
     }
 
 
@@ -145,12 +146,12 @@ impl Exchange {
     // limit: 返回条数, 最大 1000
     pub async fn get_binance_klines(&self, symbol: &String, interval: &String, limit: &i32) -> Result<Vec<Record>, Error> {
         let real_symbol = self.get_real_symbol(symbol, "".to_string());
-        let req_data = self.binance_exc.binance_k(&real_symbol, interval, &limit.to_string()).await;
-        if req_data.code == "0" {
-            let req_data_str = req_data.data;
-            let req_data_json: Vec<Vec<serde_json::Value>> = serde_json::from_str(&*req_data_str).unwrap();
+        let res_data = self.binance_exc.binance_k(&real_symbol, interval, &limit.to_string()).await;
+        if res_data.code == "0" {
+            let res_data_str = res_data.data;
+            let res_data_json: Vec<Vec<serde_json::Value>> = serde_json::from_str(&*res_data_str).unwrap();
             let mut result: Vec<Record> = vec![];
-            for item in req_data_json.iter() {
+            for item in res_data_json.iter() {
                 let record = Record {
                     time: item[0].as_i64().unwrap_or(0),
                     open: item[1].as_str().unwrap_or("0").parse().unwrap_or(0.0),
@@ -163,7 +164,7 @@ impl Exchange {
             }
             Ok(result)
         } else {
-            Err(Error::new(ErrorKind::Other, req_data.message))
+            Err(Error::new(ErrorKind::Other, res_data.message))
         }
     }
 
@@ -171,12 +172,12 @@ impl Exchange {
     // symbol: 交易币对, "BTC_USDT"
     pub async fn get_okx_account(&self, symbol: &String) -> Result<Account, Error> {
         let real_symbol = self.get_real_symbol(symbol, ",".to_string());
-        let req_data = self.okx_exc.okx_acc(&real_symbol).await;
-        if req_data.code == "0" {
-            let req_data_str = req_data.data;
-            let req_data_json: Vec<serde_json::Value> = serde_json::from_str(&*req_data_str).unwrap();
+        let res_data = self.okx_exc.okx_acc(&real_symbol).await;
+        if res_data.code == "0" {
+            let res_data_str = res_data.data;
+            let res_data_json: Vec<serde_json::Value> = serde_json::from_str(&*res_data_str).unwrap();
             let symbol_array: Vec<&str> = symbol.split("_").collect();
-            let details = req_data_json[0]["details"].as_array().unwrap();
+            let details = res_data_json[0]["details"].as_array().unwrap();
             let default_info = json!({"availBal":"0","fixedBal":"0"});
             let stocks_info = details.iter().find(|item| item["ccy"].as_str().unwrap() == symbol_array[0].to_string()).unwrap_or(&default_info);
             let balance_info = details.iter().find(|item| item["ccy"].as_str().unwrap() == symbol_array[1].to_string()).unwrap_or(&default_info);
@@ -188,7 +189,7 @@ impl Exchange {
             };
             Ok(result)
         } else {
-            Err(Error::new(ErrorKind::Other, req_data.message))
+            Err(Error::new(ErrorKind::Other, res_data.message))
         }
     }
 
@@ -200,14 +201,14 @@ impl Exchange {
     // amount: 委托数量
     pub async fn place_okx_order(&self, symbol: &String, side: &String, order_type: &String, price: &String, amount: &String) -> Result<String, Error> {
         let real_symbol = self.get_real_symbol(symbol, "-".to_string());
-        let req_data = self.okx_exc.okx_order(&real_symbol, "cash", side, order_type, price, amount).await;
-        if req_data.code == "0" {
-            let req_data_str = req_data.data;
-            let req_data_json: Vec<serde_json::Value> = serde_json::from_str(&*req_data_str).unwrap();
-            let result = req_data_json[0]["ordId"].as_str().unwrap().parse().unwrap();
+        let res_data = self.okx_exc.okx_order(&real_symbol, "cash", side, order_type, price, amount).await;
+        if res_data.code == "0" {
+            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[0]["ordId"].as_str().unwrap().parse().unwrap();
             Ok(result)
         } else {
-            Err(Error::new(ErrorKind::Other, req_data.message))
+            Err(Error::new(ErrorKind::Other, res_data.message))
         }
     }
 
@@ -216,22 +217,22 @@ impl Exchange {
     // order_id: 订单ID, "590910403358593111"
     pub async fn get_okx_order(&self, symbol: &String, order_id: &String) -> Result<Order, Error> {
         let real_symbol = self.get_real_symbol(symbol, "-".to_string());
-        let req_data = self.okx_exc.okx_get_order(&real_symbol, order_id).await;
-        if req_data.code == "0" {
-            let req_data_str = req_data.data;
-            let req_data_json: Vec<serde_json::Value> = serde_json::from_str(&*req_data_str).unwrap();
+        let res_data = self.okx_exc.okx_get_order(&real_symbol, order_id).await;
+        if res_data.code == "0" {
+            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 = Order {
-                id: req_data_json[0]["ordId"].as_str().unwrap().parse().unwrap(),
-                price: req_data_json[0]["px"].as_str().unwrap_or("0").parse().unwrap_or(0.0),
-                amount: req_data_json[0]["sz"].as_str().unwrap_or("0").parse().unwrap_or(0.0),
-                deal_amount: req_data_json[0]["accFillSz"].as_str().unwrap_or("0").parse().unwrap_or(0.0),
-                avg_price: req_data_json[0]["avgPx"].as_str().unwrap_or("0").parse().unwrap_or(0.0),
-                status: req_data_json[0]["state"].as_str().unwrap().parse().unwrap(),
-                order_type: req_data_json[0]["instType"].as_str().unwrap().parse().unwrap(),
+                id: res_data_json[0]["ordId"].as_str().unwrap().parse().unwrap(),
+                price: res_data_json[0]["px"].as_str().unwrap_or("0").parse().unwrap_or(0.0),
+                amount: res_data_json[0]["sz"].as_str().unwrap_or("0").parse().unwrap_or(0.0),
+                deal_amount: res_data_json[0]["accFillSz"].as_str().unwrap_or("0").parse().unwrap_or(0.0),
+                avg_price: res_data_json[0]["avgPx"].as_str().unwrap_or("0").parse().unwrap_or(0.0),
+                status: res_data_json[0]["state"].as_str().unwrap().parse().unwrap(),
+                order_type: res_data_json[0]["instType"].as_str().unwrap().parse().unwrap(),
             };
             Ok(result)
         } else {
-            Err(Error::new(ErrorKind::Other, req_data.message))
+            Err(Error::new(ErrorKind::Other, res_data.message))
         }
     }
 
@@ -240,15 +241,15 @@ impl Exchange {
     // order_id: 订单ID, "590910403358593111"
     pub async fn cancel_okx_order(&self, symbol: &String, order_id: &String) -> Result<bool, Error> {
         let real_symbol = self.get_real_symbol(symbol, "-".to_string());
-        let req_data = self.okx_exc.okx_revocation_order(&real_symbol, order_id).await;
-        if req_data.code == "0" {
-            let req_data_str = req_data.data;
-            let req_data_json: Vec<serde_json::Value> = serde_json::from_str(&*req_data_str).unwrap();
-            let order_info = req_data_json[0]["sCode"].as_str().unwrap();
+        let res_data = self.okx_exc.okx_revocation_order(&real_symbol, order_id).await;
+        if res_data.code == "0" {
+            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 = res_data_json[0]["sCode"].as_str().unwrap();
             let result = if order_info == "0" { true } else { false };
             Ok(result)
         } else {
-            Err(Error::new(ErrorKind::Other, req_data.message))
+            Err(Error::new(ErrorKind::Other, res_data.message))
         }
     }
 
@@ -261,11 +262,11 @@ impl Exchange {
         btree_map.insert("instType", "SPOT");
         let result = self.okx_exc.get_v("/api/v5/public/instruments".to_string(), btree_map).await;
         match result {
-            Ok(req_data) => {
+            Ok(res_data) => {
                 let symbol_array: Vec<&str> = symbol.split("_").collect();
-                let req_data_str = req_data.data;
-                let req_data_json: serde_json::Value = serde_json::from_str(&*req_data_str).unwrap();
-                let order_info = req_data_json["data"].as_array().unwrap();
+                let res_data_str = res_data.data;
+                let res_data_json: serde_json::Value = serde_json::from_str(&*res_data_str).unwrap();
+                let order_info = res_data_json["data"].as_array().unwrap();
                 let info = order_info.iter().find(|item| item["baseCcy"].as_str().unwrap() == symbol_array[0] && item["quoteCcy"].as_str().unwrap() == symbol_array[1]).unwrap();
                 println!("\n\n{:?}", info);
 
@@ -284,20 +285,20 @@ impl Exchange {
                     ct_val: 0.01,
                 };
                 println!("\n\n{:?}", result);
-                // let order_info = req_data_json;
+                // let order_info = res_data_json;
             }
             Err(err) => {}
         }
         // let real_symbol = self.get_real_symbol(symbol, "-".to_string());
-        // let req_data = self.okx_exc.get_v("/api/v5/public/instruments", order_id).await;
-        // if req_data.code == "0" {
-        //     let req_data_str = req_data.data;
-        //     let req_data_json: Vec<serde_json::Value> = serde_json::from_str(&*req_data_str).unwrap();
-        //     let order_info = req_data_json[0]["sCode"].as_str().unwrap();
+        // let res_data = self.okx_exc.get_v("/api/v5/public/instruments", order_id).await;
+        // if res_data.code == "0" {
+        //     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 = res_data_json[0]["sCode"].as_str().unwrap();
         //     let result = if order_info == "0" { true } else { false };
         //     Ok(result)
         // } else {
-        //     Err(Error::new(ErrorKind::Other, req_data.message))
+        //     Err(Error::new(ErrorKind::Other, res_data.message))
         // }
     }
 }
@@ -318,8 +319,9 @@ fn parse_depth_items(value: &serde_json::Value) -> Vec<DepthItem> {
 // 单元测试集
 #[cfg(test)]
 mod tests {
-    use crate::exchange_middle_ware::{Exchange};
-    use crate::exchange_libs::{is_proxy};
+    use std::io::{self, Write};
+    use crate::exchange_middle_ware::{Depth, Exchange};
+    use crate::exchange_libs::{is_proxy, ReqData};
 
     // new Exchange
     fn new_exchange() -> Exchange {
@@ -346,10 +348,11 @@ mod tests {
     // 测试binance获取深度信息
     #[tokio::test]
     async fn test_get_binance_depth() {
-        is_proxy();
         let exchange = new_exchange();
-        let depth = exchange.get_binance_depth(&"DOGE_USDT".to_string(), 10).await;
-        println!("test_get_binance_depth:{:?}", depth);
+        let get_depth_fn = |depth:Depth|{
+            writeln!(io::stdout(), "test_get_binance_depth:{:?}", depth).unwrap();
+        };
+        exchange.get_binance_depth(&"DOGE_USDT".to_string(), 10,get_depth_fn).await;
     }
 
     // 测试binance获取k线

+ 92 - 42
src/main.rs

@@ -1,9 +1,11 @@
-use std::io;
+use std::{env, io};
+use chrono::format::Item::Error;
 use ndarray::prelude::*;
-use rust_decimal::prelude::{ToPrimitive, Zero};
+use rust_decimal::prelude::{ToPrimitive};
 use crate::as_libs::*;
-use crate::exchange_middle_ware::{Account, cancel_okx_order, get_binance_depth, get_binance_klines, get_okx_account, get_okx_order, Order, place_okx_order, Record};
+use crate::exchange_middle_ware::{Account, Depth, Exchange, Order, Record};
 use time::OffsetDateTime;
+use crate::exchange_libs::is_proxy;
 
 mod as_libs;
 mod exchange_libs;
@@ -52,11 +54,18 @@ struct Bot {
     last_buy_time: i64,
     buy_time_limit: i64,
     cancel_time_limit: i64,
-    price_decimal_places: usize
+    price_decimal_places: usize,
+    mid_price: f64,
+    ask: f64,
+    bid: f64,
+    spread_list_limit: usize
 }
 
 impl Bot {
-    fn new(spread_list: Vec<f64>, symbol: String, limit: i32, short_interval: String, rl_start: f64, rl_end: f64, quantity_max: f64, amount_decimal_places: usize, order_info_list: Vec<OrderInfo>, last_buy_time: i64, buy_time_limit: i64, cancel_time_limit: i64, price_decimal_places: usize) -> Bot {
+    fn new(spread_list: Vec<f64>, symbol: String, limit: i32, short_interval: String,
+           rl_start: f64, rl_end: f64, quantity_max: f64, amount_decimal_places: usize,
+           order_info_list: Vec<OrderInfo>, last_buy_time: i64, buy_time_limit: i64,
+           cancel_time_limit: i64, price_decimal_places: usize, spread_list_limit: usize) -> Bot {
         Bot {
             spread_list,
             symbol,
@@ -70,32 +79,49 @@ impl Bot {
             last_buy_time,
             buy_time_limit,
             cancel_time_limit,
-            price_decimal_places
+            price_decimal_places,
+            mid_price: 0.0,
+            ask: 0.0,
+            bid: 0.0,
+            spread_list_limit
+        }
+    }
+
+    fn depth_handler(&mut self, depth: &Depth){
+        let (spread, mid_price, ask, bid) = get_spread(depth);
+        self.mid_price = mid_price;
+        self.ask = ask;
+        self.bid = bid;
+        if self.spread_list.len() > self.spread_list_limit {
+            self.spread_list.remove(0);
         }
+        self.spread_list.push(spread);
     }
 
     async fn start(&mut self){
-        while true {
-            let f = match self.do_logic().await {
+        is_proxy();
+        // 使用std::env::var函数获取环境变量的值
+        let okx_access_key= env::var("okx_access_key").unwrap();
+        let okx_secret_key= env::var("okx_secret_key").unwrap();
+        let okx_passphrase= env::var("okx_passphrase").unwrap();
+
+        let exchange:Exchange = Exchange::new(okx_access_key, okx_secret_key, okx_passphrase);
+        let bot = self;
+        let get_depth_fn = |depth:&Depth| Self::depth_handler(&mut *bot, depth);
+        exchange.get_binance_depth(&bot.symbol, 10, get_depth_fn).await;
+
+        loop {
+            let f = match bot.do_logic(&exchange).await {
                 Ok(m) => m,
                 Err(error) => {
+                    eprintln!("异常出现,捕获异常: {}", error);
                     1
                 },
             };
         }
     }
 
-    async fn do_logic(&mut self) -> Result<i8, io::Error>{
-        let depth = get_binance_depth(&self.symbol, self.limit).await;
-
-        // 1.获取最新spread,如何将主逻辑和spread(ws推送方式)关联起来
-        let (spread, mid_price, ask, bid) = get_spread(&depth);
-
-        if self.spread_list.len() > 300 {
-            self.spread_list.remove(0);
-        }
-        self.spread_list.push(spread);
-
+    async fn do_logic(&mut self, exchange: &Exchange) -> Result<i8, io::Error>{
         // 使用 max_by 方法和 partial_cmp 进行比较
         let max_option = self.spread_list.iter().max_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
         match max_option {
@@ -105,17 +131,28 @@ impl Bot {
         let max_spread =  *max_option.unwrap();
 
         if self.spread_list.len() < 10 {
-
+            println!()
         } else {
             // 1.获取账户信息
-            let balance_info = get_okx_account(&self.symbol).await;
+            let balance_info = match exchange.get_okx_account(&self.symbol).await {
+                Ok(m) => m,
+                Err(error) => {
+                    return Err(error);
+                }
+            };
+            println!("info: {:?}", balance_info);
             // 取消超时订单
-            self.order_list_deal(&balance_info.stocks).await;
+            self.order_list_deal(&balance_info.stocks, exchange).await.expect("订单信息处理异常!");
 
             // 2.获取最新k线
-            let k_line_data = get_binance_klines(&self.symbol.to_string(), &self.short_interval, &200).await;
+            let k_line_data = match  exchange.get_binance_klines(&self.symbol.to_string(), &self.short_interval, &200).await {
+                Ok(m) => m,
+                Err(error) => {
+                    return Err(error);
+                }
+            };
             // rl_list 计算
-            let (q, rl_list) = self.calc_params(&k_line_data, balance_info, max_spread, mid_price, bid, ask);
+            let (q, rl_list) = self.calc_params(&k_line_data, balance_info, max_spread);
 
             let rate :f64 = (q/self.quantity_max) * 100.0;
             let index_f :f64 = rl_list.len().to_f64().unwrap() / 100.0 * rate;
@@ -134,7 +171,7 @@ impl Bot {
                 return Ok(0);
             }
             // 下单
-            let buy_order_id = place_okx_order(&self.symbol, &"buy".to_string(), &"limit".to_string(), &order_dict.buy_price.to_string(), &order_dict.order_amount.to_string()).await;
+            let buy_order_id = exchange.place_okx_order(&self.symbol, &"buy".to_string(), &"limit".to_string(), &order_dict.buy_price.to_string(), &order_dict.order_amount.to_string()).await.unwrap();
             let order = OrderInfo{
                 id: buy_order_id,
                 sell_price: order_dict.sell_price,
@@ -144,15 +181,15 @@ impl Bot {
             self.order_info_list.push(order);
             self.last_buy_time = now_time;
         }
-        return Ok(1);
+        return Ok(0);
     }
 
-    fn calc_params(&self, k_line_data: &Vec<Record>, balance_info: Account, max_spread: f64, mid_price:f64, bid: f64, ask: f64) -> (f64, Vec<RiskLevel>){
+    fn calc_params(&self, k_line_data: &Vec<Record>, balance_info: Account, max_spread: f64) -> (f64, Vec<RiskLevel>){
         // 计算最近20根K线的标准差
         // 3.获取标准差数组的最后一个值
         let last_std = std_n_by_records(k_line_data, 20);
         // 4.计算库存资产折合本位币价值
-        let mut q = (balance_info.stocks + balance_info.frozen_stocks) * mid_price;
+        let mut q = (balance_info.stocks + balance_info.frozen_stocks) * self.mid_price;
         if q < 1.0 {
             q = 1.0;
         }
@@ -167,9 +204,9 @@ impl Bot {
             // 7.获取dd
             let dd = calc_deviation_range(self.rl_end, &self.spread_list, *i);
             // 8.获取Reservation price 预定价格
-            let rp = calc_rp(mid_price, q, *i, gamma, last_std);
+            let rp = calc_rp(self.mid_price, q, *i, gamma, last_std);
             // eprintln!("rp {}, dd {}, ask {}, bid {}", rp, dd, ask, bid);
-            if (rp + 0.5 * dd) < ask || (rp - 0.5 * dd) > bid {
+            if (rp + 0.5 * dd) < self.ask || (rp - 0.5 * dd) > self.bid {
                 continue;
             }
             // 9.获取dk,用于计算e的dk次方
@@ -181,16 +218,16 @@ impl Bot {
             // 11.获取theta
             let cal_theta = calc_theta(gamma, last_std, kappa, *i);
             // 交易数量
-            let order_amount = calc_order_amount(self.rl_end, *i, q, self.quantity_max, bid, self.amount_decimal_places);
+            let order_amount = calc_order_amount(self.rl_end, *i, q, self.quantity_max, self.bid, self.amount_decimal_places);
             let rl_info = RiskLevel{
                 gamma: gamma*i,
-                mid_price,
+                mid_price: self.mid_price,
                 rp,
                 theta_a_b_half: 0.5*dd,
                 bid: rp - cal_theta,
-                bid_best: bid,
+                bid_best: self.bid,
                 ask: rp + cal_theta,
-                ask_best: ask,
+                ask_best: self.ask,
                 kappa,
                 cal_theta,
                 order_amount
@@ -200,9 +237,9 @@ impl Bot {
         return (q, rl_list);
     }
 
-    async fn order_list_deal(&mut self, stocks: &f64){
+    async fn order_list_deal(&mut self, stocks: &f64, exchange: &Exchange) -> Result<i8, io::Error> {
         if self.order_info_list.len() == 0{
-            return;
+            return Ok(1_i8);
         }
         let now_time = OffsetDateTime::now_utc().unix_timestamp();
         let mut next_list:Vec<OrderInfo> = vec![];
@@ -210,18 +247,28 @@ impl Bot {
         // 超300s 需取消的订单
         for order in self.order_info_list.iter_mut(){
             eprintln!("order_id: {:?} ", order);
-            let order_info: Order = get_okx_order(&self.symbol, &order.id).await;
+            let order_info: Order = exchange.get_okx_order(&self.symbol, &order.id).await.unwrap();
             eprintln!("order_info: {:?}", order_info);
             // 已成交的订单
             if order_info.status.eq("filled"){
                 // 防止有手续费的账户导致的余额小于实际下单数额
                 let order_amount = f64::min(*stocks, order_info.amount);
-                let id = place_okx_order(&self.symbol, &"sell".to_string(), &"limit".to_string(), &order.sell_price.to_string(), &order_amount.to_string()).await;
+                let id = match exchange.place_okx_order(&self.symbol, &"sell".to_string(), &"limit".to_string(), &order.sell_price.to_string(), &order_amount.to_string()).await {
+                    Ok(m) => m,
+                    Err(error) => {
+                        return Err(error);
+                    }
+                };
                 eprintln!("卖单id: {}", id);
             } else if order.time_num + self.cancel_time_limit < now_time { // 未成交 && 超时
-                cancel_okx_order(&self.symbol, &order.id).await;
+                let is_success = match exchange. cancel_okx_order(&self.symbol, &order.id).await {
+                    Ok(m) => m,
+                    Err(error) => {
+                        return Err(error);
+                    }
+                };
                 // 取消订单,可以在这里执行取消订单的操作
-                eprintln!("取消订单: {}, 订单下单时间:{}, 现在时间: {}", order.id, order.time_num, now_time);
+                eprintln!("是否成功:{}, 取消订单: {}, 订单下单时间:{}, 现在时间: {}", is_success, order.id, order.time_num, now_time);
             } else {
                 // 使用解构复制满足条件的订单
                 let new_order = OrderInfo {
@@ -235,8 +282,10 @@ impl Bot {
         }
         self.order_info_list.clear();
         self.order_info_list.extend(next_list);
+        return Ok(1_i8);
     }
 
+
 }
 
 
@@ -268,9 +317,10 @@ async fn main() {
     let cancel_time_limit = 30;
     // 价格小数位数
     let price_decimal_places = 2;
+    // spread_list_limit 长度限制
+    let spread_list_limit = 10;
 
-
-    let mut bot = Bot::new(spread_list, symbol, limit, short_interval, rl_start, rl_end, quantity_max, amount_decimal_places, order_info_list, last_buy_time, buy_time_limit, cancel_time_limit, price_decimal_places);
+    let mut bot = Bot::new(spread_list, symbol, limit, short_interval, rl_start, rl_end, quantity_max, amount_decimal_places, order_info_list, last_buy_time, buy_time_limit, cancel_time_limit, price_decimal_places, spread_list_limit);
     bot.start().await;
 
 }

+ 7 - 2
tests/hook_test.rs

@@ -9,6 +9,12 @@ impl Main {
         }
     }
 
+    fn call_b(&mut self, middle: &MiddleWare) {
+        let a = self;
+        let hook = |deep_spread: &f64| Self::hook_func_demo(a, deep_spread);
+        middle.call_hook(hook);
+    }
+
     // 钩子演示方法
     fn hook_func_demo(&mut self, depth_spread: &f64) {
         self.spread_list.push(depth_spread.clone());
@@ -38,8 +44,7 @@ async fn test_hook() {
     let mut a = Main::new();
     let b = MiddleWare::new(0.1);
 
-    let hook = |deep_spread: &f64| a.hook_func_demo(deep_spread);
-    b.call_hook(hook);
+    a.call_b(&b);
 
     println!("{:?}", a.spread_list);
 }