From cb4589db74aac2822f2aeb97eb3c28d2b7d59338 Mon Sep 17 00:00:00 2001
From: Administrator <admin@example.com>
Date: 星期二, 19 八月 2025 18:32:52 +0800
Subject: [PATCH] 最后一笔卖被消耗触发下单信号

---
 l2/l2_data_manager_new.py |  206 ++++++++++++++++++++++++++++-----------------------
 1 files changed, 112 insertions(+), 94 deletions(-)

diff --git a/l2/l2_data_manager_new.py b/l2/l2_data_manager_new.py
index 9db1944..9b20c06 100644
--- a/l2/l2_data_manager_new.py
+++ b/l2/l2_data_manager_new.py
@@ -262,6 +262,7 @@
         """
         if code in cls.__human_radical_buy_mark_info:
             return True
+        return False
 
     @classmethod
     def is_valid(cls, code, data):
@@ -546,29 +547,6 @@
                                     logger_l2_error.exception(e)
                                 finally:
                                     buy_open_limit_up_strategy.BuyOpenLimitupDataManager().remove_place_order_info(code)
-
-                        # 鑾峰彇涓嬪崟浣嶇疆
-
-                        if constant.IS_NEW_VERSION_PLACE_ORDER:
-                            place_order_index, order_info, compute_type = huaxin_delegate_postion_manager.RealDelegateOrderPositionManager.compute_l2_place_order_position(
-                                code, add_datas)
-                        else:
-                            place_order_index, order_info, compute_type = huaxin_delegate_postion_manager.get_l2_place_order_position(
-                                code, float(
-                                    gpcode_manager.get_limit_up_price(code)), add_datas)
-
-                        if place_order_index:
-                            order_begin_pos = cls.__get_order_begin_pos(
-                                code)
-                            cls.set_real_place_order_index(code, place_order_index, order_begin_pos, order_info[1])
-                            try:
-                                cls.__re_compute_threading_pool.submit(
-                                    cls.__recompute_real_order_index, code, place_order_index, order_info,
-                                    compute_type)
-                            except:
-                                pass
-                            async_log_util.info(logger_l2_process, f"code:{code} 鑾峰彇鍒颁笅鍗曠湡瀹炰綅缃細{place_order_index}")
-
                     # 澶勭悊娑ㄥ仠鍗栦笌娑ㄥ仠鍗栨挙
                     try:
                         for d in add_datas:
@@ -579,6 +557,9 @@
                                                                                                 d['val']['orderNo'])
                     except Exception as e:
                         logger_debug.exception(e)
+                    finally:
+                        # 鎵ц鏈�鍚庡啀鑾峰彇鐪熷疄涓嬪崟浣嶇疆锛岄槻姝笅鍗曚綅缃偅鎵规暟鎹湁澶ф壒閲忕殑鎾ゅ崟
+                        pass
                 except:
                     async_log_util.error(logger_l2_error, f"{code} 澶勭悊鐪熷疄涓嬪崟浣嶇疆鍑洪敊")
             # 绗�1鏉℃暟鎹槸鍚︿负09:30:00
@@ -654,6 +635,28 @@
                     # 宸叉寕鍗�
                     place_ordered_desc = "宸蹭笅鍗�"
                     cls.__process_order(code, start_index, end_index, capture_timestamp, is_first_code)
+                    # ======鑾峰彇涓嬪崟浣嶇疆
+                    state = cls.__CodesTradeStateManager.get_trade_state_cache(code)
+                    if trade_util.is_delegated(state):
+                        if constant.IS_NEW_VERSION_PLACE_ORDER:
+                            place_order_index, order_info, compute_type = huaxin_delegate_postion_manager.RealDelegateOrderPositionManager.compute_l2_place_order_position(
+                                code, add_datas)
+                        else:
+                            place_order_index, order_info, compute_type = huaxin_delegate_postion_manager.get_l2_place_order_position(
+                                code, float(
+                                    gpcode_manager.get_limit_up_price(code)), add_datas)
+
+                        if place_order_index:
+                            order_begin_pos = cls.__get_order_begin_pos(
+                                code)
+                            cls.set_real_place_order_index(code, place_order_index, order_begin_pos, order_info[1])
+                            try:
+                                cls.__re_compute_threading_pool.submit(
+                                    cls.__recompute_real_order_index, code, place_order_index, order_info,
+                                    compute_type)
+                            except:
+                                pass
+                            async_log_util.info(logger_l2_process, f"code:{code} 鑾峰彇鍒颁笅鍗曠湡瀹炰綅缃細{place_order_index}")
                 else:
                     place_ordered_desc = "鏈笅鍗�"
                     # 鏈寕鍗�,鏃堕棿鐩稿樊涓嶅ぇ鎵嶈兘鎸傚崟
@@ -791,11 +794,14 @@
                 b_need_cancel, b_cancel_data, extra_msg = RDCancelBigNumComputer().need_cancel(code, start_index,
                                                                                                end_index)
                 if b_need_cancel and b_cancel_data:
+                    l2_log.d_cancel_debug(code, f"鍑嗗RD鎾�({start_index}-{end_index}): {extra_msg}")
                     big_order_info = radical_buy_data_manager.get_total_deal_big_order_info(code,
                                                                                             gpcode_manager.get_limit_up_price_as_num(
                                                                                                 code))
                     if big_order_info[0] > 0:
                         return b_cancel_data, f"RD鎾�({extra_msg})", trade_constant.CANCEL_TYPE_RD
+                    else:
+                        l2_log.d_cancel_debug(code, f"瑙﹀彂RD鎾わ紝浣嗘槸澶у崟宸茬粡瓒冲锛歿big_order_info}")
             except Exception as e:
                 async_log_util.error(logger_l2_error,
                                      f"RD鎾ゅ嚭閿� 鍙傛暟锛歜uy_single_index-{_buy_single_index} buy_exec_index-{_buy_exec_index} 閿欒鍘熷洜锛歿str(e)}")
@@ -815,42 +821,25 @@
         if order_begin_pos.buy_volume_rate is None:
             order_begin_pos.buy_volume_rate = 0.2
         cancel_data, cancel_msg, cancel_type = None, "", None
-        if order_begin_pos.mode == OrderBeginPosInfo.MODE_RADICAL:
 
-            if not cancel_data:
-                cancel_data, cancel_msg, cancel_type = rd_cancel(order_begin_pos.buy_single_index,
-                                                                 order_begin_pos.buy_exec_index)
+        if not cancel_data:
+            cancel_data, cancel_msg, cancel_type = rd_cancel(order_begin_pos.buy_single_index,
+                                                             order_begin_pos.buy_exec_index)
 
-            # 鎵叆涓嬪崟鍙湁L鎾�
-            if not cancel_data:
-                cancel_data, cancel_msg, cancel_type = l_cancel(order_begin_pos.buy_single_index,
-                                                                order_begin_pos.buy_exec_index)
-        else:
-            if not cancel_data:
-                cancel_data, cancel_msg = g_cancel(order_begin_pos.buy_single_index, order_begin_pos.buy_exec_index)
-                cancel_type = trade_constant.CANCEL_TYPE_G
-            # 渚濇澶勭悊
-            if not cancel_data:
-                cancel_data, cancel_msg, cancel_type = l_cancel(order_begin_pos.buy_single_index,
-                                                                order_begin_pos.buy_exec_index)
-            # B鎾�
-            if not cancel_data:
-                cancel_data, cancel_msg = b_cancel(order_begin_pos.buy_single_index, order_begin_pos.buy_exec_index)
-                cancel_type = trade_constant.CANCEL_TYPE_G
-            if not cancel_data:
-                cancel_data, cancel_msg = h_cancel(order_begin_pos.buy_single_index, order_begin_pos.buy_exec_index)
-                cancel_type = trade_constant.CANCEL_TYPE_H
-            # J鎾�
-            if not cancel_data:
-                cancel_data, cancel_msg = j_cancel(order_begin_pos.buy_single_index, order_begin_pos.buy_exec_index)
-                cancel_type = trade_constant.CANCEL_TYPE_J
+        # 鎵叆涓嬪崟鍙湁L鎾�
+        if not cancel_data:
+            cancel_data, cancel_msg, cancel_type = l_cancel(order_begin_pos.buy_single_index,
+                                                            order_begin_pos.buy_exec_index)
 
         if cancel_data and not DCancelBigNumComputer().has_auto_cancel_rules(code):
-            l2_log.debug(code, "瑙﹀彂鎾ゅ崟锛屾挙鍗曚綅缃細{} 锛屾挙鍗曞師鍥狅細{}", cancel_data["index"], cancel_msg)
-            # 鎾ゅ崟
-            cls.cancel_buy(code, cancel_msg, cancel_index=cancel_data["index"], cancel_type=cancel_type)
-            # 鎾ゅ崟鎴愬姛锛岀户缁绠椾笅鍗�
-            cls.__process_not_order(code, cancel_data["index"] + 1, end_index, capture_time, is_first_code)
+            try:
+                # 鎾ゅ崟
+                cls.cancel_buy(code, cancel_msg, cancel_index=cancel_data["index"], cancel_type=cancel_type)
+                # 鎾ゅ崟鎴愬姛锛岀户缁绠椾笅鍗�
+                cls.__process_not_order(code, cancel_data["index"] + 1, end_index, capture_time, is_first_code)
+            finally:
+                l2_log.debug(code, "瑙﹀彂鎾ゅ崟锛屾挙鍗曚綅缃細{} 锛屾挙鍗曞師鍥狅細{}, 涓嬪崟妯″紡锛歿}", cancel_data["index"], cancel_msg,
+                             f"{order_begin_pos.mode}")
         else:
             pass
 
@@ -872,8 +861,16 @@
         now_time_int = int(tool.get_now_time_str().replace(":", ""))
         if now_time_int >= 145700:
             return False, True, f"14:57鍚庝笉鑳戒氦鏄�", True
-        # if now_time_int < 93100:
-        #     return False, True, f"09:31涔嬪墠涓嶈兘浜ゆ槗", True
+        if now_time_int < 93200:
+            return False, True, f"09:32涔嬪墠涓嶈兘浜ゆ槗", True
+        if 125950 < now_time_int < 130100:
+            # 鍒ゆ柇澶у崟鏄惁瓒冲
+            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 5000e4 <= deal_big_order_info[5] < deal_big_order_info[1]:
+                pass
+            else:
+                return False, True, f"13:01涔嬪墠涓嶈兘浜ゆ槗", True
+
         # 浜屾澘浠ヤ笂鐨勭エ涓嶄拱
         yesterday_codes = kpl_data_manager.get_yesterday_limit_up_codes()
         if yesterday_codes and code in yesterday_codes:
@@ -896,6 +893,13 @@
             else:
                 if average_rate < 0.04:
                     return False, True, f"鍧囦环娑ㄥ箙({average_rate})灏忎簬4%", True
+
+        limit_up_price = gpcode_manager.get_limit_up_price_as_num(code)
+        if tool.is_ge_code(code) and limit_up_price < 2:
+            return False, True, f"鍒涗笟鏉胯偂浠�<({limit_up_price})2鍧�", True
+
+        if limit_up_price < 1:
+            return False, True, f"鑲′环<({limit_up_price})1鍧�", True
 
         return True, False, f"", False
 
@@ -1040,7 +1044,6 @@
             else:
 
                 try:
-
                     # 鍒ゆ柇鏄惁涓洪灏佷笅鍗�
                     order_begin_pos.first_limit_up_buy = radical_buy_data_manager.is_first_limit_up_buy(code)
 
@@ -1053,7 +1056,8 @@
                                                                  order_begin_pos.buy_exec_index,
                                                                  local_today_datas.get(code))
                         return False
-                    l2_log.debug(code, "鍙互涓嬪崟锛屽師鍥狅細{}锛� 涓嬪崟妯″紡锛歿}", reason, order_begin_pos.mode)
+                    l2_log.debug(code, "鍙互涓嬪崟锛屽師鍥狅細{}锛� 涓嬪崟妯″紡锛歿} 鏈�灏忚鍗曞彿锛歿}", reason, order_begin_pos.mode,
+                                 order_begin_pos.min_order_no)
                     l2_log.debug(code, "寮�濮嬫墽琛屼拱鍏�")
                     trade_manager.start_buy(code, capture_timestamp, last_data,
                                             last_data_index, order_begin_pos.mode, order_begin_pos.buy_exec_index)
@@ -1394,14 +1398,14 @@
             # 鎵叆涓嬪崟鍙湁L鎾よ兘鎾ゅ崟
             if order_begin_pos and order_begin_pos.mode == OrderBeginPosInfo.MODE_RADICAL and cancel_type not in {
                 trade_constant.CANCEL_TYPE_L_DOWN, trade_constant.CANCEL_TYPE_L, trade_constant.CANCEL_TYPE_RD,
-                trade_constant.CANCEL_TYPE_P}:
+                trade_constant.CANCEL_TYPE_P, trade_constant.CANCEL_TYPE_F}:
                 l2_log.cancel_debug(code, "鎾ゅ崟涓柇锛屽師鍥狅細{}", "鎵叆涓嬪崟涓嶆槸L鎾�")
                 return False
             # 鍔犵豢鍙湁L鎾�/浜烘挙鐢熸晥
             if gpcode_manager.GreenListCodeManager().is_in_cache(code):
                 if cancel_type not in {trade_constant.CANCEL_TYPE_L, trade_constant.CANCEL_TYPE_L_UP,
                                        trade_constant.CANCEL_TYPE_L_DOWN, trade_constant.CANCEL_TYPE_RD,
-                                       trade_constant.CANCEL_TYPE_P}:
+                                       trade_constant.CANCEL_TYPE_P, trade_constant.CANCEL_TYPE_F}:
                     l2_log.cancel_debug(code, "鎾ゅ崟涓柇锛屽師鍥狅細{}", "鍔犵豢涓嶆槸L鎾�")
                     return False
 
@@ -1521,32 +1525,35 @@
         _start_time = tool.get_now_timestamp()
         total_datas = local_today_datas[code]
 
-        if not HumanRadicalBuySingleManager.has_single(code):
-            # ---------璁$畻婵�杩涗拱鍏ョ殑淇″彿---------
-            radical_result = cls.__compute_radical_order_begin_pos(code, compute_start_index, compute_end_index)
-        else:
-            human_radical_result = cls.__compute_human_radical_order_begin_pos(code, compute_start_index,
-                                                                               compute_end_index)
-            l2_log.debug(code, f"澶у崟瓒冲锛屼汉涓轰笅鍗曡绠楃粨鏋�({compute_start_index}-{compute_end_index}):{human_radical_result}")
-            if human_radical_result[0]:
-                radical_result = list(human_radical_result[2])
-                # 鏀瑰彉鎵ц浣嶇疆
-                radical_result[1] = human_radical_result[1]["index"]
-            else:
-                radical_result = None
+        # 涓嶉渶瑕佹牴鎹汉涓轰笅鍗曟潵涓嬪崟
+        # if not HumanRadicalBuySingleManager.has_single(code):
+        #     # ---------璁$畻婵�杩涗拱鍏ョ殑淇″彿---------
+        #     radical_result = cls.__compute_radical_order_begin_pos(code, compute_start_index, compute_end_index)
+        # else:
+        #     human_radical_result = cls.__compute_human_radical_order_begin_pos(code, compute_start_index,
+        #                                                                        compute_end_index)
+        #     l2_log.debug(code, f"澶у崟瓒冲锛屼汉涓轰笅鍗曡绠楃粨鏋�({compute_start_index}-{compute_end_index}):{human_radical_result}")
+        #     if human_radical_result[0]:
+        #         radical_result = list(human_radical_result[2])
+        #         # 鏀瑰彉鎵ц浣嶇疆
+        #         radical_result[1] = human_radical_result[1]["index"]
+        #     else:
+        #         radical_result = None
+
+        radical_result = cls.__compute_radical_order_begin_pos(code, compute_start_index, compute_end_index)
         if radical_result and radical_result[0]:
 
-            if not HumanRadicalBuySingleManager.has_single(code):
-                big_order_deal_enough_result = radical_buy_data_manager.is_big_order_deal_enough(code,
-                                                                                                 code_volumn_manager.CodeVolumeManager().get_volume_rate_refer_in_5days(
-                                                                                                     code), 0)
-                if big_order_deal_enough_result[6] <= 0:
-                    HumanRadicalBuySingleManager.add_single(code, total_datas[-1], radical_result)
-                    async_log_util.info(logger_l2_not_buy_reasons, f"{code}#澶у崟瓒冲锛岄渶瑕佹牴鎹汉涓轰笅鍗�({compute_start_index}-{compute_end_index})锛歿radical_result[1]}")
-                    return
-            # 涓嬪崟鍓嶄竴姝ワ紝绉婚櫎浜轰负涓嬪崟淇″彿
-            is_human_radical_buy = HumanRadicalBuySingleManager.has_single(code)
-            HumanRadicalBuySingleManager.remove_single(code)
+            # if not HumanRadicalBuySingleManager.has_single(code):
+            #     big_order_deal_enough_result = radical_buy_data_manager.is_big_order_deal_enough(code,
+            #                                                                                      code_volumn_manager.CodeVolumeManager().get_volume_rate_refer_in_5days(
+            #                                                                                          code), 0)
+            #     if big_order_deal_enough_result[6] <= 0:
+            #         HumanRadicalBuySingleManager.add_single(code, total_datas[-1], radical_result)
+            #         async_log_util.info(logger_l2_not_buy_reasons, f"{code}#澶у崟瓒冲锛岄渶瑕佹牴鎹汉涓轰笅鍗�({compute_start_index}-{compute_end_index})锛歿radical_result[1]}")
+            #         return
+            # #涓嬪崟鍓嶄竴姝ワ紝绉婚櫎浜轰负涓嬪崟淇″彿
+            # is_human_radical_buy = HumanRadicalBuySingleManager.has_single(code)
+            # HumanRadicalBuySingleManager.remove_single(code)
 
             buy_single_index, buy_exec_index = radical_result[1], radical_result[1]
             buy_volume_rate = cls.volume_rate_info[code][0]
@@ -1565,9 +1572,11 @@
                                                      max_num_set=set(),
                                                      buy_volume_rate=buy_volume_rate,
                                                      mode=OrderBeginPosInfo.MODE_RADICAL,
-                                                     mode_desc=f"澶у崟涓嶈冻鎵叆:{radical_result[2]} 鏄惁璺熶汉涔板叆-{is_human_radical_buy}",
+                                                     mode_desc=f"澶у崟涓嶈冻鎵叆:{radical_result[2]}",
                                                      sell_info=sell_info,
-                                                     threshold_money=threshold_money)
+                                                     threshold_money=threshold_money,
+                                                     min_order_no=radical_result[5]
+                                                     )
             order_begin_pos_info.at_limit_up = cls.__is_at_limit_up_buy(code)
             ordered = cls.__process_with_find_exec_index(code, order_begin_pos_info, compute_end_index,
                                                          block_info=radical_result[3])
@@ -2020,11 +2029,10 @@
         @param code:
         @param start_index:
         @param end_index:
-        @return: (鏄惁鑾峰彇鍒颁俊鍙�, 淇″彿浣嶇疆, 鎵叆鏉垮潡/娑堟伅, 鎵叆鏉垮潡澶у崟娴佸叆淇℃伅, 闇�瑕佺洃鍚殑澶у崟)
+        @return: (鏄惁鑾峰彇鍒颁俊鍙�, 淇″彿浣嶇疆, 鎵叆鏉垮潡/娑堟伅, 鎵叆鏉垮潡澶у崟娴佸叆淇℃伅, 闇�瑕佺洃鍚殑澶у崟, 缁熻涓婃澘澶у崟鎴愪氦鐨勬渶灏忚鍗曞彿)
         """
 
         # 婵�杩涗拱淇″彿鐨勬椂闂�
