From d163fc446359d66afa10e2ab63e860887aa8732c Mon Sep 17 00:00:00 2001
From: Administrator <admin@example.com>
Date: 星期二, 19 八月 2025 01:33:11 +0800
Subject: [PATCH] 连续涨停时间记录/新增大单概览接口

---
 cancel_strategy/s_l_h_cancel_strategy.py |  140 ++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 128 insertions(+), 12 deletions(-)

diff --git a/cancel_strategy/s_l_h_cancel_strategy.py b/cancel_strategy/s_l_h_cancel_strategy.py
index 04c21d8..9f28fa1 100644
--- a/cancel_strategy/s_l_h_cancel_strategy.py
+++ b/cancel_strategy/s_l_h_cancel_strategy.py
@@ -4,6 +4,7 @@
 
 import constant
 from code_attribute import gpcode_manager, code_volumn_manager
+from code_attribute.today_max_price_manager import MaxPriceInfoManager
 from db import redis_manager_delegate as redis_manager
 from db.redis_manager_delegate import RedisUtils
 from l2.code_price_manager import Buy1PriceManager
@@ -590,9 +591,7 @@
                     return max(constant.L_CANCEL_RATE_WITH_MUST_BUY_FOR_REDICAL_BUY, human_rate), True, (
                         constant.L_CANCEL_RATE_WITH_MUST_BUY_FOR_REDICAL_BUY, human_rate)
                 else:
-                    # deal_big_order_info = radical_buy_data_manager.get_total_deal_big_order_info(code,
-                    #                                                                              gpcode_manager.get_limit_up_price_as_num(
-                    #                                                                                  code))
+
                     # # 鏍规嵁鎴愪氦棰濈殑澶у崟鎴愪氦鍗犳瘮鏉ヨ绠楁挙鍗曟瘮渚�
                     # big_money_rate = radical_buy_data_manager.TotalDealBigOrderInfoManager.get_big_order_rate(code)
                     # if big_money_rate is not None:
@@ -610,6 +609,18 @@
                     #         # 澶у崟瓒冲锛屽皢鍩虹姣斾緥璋冩暣鑷�79%
                     #         threshold_rate = max(threshold_rate, 0.79)
                     threshold_rate = constant.L_CANCEL_RATE
+                    if constant.CAN_AUTO_L_DOWN_RATE_CHANGE:
+                        # TODO 鏈�闀挎定鍋滄椂闂磋秴杩�1鍒嗛挓
+                        try:
+                            if MaxPriceInfoManager().get_max_limit_up_time(code) > 60:
+                                deal_big_order_info = radical_buy_data_manager.get_total_deal_big_order_info(code,
+                                                                                                             gpcode_manager.get_limit_up_price_as_num(
+                                                                                                                 code))
+                                if deal_big_order_info:
+                                    temp_rate = round(deal_big_order_info[1] / deal_big_order_info[5], 2)
+                                    threshold_rate = min(max(temp_rate, 0.3), 0.9)
+                        except:
+                            pass
                     return human_rate if human_rate > 0 else threshold_rate, False, (threshold_rate, human_rate)
             if must_buy:
                 if is_up:
@@ -956,7 +967,7 @@
         # 閲嶆柊璁$畻L涓�
 
     # big_sell_info鍗栧崟淇℃伅锛屾牸寮忥細[鏈�杩戞垚浜ょ储寮�,鏈�杩戞垚浜ゆ椂闂�(甯︽绉�)]
-    def re_compute_l_down_watch_indexes(self, code, big_sell_info=None, is_force=False):
+    def re_compute_l_down_watch_indexes(self, code, big_sell_info=None, is_force=False, is_human=False):
         watch_index_info = self.__cancel_watch_index_info_cache.get(code)
         if not is_force:
             if not watch_index_info or watch_index_info[1] > 0:
@@ -976,13 +987,13 @@
                                  real_place_order_index_info[0],
                                  re_compute=1, min_cancel_time_with_ms=min_cancel_time_with_ms,
                                  msg=f"澶у崟鍗�: 鎴愪氦杩涘害-{big_sell_info}" if big_sell_info is not None else '',
