From 3bec07f70237ca81990279a6b2f866a2adf70575 Mon Sep 17 00:00:00 2001
From: Administrator <admin@example.com>
Date: 星期三, 27 八月 2025 22:28:42 +0800
Subject: [PATCH] L后撤单修改/L后重新囊括修改

---
 cancel_strategy/s_l_h_cancel_strategy.py |  132 ++++++++++++++++++-------------------------
 1 files changed, 56 insertions(+), 76 deletions(-)

diff --git a/cancel_strategy/s_l_h_cancel_strategy.py b/cancel_strategy/s_l_h_cancel_strategy.py
index 7f39058..38f71ff 100644
--- a/cancel_strategy/s_l_h_cancel_strategy.py
+++ b/cancel_strategy/s_l_h_cancel_strategy.py
@@ -816,6 +816,9 @@
     # 涓婁竴娆$殑L鍚庣殑缁熻淇℃伅
     __last_l_down_watch_index_statistic_info = {}
 
+    # 鎬诲ぇ鍗栧崟鎴愪氦鍒楄〃
+    __total_big_sell_order_list_cache = {}
+
     __instance = None
 
     def __new__(cls, *args, **kwargs):
@@ -871,6 +874,8 @@
         return cls.__redis_manager.getRedis()
 
     def __set_watch_indexes(self, code, buy_single_index, re_compute: int, indexes):