-
         def __can_order():
             # 鍒ゆ柇鏄惁鏄澘涓婃斁閲�
             # if cls.__is_at_limit_up_buy(code, start_index):
@@ -2050,6 +2058,7 @@
                                                                                              radical_data[5])
             # 缂轰箯鐨勫ぇ鍗曢噾棰�
             current_lack_money = int(big_order_deal_enough_result[5])
+            current_deal_order_ids = big_order_deal_enough_result[7]
             total_lack_money = int(big_order_deal_enough_result[6])
             # 濡傛灉鏈夊ぇ鍗曟垚浜ゅ氨涓嶉渶瑕佺湅澶у崟
             if constant.CAN_RADICAL_BUY_NEED_BIG_ORDER_EVERYTIME:
@@ -2115,8 +2124,9 @@
                 if val["num"] >= bigger_money_num:
                     watch_indexes.add(i)
 
-                if val["num"] >= current_min_num:
+                if val["num"] >= current_min_num and int(val["orderNo"]) not in current_deal_order_ids:
                     current_lack_money -= round(val["price"], 2) * val["num"] * 100
+                    current_deal_order_ids.add(val["orderNo"])
 
                 if val["num"] >= total_min_num:
                     total_lack_money -= round(val["price"], 2) * val["num"] * 100