-                                 is_force=is_force)
+                                 is_force=is_force, is_human=is_human)
 
     # 璁$畻瑙傚療绱㈠紩锛屽�掑簭璁$畻
     # re_compute:鏄惁鏄噸鏂拌绠楃殑
     # min_cancel_time_with_ms:鏈�灏忔挙鍗曟椂闂达紝澶т簬绛変簬姝ゆ椂闂寸殑鎾ゅ崟闇�瑕佸泭鎷繘鍘�
     def compute_watch_index(self, code, buy_single_index, start_index, end_index, re_compute=0,
-                            min_cancel_time_with_ms=None, msg="", is_force=False):
+                            min_cancel_time_with_ms=None, msg="", is_force=False, is_human=False):
         try:
             l2_log.l_cancel_debug(code, f"璁$畻L鍚庡泭鎷寖鍥达細{start_index}-{end_index}")
             total_datas = local_today_datas.get(code)
@@ -1037,7 +1048,11 @@
                 MIN_MONEYS = [300, 200, 100]
                 watch_indexes = set()
                 for min_money in MIN_MONEYS:
-                    for i in range(end_index, re_start_index - 1, -1):
+                    start_index_for_compute = re_start_index - 1
+                    if is_human and min_money >= 300:
+                        # 浜轰负鍥婃嫭浼樺厛鍥婃嫭鎵�鏈夊ぇ鍗�
+                        start_index_for_compute = start_index - 1
+                    for i in range(end_index, start_index_for_compute, -1):
                         try:
                             data = total_datas[i]
                             val = data['val']
@@ -1134,9 +1149,11 @@
                         big_order_list.sort(key=lambda x: x[1], reverse=True)
                         watch_indexes |= set([x[0] for x in big_order_list[:2]])
                     # 鑾峰彇鐪熷疄涓嬪崟浣嶅悗闈�10绗斿ぇ鍗�
-                    watch_indexes_after = self.__compute_l_down_watch_index_after_real_place_order_index(code)
-                    if watch_indexes_after:
-                        watch_indexes |= watch_indexes_after
+                    if not is_human:
+                        # 浜轰负涓嶉渶瑕佽缃�
+                        watch_indexes_after = self.__compute_l_down_watch_index_after_real_place_order_index(code)
+                        if watch_indexes_after:
+                            watch_indexes |= watch_indexes_after
                     self.__set_watch_indexes(code, buy_single_index, re_compute, watch_indexes)
                     l2_log.l_cancel_debug(code,
                                           f"璁剧疆鐩戝惉鑼冨洿({msg}){'(閲嶆柊璁$畻)' if re_compute else ''}锛� 鏁版嵁鑼冨洿锛歿re_start_index}-{end_index} 鐩戝惉鑼冨洿-{watch_indexes}")
@@ -1561,9 +1578,8 @@
         # 璁$畻鐩戝惉鐨勬�绘潯鏁�
         total_num = 0
         # 瓒呭ぇ鍗曠殑鎵嬫暟
-        super_big_num_thresold = int(2e7/gpcode_manager.get_limit_up_price_as_num(code)/100)
+        super_big_num_thresold = int(2e7 / gpcode_manager.get_limit_up_price_as_num(code) / 100)
         max_num, max_num_count = 0, 0
-
 
         thresh_hold_rate, must_buy, cancel_rate_info = LCancelRateManager.get_cancel_rate(code)
         for wi in watch_indexes:
@@ -2045,6 +2061,106 @@
     def cancel_success(self, code):
         self.clear(code)
 
