瀏覽代碼

使用新版订单检查方法

skyfffire 2 周之前
父節點
當前提交
70726ef535
共有 4 個文件被更改,包括 105 次插入75 次删除
  1. 5 0
      src/data_manager.rs
  2. 5 5
      src/exchange/extended_rest_client.rs
  3. 1 6
      src/main.rs
  4. 94 64
      src/strategy.rs

+ 5 - 0
src/data_manager.rs

@@ -75,6 +75,11 @@ impl DataManager {
         
         // 3. 根据 topic_info 的内容进行分发 (match)
         if topic_info.contains("ExtendedBestPrices") {
+            // 数据不新鲜直接跳过
+            if response.reach_time - response.received_time > 100 {
+                return Ok(());
+            }
+            
             self.process_best_prices(&v).await?;            
         } else if topic_info.contains("ExtendedAccount") {
             self.process_account(&v).await?;

+ 5 - 5
src/exchange/extended_rest_client.rs

@@ -209,7 +209,7 @@ impl ExtendedRestClient {
         ).await
     }
 
-    pub async fn post_order(&mut self, order_type: &str, side: &str, qty: &str, price: &str, reduce_only: bool) -> Result<Response> {
+    pub async fn post_order(&mut self, order_type: &str, side: &str, qty: &str, price: &str, post_only: bool, reduce_only: bool) -> Result<Response> {
         let account = self.account.clone().ok_or_else(|| anyhow!("请将账户传入再进行下单操作"))?;
 
         // 时间戳处理
@@ -354,7 +354,7 @@ impl ExtendedRestClient {
             "expiryEpochMillis": expiry_epoch_millis,
             "fee": total_fee_rate.to_string(),
             "nonce": nonce,
-            "postOnly": false,
+            "postOnly": post_only,
             "reduceOnly": reduce_only,
             "settlement": settlement,
             "selfTradeProtectionLevel": self_trade_protection_level,
@@ -537,7 +537,7 @@ mod tests {
 
     async fn get_client() -> ExtendedRestClient {
         let config = Config::load().unwrap();
-        
+
         let tag = "Extended";
         let market = config.strategy.market.as_str();
         let account = ExtendedAccount::new(
@@ -582,7 +582,7 @@ mod tests {
     async fn test_get_order() {
         let _guard = setup_logging().unwrap();
         let mut client = get_client().await;
-        let response = client.get_order("1978656082822787072").await;
+        let response = client.get_order("1981274685908439040").await;
 
         info!("{}", serde_json::to_string_pretty(&response.data).unwrap());
     }
@@ -591,7 +591,7 @@ mod tests {
     async fn test_create_order() {
         let _guard = setup_logging().unwrap();
         let mut client = get_client().await;
-        let response_result = client.post_order("LIMIT", "BUY", "0.0001", "100000", false).await;
+        let response_result = client.post_order("LIMIT", "BUY", "0.0001", "100000", false, false).await;
 
         match response_result {
             Ok(response) => {

+ 1 - 6
src/main.rs

@@ -147,12 +147,7 @@ pub async fn run_extended_subscriptions(running: Arc<AtomicBool>, config: &Confi
 
             let dm_clone = Arc::clone(&dm);
             let sm_clone = Arc::clone(&sm);
-            async move {
-                // 数据不新鲜直接跳过
-                if response.reach_time - response.received_time > 100 {
-                    return
-                }
-                
+            async move {                
                 let mut dm_guard = dm_clone.lock().await;
 
                 // 记录消息延迟

+ 94 - 64
src/strategy.rs

@@ -3,6 +3,7 @@ use std::sync::Arc;
 use anyhow::{anyhow, bail, Result};
 use rust_decimal::Decimal;
 use std::time::{Duration, Instant};
+use serde_json::Value;
 use tokio::sync::Mutex;
 use tokio::time::sleep;
 use tracing::{info, warn};
@@ -156,14 +157,15 @@ impl Strategy {
         self.last_query_order_time = Instant::now();
 
         // 检查订单是否已成交
-        match self.check_order_filled(&order_id, dm).await {
-            Ok(true) => {
-                info!("限价单已成交,准备执行市价单");
-                self.state = StrategyState::ExecutingMarketOrder { };
-                return Ok(());
-            }
-            Ok(false) => {
-                // 订单未成交,继续检查价格
+        match self.check_order_filled_status(&order_id, dm).await {
+            Ok(status) => {
+                let has_filled = matches!(status.as_str(), "FILLED");
+                
+                if has_filled {
+                    info!("限价单已成交,准备执行市价单");
+                    self.state = StrategyState::ExecutingMarketOrder { };
+                    return Ok(());
+                }
             }
             Err(e) => {
                 return Err(e);
@@ -198,18 +200,21 @@ impl Strategy {
         sleep(Duration::from_millis(3000)).await;
 
         // 撤单后检查是否有成交
-        match self.check_order_partially_filled(&order_id, dm).await {
-            Ok(true) => {
-                info!("撤单后发现有成交,准备执行市价单");
-                self.state = StrategyState::ExecutingMarketOrder { };
-                Ok(())
-            }
-            Ok(false) => {
-                info!("撤单完成,无成交,返回空闲状态");
-                self.state = StrategyState::Idle;
+        match self.check_order_filled_status(&order_id, dm).await {
+            Ok(status) => {
+                let has_filled = matches!(status.as_str(), "PARTIALLY_FILLED" | "FILLED");
+
+                if has_filled {
+                    info!("撤单后发现有成交,准备执行市价单");
+                    self.state = StrategyState::ExecutingMarketOrder { };
+                } else {
+                    info!("撤单完成,无成交,返回空闲状态");
+                    self.state = StrategyState::Idle;
+                }
                 Ok(())
             }
             Err(e) => {
+                warn!("检查订单成交状态失败: {}", e);
                 Err(e)
             }
         }
@@ -259,19 +264,29 @@ impl Strategy {
        self.last_query_order_time = Instant::now();
 
        // 等待市价单成交(市价单通常立即成交)
-       match self.check_order_filled(&order_id, dm).await {
-           Ok(true) => {
-               info!("市价单已成交,返回空闲状态");
-
-               self.state = StrategyState::Idle;
-               self.filled_quantity = Decimal::ZERO;
-
-               Ok(())
-           }
-           Ok(false) => {
-               self.state = StrategyState::ExecutingMarketOrder { };
-               
-               Ok(())
+       match self.check_order_filled_status(&order_id, dm).await {
+           Ok(status) => {
+               match status.as_str() {
+                   "PARTIALLY_FILLED" | "FILLED" => {
+                       info!("市价单已成交,返回空闲状态");
+
+                       self.state = StrategyState::Idle;
+                       self.filled_quantity = Decimal::ZERO;
+
+                       Ok(())
+                   }
+                   "CANCELLED" => {
+                       info!("市价单已被取消,重新下单");
+                       
+                       self.state = StrategyState::ExecutingMarketOrder { };
+
+                       Ok(())
+                   }
+                   _ => {
+                       // 这里是其他状态,等待市价单终止
+                       Ok(())
+                   }
+               }
            }
            Err(e) => {
                Err(e)
@@ -293,6 +308,7 @@ impl Strategy {
             "BUY",
             quantity.to_string().as_str(),
             price.to_string().as_str(),
+            true,
             false,
         ).await;
 
@@ -311,6 +327,7 @@ impl Strategy {
             "SELL",
             quantity.to_string().as_str(),
             price.to_string().as_str(),
+            false,
             true,
         ).await;
 
@@ -343,23 +360,19 @@ impl Strategy {
         Ok(())
     }
 
-    /// 检查订单是否完全成交
-    async fn check_order_filled(&mut self, order_id: &str, dm: &DataManager) -> Result<bool> {
-        self.check_order_filled_status(order_id, dm, true).await
-    }
-
-    /// 检查订单是否有部分成交
-    async fn check_order_partially_filled(&mut self, order_id: &str, dm: &DataManager) -> Result<bool> {
-        self.check_order_filled_status(order_id, dm, false).await
-    }
-
     /// 检查订单成交状态
     /// - `require_full_fill`: true 表示只接受完全成交,false 表示部分成交也接受
-    async fn check_order_filled_status(&mut self, order_id: &str, dm: &DataManager, require_full_fill: bool) -> Result<bool> {
-        let check_type = if require_full_fill { "完全成交" } else { "部分成交" };
+    async fn check_order_filled_status(&mut self, order_id: &str, dm: &DataManager) -> Result<String> {
+        let data_option = dm.extended_orders.get(order_id);
 
-        let data = dm.extended_orders.get(order_id)
-            .ok_or_else(|| anyhow!("订单暂时不存在: {}", order_id))?;
+        let data = match data_option {
+            Some(data) => { data },
+            None => {
+                warn!("订单暂时不存在ws缓存中: {}, 使用rest方式获取。", order_id);
+
+                &self.get_order_result(order_id).await?
+            }
+        };
 
         let data_str = serde_json::to_string(&data)
             .unwrap_or_else(|_| "无法序列化 JSON Value".to_string());
@@ -369,28 +382,45 @@ impl Strategy {
             .and_then(|v| v.as_str())
             .ok_or_else(|| anyhow!("查单-获取 'data.status' 失败,原始JSON:{}", data_str))?;
 
-        // 根据要求判断是否符合成交条件
-        let is_filled = if require_full_fill {
-            status == "FILLED"
-        } else {
-            status == "FILLED" || status == "PARTIALLY_FILLED"
-        };
+        // 获取真实成交数量
+        let filled_qty = data.get("filledQty")
+            .and_then(|v| v.as_str())
+            .ok_or_else(|| anyhow!("查单-获取 'data.filledQty' 失败,原始JSON:{}", data_str))
+            .and_then(|v| Decimal::from_str(v)
+                .map_err(|e| anyhow!("查单-解析 'data.filledQty' 为 Decimal 失败: {}, 值: {}", e, v))
+            )?;
+    
+        self.filled_quantity = filled_qty.normalize();
+        if self.filled_quantity > Decimal::ZERO {
+            info!("订单 {} ,成交数量: {}", order_id, self.filled_quantity);
+        }
+        
+        Ok(status.to_string())
+    }
+
+    async fn get_order_result(&self, order_id: &str) -> Result<Value> {
+        let mut client = self.rest_client.lock().await;
+        let response = client.get_order(order_id).await;
+
+        let value = &response.data;
 
-        if is_filled {
-            // 获取真实成交数量
-            let filled_qty = data.get("filledQty")
-                .and_then(|v| v.as_str())
-                .ok_or_else(|| anyhow!("查单-获取 'data.filledQty' 失败,原始JSON:{}", data_str))
-                .and_then(|v| Decimal::from_str(v)
-                    .map_err(|e| anyhow!("查单-解析 'data.filledQty' 为 Decimal 失败: {}, 值: {}", e, v))
-                )?;
-
-            self.filled_quantity = filled_qty.normalize();
-            info!("订单 {} 已{},成交数量: {}", order_id, check_type, filled_qty);
-            Ok(true)
-        } else {
-            Ok(false)
+        // 预先捕获整个 Value 的字符串表示,用于错误报告
+        let value_str = serde_json::to_string(&value)
+            .unwrap_or_else(|_| "无法序列化 JSON Value".to_string());
+
+        // 获取并判定 status
+        let status = value.get("status")
+            .and_then(|v| v.as_str())
+            .ok_or_else(|| anyhow!("查单-获取 'status' 失败,原始JSON:{}", value_str))?;
+
+        if status != "OK" {
+            bail!("查单失败,状态不为OK: {},原始JSON:{}", status, value_str)
         }
+
+        // 获取 data 字段
+        value.get("data")
+            .cloned()
+            .ok_or_else(|| anyhow!("查单-获取 'data' 字段失败,原始 JSON: {}", value_str))
     }
 
     fn match_create_order_result(&self, create_result: &Result<Response>) -> Result<String> {