@@ -2125,8 +2135,13 @@
                     single_index = i
                     break
             if single_index is not None:
-                return True, single_index, f"鏈夊ぇ鍗�,澶у崟鎯呭喌锛歿big_order_deal_enough_result[1]}", watch_indexes
-            return False, None, f"澶у崟涓嶈冻锛歿trade_index}-{end_index}  缂哄皯鐨勫ぇ鍗�-{max(current_lack_money, total_lack_money)}  澶у崟鎯呭喌锛歿big_order_deal_enough_result[1]}", watch_indexes
+                every_time_big_orders = EveryLimitupBigDealOrderManager.list_big_buy_deal_orders(code)
+                if every_time_big_orders:
+                    min_order_no = min(min(every_time_big_orders, key=lambda e: e[0])[0], radical_data[1])
+                else:
+                    min_order_no = radical_data[1]
+                return True, single_index, f"鏈夊ぇ鍗�,澶у崟鎯呭喌锛歿big_order_deal_enough_result[1]}, 鏈壒娆′笂鏉垮ぇ鍗曪細{current_deal_order_ids}", watch_indexes, min_order_no
+            return False, None, f"澶у崟涓嶈冻锛歿trade_index}-{end_index}  缂哄皯鐨勫ぇ鍗�-{max(current_lack_money, total_lack_money)}  澶у崟鎯呭喌锛歿big_order_deal_enough_result[1]}", watch_indexes, None
 
         radical_data = RadicalBuyDealCodesManager.buy_by_l2_delegate_expire_time_dict.get(code)
         record_codes = radical_buy_data_manager.BlockPlaceOrderRecordManager().get_codes()