+    def statistic_l_down_watch_indexes_of_big_order_info(self, code):
+        """
+        缁熻L鍚庣殑澶у崟淇℃伅
+        @param code:
+        @return: 鍥婃嫭閲戦鍒楄〃, 鎴愪氦閲戦鍒楄〃, 鎾ゅ崟閲戦鍒楄〃, 寰呮垚浜ゅ垪琛�
+        """
+        watch_indexes_info = self.__get_watch_indexes_cache(code)
+        if not watch_indexes_info:
+            return None
+        trade_index, is_default = TradeBuyQueue().get_traded_index(code)
+        if trade_index is None:
+            trade_index = 0
+        real_place_order_index_info = self.__real_place_order_index_dict.get(code)
+        if not real_place_order_index_info:
+            return None
+
+        total_datas = local_today_datas.get(code)
+        # 缁熻鍥婃嫭锛屽凡鎴愶紝宸叉挙锛屽緟鎴愪氦
+        all_indexes = set()
+        deal_indexes = set()
+        canceled_indexes = set()
+        not_deal_indexes = set()
+        for index in watch_indexes_info[2]:
+            if index > real_place_order_index_info[0]:
+                continue
+            all_indexes.add(index)
+            data = total_datas[index]
+            val = data["val"]
+            left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count_v2(code,
+                                                                                                     index,
+                                                                                                     total_datas,
+                                                                                                     local_today_canceled_buyno_map.get(
+                                                                                                         code))
+            if left_count == 0:
+                canceled_indexes.add(index)
+                continue
+            if index < trade_index:
+                deal_indexes.add(index)
+                continue
+            not_deal_indexes.add(index)
+        all_money_list = [int(float(total_datas[x]['val']['price'] * total_datas[x]['val']['num'] * 100)) for x in
+                          all_indexes]
+        deal_money_list = [int(float(total_datas[x]['val']['price'] * total_datas[x]['val']['num'] * 100)) for x in
+                           deal_indexes]
+        canceled_money_list = [int(float(total_datas[x]['val']['price'] * total_datas[x]['val']['num'] * 100)) for x in
+                               canceled_indexes]
+        not_deal_money_list = [int(float(total_datas[x]['val']['price'] * total_datas[x]['val']['num'] * 100)) for x in
+                               not_deal_indexes]
+        return all_money_list, deal_money_list, canceled_money_list, not_deal_money_list
+
+    def statistic_total_big_order_info(self, code):
+        """
+        缁熻L鍚庣殑澶у崟淇℃伅
+        @param code:
+        @return: 鍥婃嫭閲戦鍒楄〃, 鎴愪氦閲戦鍒楄〃, 鎾ゅ崟閲戦鍒楄〃, 寰呮垚浜ゅ垪琛�
+        """
+        trade_index, is_default = TradeBuyQueue().get_traded_index(code)
+        if trade_index is None:
+            trade_index = 0
+        real_place_order_index_info = self.__real_place_order_index_dict.get(code)
+        if not real_place_order_index_info:
+            return None
+        total_datas = local_today_datas.get(code)
+        # 缁熻鍥婃嫭锛屽凡鎴愶紝宸叉挙锛屽緟鎴愪氦
+        all_indexes = set()
+        deal_indexes = set()
+        canceled_indexes = set()
+        not_deal_indexes = set()
+        big_money_threshold = l2_data_util.get_big_money_val(gpcode_manager.get_limit_up_price_as_num(code), tool.is_ge_code(code))
+        big_num_threshold = int(big_money_threshold/gpcode_manager.get_limit_up_price_as_num(code)/100)
+        for index in range(0,total_datas[-1]):
+            data = total_datas[index]
+            val = data["val"]
+            if val['num']<big_num_threshold:
+                continue
+            if not L2DataUtil.is_limit_up_price_buy(val):
+                continue
+            all_indexes.add(index)
+            left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count_v2(code,
+                                                                                                     index,
+                                                                                                     total_datas,
+                                                                                                     local_today_canceled_buyno_map.get(
+                                                                                                         code))
+            if left_count == 0:
+                canceled_indexes.add(index)
+                continue
+            if index < trade_index:
+                deal_indexes.add(index)
+                continue
+            not_deal_indexes.add(index)
+        all_money_list = [int(float(total_datas[x]['val']['price'] * total_datas[x]['val']['num'] * 100)) for x in
+                          all_indexes]
+        deal_money_list = [int(float(total_datas[x]['val']['price'] * total_datas[x]['val']['num'] * 100)) for x in
+                           deal_indexes]
+        canceled_money_list = [int(float(total_datas[x]['val']['price'] * total_datas[x]['val']['num'] * 100)) for x in
+                               canceled_indexes]
+        not_deal_money_list = [int(float(total_datas[x]['val']['price'] * total_datas[x]['val']['num'] * 100)) for x in
+                               not_deal_indexes]
+        return all_money_list, deal_money_list, canceled_money_list, not_deal_money_list
+
     def statistic_l_down_watch_indexes_info(self, code):
         """
         缁熻L鍚庣洃鍚暟鎹俊鎭�

--
Gitblit v1.8.0