+        if code in self.__total_big_sell_order_list_cache:
+            self.__total_big_sell_order_list_cache.pop(code)
         self.__cancel_watch_index_info_cache[code] = (buy_single_index, re_compute, indexes)
         RedisUtils.delete_async(self.__db, f"l_cancel_watch_index_info-{code}")
         RedisUtils.setex_async(self.__db, f"l_cancel_watch_index_info-{code}", tool.get_expire(),
@@ -954,6 +959,8 @@
 
     def clear(self, code=None):
         if code:
+            if code in self.__total_big_sell_order_list_cache:
+                self.__total_big_sell_order_list_cache.pop(code)
             LDownCancelWatchIndexStatisticManager().remove_statistic_info(code)
             self.del_watch_index(code)
             if code in self.__l_down_after_by_big_order_dict:
@@ -1174,6 +1181,21 @@
                     if big_order_list:
                         big_order_list.sort(key=lambda x: x[1], reverse=True)
                         watch_indexes |= set([x[0] for x in big_order_list[:2]])
+
+                    # 鍒ゆ柇鏈壒娆℃槸鍚︽湁澶у崟锛� 濡傛灉娌″ぇ鍗曞氨涓嶆洿鏂颁簡
+                    if is_human and watch_indexes:
+                        try:
+                            watch_num_list = [total_datas[x]['val']['num'] for x in watch_indexes]
+                            max_num = max(watch_num_list)
+                            if max_num < BIG_ORDER_NUM_THRESHOLD:
+                                l2_log.l_cancel_debug(code, f"浜轰负鏇存柊鐩戝惉L鍚庢棤澶у崟锛屽拷鐣ユ湰娆″泭鎷�:{watch_indexes}")
+                                return
+                            if round(max_num / sum(watch_num_list), 2) > 0.5:
+                                l2_log.l_cancel_debug(code, f"鏈�澶у崟鍗犳瘮瓒呰繃50%锛屽拷鐣ユ湰娆″泭鎷細{watch_indexes}")
+                                return
+                        except Exception as e:
+                            logger_debug.exception(e)
+
                     # 鑾峰彇鐪熷疄涓嬪崟浣嶅悗闈�10绗斿ぇ鍗�
                     if not is_human:
                         # 浜轰负涓嶉渶瑕佽缃�
@@ -1671,7 +1693,7 @@
         rate = round(canceled_num / total_num, 3)
         return rate, canceled_data_indexes, (before_nums_info, before_canceled_nums_info)
 
-    def __compute_need_cancel(self, code, buy_exec_index, start_index, end_index, total_data, is_first_code):
+    def __compute_need_cancel(self, code, buy_exec_index, start_index, end_index, total_data, is_first_code, force_compute=False):
         """
         L鍚庢挙鍗�;
         鎾ゅ崟璁$畻瑙勫垯锛氳绠楁挙鍗曟瘮渚嬫椂锛屽皢鐪熷疄涓嬪崟浣嶇疆涔嬪悗鐨勬暟鎹寜鏉冮噸锛堢涓嬪崟浣嶆渶杩戠殑鏉冮噸瓒婂ぇ锛夊姞鍏ュ垎瀛愶紝涓嶅姞鍏ュ垎姣嶏紙鎬诲泭鎷墜鏁帮級璁$畻
@@ -1744,12 +1766,31 @@
                 if buy_index is not None and buy_index in watch_indexes:
                     need_compute = True
                     break
+        if force_compute:
+            need_compute=True
         if need_compute:
+            # =====璁$畻鏈壒娆″ぇ鍗栧崟鎴愪氦閲�====
+            sell_nos = set()
+            total_sell_nums = 0
+            try:
+                if code in self.__total_big_sell_order_list_cache:
+                    for d in self.__total_big_sell_order_list_cache[code]:
+                        if d[0] in sell_nos:
+                            continue
+                        sell_nos.add(d[0])
+                        total_sell_nums += d[1]
+                # 鑾峰彇姝e湪鎴愪氦鐨勫ぇ鍗栧崟
+                dealing_sell_order_info=HuaXinSellOrderStatisticManager.get_dealing_order_info(code)
+                if dealing_sell_order_info and dealing_sell_order_info[2]>=299e4:
+                    total_sell_nums += dealing_sell_order_info[1]
+                total_sell_nums=total_sell_nums//100
+            except Exception as e:
+                l2_log.l_cancel_debug(code, f"璁$畻鎬诲崠澶у崟鍑洪敊锛歿str(e)}")
 
             # 璁$畻鎾ゅ崟姣斾緥
             watch_indexes_list = list(watch_indexes)
             watch_indexes_list.sort()
-            canceled_num = 0
+            canceled_num = total_sell_nums # 灏嗘垚浜ょ殑澶у崠鍗曡鍏ュ凡鎾ら噾棰�
             # 璁板綍鎾ゅ崟绱㈠紩
             canceled_indexes = []
 
@@ -1807,7 +1848,7 @@
                 # 浜轰负璁剧疆鐨勪笉鑳藉彇鏈�灏�
                 thresh_hold_rate = min(0.49, thresh_hold_rate)
             l2_log.l_cancel_debug(code,
-                                  f"L鍚庤绠楄寖鍥达細{start_index}-{end_index},宸叉挙鍗曟瘮渚嬶細{rate}/{thresh_hold_rate},  涓嬪崟浣嶄箣鍚庣殑绱㈠紩锛歿after_place_order_index_dict}, 鏈�澶у崟-({max_num}锛寋max_num_count}), 浜轰负璁剧疆-{cancel_rate_info}, 鐪熷疄涓嬪崟浣�-{real_place_order_info}")
+                                  f"L鍚庤绠楄寖鍥达細{start_index}-{end_index},宸叉挙鍗曟瘮渚嬶細{rate}/{thresh_hold_rate},  涓嬪崟浣嶄箣鍚庣殑绱㈠紩锛歿after_place_order_index_dict}, 鏈�澶у崟-({max_num}锛寋max_num_count}), 浜轰负璁剧疆-{cancel_rate_info}, 鐪熷疄涓嬪崟浣�-{real_place_order_info}, 澶у崠鍗曟垚浜わ細{total_sell_nums}鎵�")
             if rate >= thresh_hold_rate:
                 canceled_indexes.sort()
                 l2_log.l_cancel_debug(code, f"L鍚庢挙鍗�,鎾ゅ崟浣嶇疆锛歿canceled_indexes[-1]}")
@@ -1915,84 +1956,23 @@
     # L鍚庨噸鏂板泭鎷殑鏃堕棿
     __recompute_l_down_time_dict = {}
 
-    def set_big_sell_order_info(self, code, big_sell_order_info):
+    def add_big_sell_order_deal_list(self, code, deal_order_list):
         """
-        璁剧疆澶у崠鍗曚俊鎭�
+        娣诲姞澶у崟鍗栨垚浜ゅ垪琛�
         @param code:
-        @param big_sell_order_info:
-        @return:
+        @param deal_order_list:[(鍗栧崟鍙�,鑲℃暟,鎴愪氦棰�)]
+        @return: 鏄惁鍙挙鍗�, 鎾ゅ崟鏁版嵁
         """
-        if not big_sell_order_info or not big_sell_order_info[0] or not big_sell_order_info[1]:
-            return False, ""
+        if not deal_order_list:
+            return False
+        # 娣诲姞鎴愪氦閲�
+        if code not in self.__total_big_sell_order_list_cache:
+            self.__total_big_sell_order_list_cache[code] = []
+        self.__total_big_sell_order_list_cache[code].extend(deal_order_list)
 
+        # 璁$畻鏄惁鍙挙鍗�
         total_datas = local_today_datas.get(code)
-        # 鏌ヨ鏄惁鏄湡鐨勭湡瀹炰笅鍗曚綅缃�
-        trade_index, is_default = TradeBuyQueue().get_traded_index(code)
-        if trade_index is None:
-            trade_index = 0
-        real_order_index_info = self.get_real_place_order_index_info(code)
-        if real_order_index_info is None or real_order_index_info[1]:
-            return False, "娌℃壘鍒扮湡瀹炰笅鍗曚綅"
-        real_order_index = real_order_index_info[0]
-        total_deal_money = sum([x[1] * x[2] for x in big_sell_order_info[1]])
-        start_order_no = big_sell_order_info[1][0][3][1]
-        # 闃叉鍒嗘瘝浣�0
-        total_num = 1
-        # 鑾峰彇姝e湪鎴愪氦鐨勬暟鎹�
-        dealing_info = HuaXinBuyOrderManager.get_dealing_order_info(code)
-        for i in range(trade_index, real_order_index):
-            data = total_datas[i]
-            val = data['val']
-            if not L2DataUtil.is_limit_up_price_buy(val):
-                continue
-            if int(val['orderNo']) < start_order_no:
-                continue
-            if i == trade_index and dealing_info and str(total_datas[trade_index]["val"]["orderNo"]) == str(
-                    dealing_info[0]):
-                # 鍑忓幓褰撳墠姝e湪鎴愪氦鐨勬暟鎹腑宸茬粡鎴愪氦浜嗙殑鏁版嵁
-                total_num -= dealing_info[1] // 100
-            left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count_v2(code, i,
-                                                                                                     total_datas,
-                                                                                                     local_today_canceled_buyno_map.get(
-                                                                                                         code))
-            if left_count > 0:
-                total_num += val["num"]
-
-        # 鍗栭噾棰�>=鍧囧ぇ鍗曟墠瑙﹀彂閲嶆柊鍥婃嫭
-        THRESHOLD_MONEY = radical_buy_data_manager.BeforeSubDealBigOrderManager().get_big_sell_order_threshold(code)
-        if total_deal_money >= THRESHOLD_MONEY:
-            l2_log.l_cancel_debug(code, "鍑嗗鏇存柊L鍚庡泭鎷�(澶у崠鍗�)")
-            start_order_no = big_sell_order_info[1][-1][4][1]
-            latest_deal_time_ms = l2_huaxin_util.convert_time(big_sell_order_info[1][-1][4][0], with_ms=True)
-            real_trade_index = None
-            for i in range(trade_index, real_order_index):
-                data = total_datas[i]
-                val = data['val']
-                if not L2DataUtil.is_limit_up_price_buy(val):
-                    continue
-                if int(val['orderNo']) < start_order_no:
-                    continue
-                real_trade_index = i
-                break
-            if real_trade_index is None:
-                l2_log.l_cancel_debug(code, f"娌℃壘鍒扮湡瀹炵殑鎴愪氦杩涘害(澶у崠鍗�)锛歴tart_order_no-{start_order_no} 鍗栧崟-{big_sell_order_info}")
-                return False, ""
-            # 闂撮殧1S浠ヤ笂鎵嶈兘閲嶆柊鍥婃嫭
-            if code in self.__recompute_l_down_time_dict and tool.trade_time_sub_with_ms(latest_deal_time_ms,
-                                                                                         self.__recompute_l_down_time_dict[
-                                                                                             code]) < 1000:
-                l2_log.s_cancel_debug(code,
-                                      f"鏇存柊L鍚庡泭鎷�(澶у崠鍗�)锛氭洿鏂伴棿闅斿湪1s鍐咃紝{latest_deal_time_ms}-{self.__recompute_l_down_time_dict[code]}")
-                return False, ""
-            self.__recompute_l_down_time_dict[code] = latest_deal_time_ms
-            # 閲嶆柊鍥婃嫭L鍚�
-            # 鎾ゅ崟鏃堕棿姣旀棭鎴愪氦鏃堕棿澶у氨闇�瑕佽绠楀湪閲岄潰
-            self.re_compute_l_down_watch_indexes(code, big_sell_info=(
-                real_trade_index, latest_deal_time_ms))
-            l2_log.l_cancel_debug(code, f"鏇存柊L鍚庡泭鎷畬鎴�(澶у崠鍗�)锛歿(real_trade_index, latest_deal_time_ms)}")
-        else:
-            l2_log.l_cancel_debug(code, f"澶у崠鍗曢噾棰濅笉瓒�({THRESHOLD_MONEY})")
-        return False, ""
+        return self.__compute_need_cancel(code, 0, total_datas[-1]["index"], total_datas[-1]["index"], total_datas, True, force_compute=True)
 
     # L鍚庢槸鍚﹁繕鏈夊彲鑳芥挙鍗�
     def __is_l_down_can_cancel(self, code, buy_exec_index):

--
Gitblit v1.8.0