@@ -2170,7 +2185,7 @@
             # 濡傛灉鏉夸笂鏀鹃噺涓嶅彲涔板叆灏遍渶瑕佸垹闄や俊鍙�
             if not constant.CAN_RADICAL_BUY_AT_LIMIT_UP and code in RadicalBuyDealCodesManager.buy_by_l2_delegate_expire_time_dict:
                 RadicalBuyDealCodesManager.buy_by_l2_delegate_expire_time_dict.pop(code)
-            return True, result[1], radical_data[2], radical_data[4], result[3]
+            return True, result[1], radical_data[2], radical_data[4], result[3], result[4]
         else:
             async_log_util.info(logger_l2_not_buy_reasons, f"{code}#{result[2]}")
         return result
@@ -2216,7 +2231,8 @@
                 return False, None, "瓒呰繃淇″彿鐢熸晥鏃堕棿"
             is_valid = False
             # 鍒ゆ柇璺濈涓婁釜50w涔板崟鐨勬椂闂存槸鍚﹁秴杩囦簡space_time_ms
-            for ii in range(i - 1, -1, -1):
+            buy_exec_index = radical_result[1]
+            for ii in range(i - 1, buy_exec_index, -1):
                 data_child = total_datas[ii]
                 val_child = data_child["val"]
                 if not L2DataUtil.is_limit_up_price_buy(val_child):
@@ -2243,6 +2259,8 @@
         @param end_index:
         @return: 淇″彿淇℃伅锛堜俊鍙蜂綅,鎵ц浣嶏級, 娑堟伅, 鍙拱鍏ョ殑鏉垮潡
         """
+        if True:
+            return None, "姝ゆ潯涓嶇敓鏁�", None
         if not tool.is_sz_code(code):
             return None, "闈炴繁璇佺殑绁�", None
         # 鍒ゆ柇鎶涘帇鏄惁澶т簬5000w

--
Gitblit v1.8.0