Administrator
1 天以前 3a87b1c89a76d858e8e7e4e54ff360dc0b8670f5
L撤删除L前撤单与L后后半段撤单
1个文件已修改
620 ■■■■■ 已修改文件
cancel_strategy/s_l_h_cancel_strategy.py 620 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cancel_strategy/s_l_h_cancel_strategy.py
@@ -618,7 +618,7 @@
                                # if deal_big_order_info and deal_big_order_info[5] > 5000e4:
                                #     temp_rate = round(deal_big_order_info[1] / deal_big_order_info[5], 2)
                                #     threshold_rate = min(max(temp_rate, 0.3), 0.7)
                                volume_rate = code_volumn_manager.CodeVolumeManager().get_volume_rate(code)*0.9
                                volume_rate = code_volumn_manager.CodeVolumeManager().get_volume_rate(code) * 0.9
                                threshold_rate = min(max(volume_rate, 0.3), 0.6)
                        except:
                            pass
@@ -821,6 +821,9 @@
    # 总大卖单成交列表
    __total_big_sell_order_list_cache = {}
    # L后重新囊括的时间
    __recompute_l_down_time_dict = {}
    __instance = None
    def __new__(cls, *args, **kwargs):
@@ -921,39 +924,6 @@
        @return:
        """
        self.__set_watch_indexes(code, buy_single_index, re_compute, indexes)
    def __set_near_by_trade_progress_indexes(self, code, buy_single_index, indexes):
        if indexes:
            trade_record_log_util.add_cancel_watch_indexes_log(code,
                                                               trade_record_log_util.CancelWatchIndexesInfo(
                                                                   trade_record_log_util.CancelWatchIndexesInfo.CANCEL_TYPE_L_UP,
                                                                   buy_single_index,
                                                                   list(indexes)))
        self.__near_by_trade_progress_index_cache[code] = indexes
        RedisUtils.setex_async(self.__db, f"l_cancel_near_by_index-{code}", tool.get_expire(),
                               json.dumps(list(indexes)))
    def __get_near_by_trade_progress_indexes(self, code):
        val = RedisUtils.get(self.__get_redis(), f"l_cancel_near_by_index-{code}")
        if val is None:
            return None
        return set(json.loads(val))
    def __get_near_by_trade_progress_indexes_cache(self, code):
        cache_result = CodeDataCacheUtil.get_cache(self.__near_by_trade_progress_index_cache, code)
        if cache_result[0]:
            return cache_result[1]
        return None
    def __set_cancel_l_down_after_place_order_index(self, code, watch_index, index):
        if code not in self.__cancel_l_down_after_place_order_index_cache:
            self.__cancel_l_down_after_place_order_index_cache[code] = {}
        self.__cancel_l_down_after_place_order_index_cache[code][str(watch_index)] = index
        RedisUtils.setex_async(self.__db, f"l_cancel_down_after_place_order_index-{code}", tool.get_expire(),
                               json.dumps(self.__cancel_l_down_after_place_order_index_cache[code]))
    def __get_cancel_l_down_after_place_order_index_dict(self, code):
        return self.__cancel_l_down_after_place_order_index_cache.get(code)
    def del_watch_index(self, code):
        CodeDataCacheUtil.clear_cache(self.__cancel_watch_index_info_cache, code)
@@ -1197,173 +1167,17 @@
                            logger_debug.exception(e)
                    # 获取真实下单位后面10笔大单
                    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
                    # 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}")
        except Exception as e:
            l2_log.l_cancel_debug(code, f"计算L后囊括范围出错:{str(e)}")
            async_log_util.exception(logger_l2_l_cancel, e)
    def __need_update_l_down_after(self, code, start_index, end_index):
        """
        是否需要更新l后真实下单位置之后的囊括范围
        @param code:
        @return:
        """
        real_place_order_info = self.__real_place_order_index_dict.get(code)
        if not real_place_order_info or real_place_order_info[1]:
            return False
        # 判断L后是否包含后面的数据
        watch_indexes_info = self.__get_watch_indexes_cache(code)
        if not watch_indexes_info:
            # 没有囊括
            return False
        watch_indexes = set([int(i) for i in watch_indexes_info[2]])
        real_place_order_index = real_place_order_info[0]
        for index in watch_indexes:
            if index > real_place_order_index:
                # L后后段已经囊括
                return False
        # 下单位置之后数10笔买单
        watch_indexes = set()
        total_datas = local_today_datas.get(code)
        MIN_NUM = int(5000 / gpcode_manager.get_limit_up_price_as_num(code))
        MAX_COUNT = 10
        for i in range(real_place_order_index + 1, end_index):
            data = total_datas[i]
            val = data['val']
            if not L2DataUtil.is_limit_up_price_buy(val):
                continue
            if val['num'] < MIN_NUM:
                continue
            watch_indexes.add(i)
            if len(watch_indexes) >= MAX_COUNT:
                break
        # 看里面的撤单率是否
        if len(watch_indexes) < MAX_COUNT:
            # 数量不够
            return False
        # 计算撤单比例是否足够
        canceled_buyno_map = local_today_canceled_buyno_map.get(code)
        cancel_count = 0
        for index in watch_indexes:
            # 是否撤单
            left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count_v2(
                code, index,
                total_datas,
                canceled_buyno_map)
            if left_count <= 0:
                cancel_count += 1
        if cancel_count > len(watch_indexes) * 0.5:
            return True
        return False
    def __compute_l_down_watch_index_after_real_place_order_index(self, code):
        """
        计算L后真实下单位置之后的监控索引
        @return:
        """
        watch_indexes = set()
        total_datas = local_today_datas.get(code)
        is_ge_code = tool.is_ge_code(code)
        try:
            # 真实下单位置后面的数据就只看大单
            MIN_NUM = int(5000 / gpcode_manager.get_limit_up_price_as_num(code))
            real_place_order_info = self.__real_place_order_index_dict.get(code)
            if real_place_order_info and not real_place_order_info[1]:
                # 从真实下单位往后找
                after_count = 0
                for i in range(real_place_order_info[0] + 1, total_datas[-1]['index'] + 1):
                    if after_count > 10:
                        break
                    data = total_datas[i]
                    val = data['val']
                    # 涨停买,且未撤单
                    if not L2DataUtil.is_limit_up_price_buy(val):
                        continue
                    # 小金额过滤
                    if val['num'] < MIN_NUM:
                        continue
                    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:
                        after_count += 1
                        if l2_data_util.is_big_money(val, is_ge_code):
                            watch_indexes.add(i)
                            # 记录索引的位置
                            self.__set_cancel_l_down_after_place_order_index(code, i, after_count - 1)
        except Exception as e:
            pass
        return watch_indexes
    def __compute_l_down_watch_index_after_by(self, code):
        """
        计算L后后半段大单备用
        @param code:
        @return:
        """
        if self.__l_down_after_by_big_order_dict.get(code):
            # 不用重复计算
            return
        real_place_order_info = self.__real_place_order_index_dict.get(code)
        if not real_place_order_info or real_place_order_info[1]:
            return
        real_place_order_index = real_place_order_info[0]
        total_datas = local_today_datas.get(code)
        limit_up_price = gpcode_manager.get_limit_up_price(code)
        limit_up_price = round(float(limit_up_price), 2)
        bigger_num = l2_data_util.get_big_money_val(limit_up_price, tool.is_ge_code(code)) // (limit_up_price * 100)
        min_num = 500000 // (limit_up_price * 100)
        index = -1
        watch_indexes = set()
        if code not in self.__l_down_after_by_big_order_weight_dict:
            self.__l_down_after_by_big_order_weight_dict[code] = {}
        for i in range(real_place_order_index + 1, total_datas[-1]["index"]):
            data = total_datas[i]
            val = data["val"]
            if not L2DataUtil.is_limit_up_price_buy(val):
                continue
            if val["num"] < min_num:
                continue
            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:
                if val["num"] >= bigger_num:
                    if index < 0:
                        # 开始计数
                        index = 0
                    # 加入大单监听
                    self.__l_down_after_by_big_order_weight_dict[code][str(i)] = int(str(index))
                    watch_indexes.add(i)
                if index >= 0:
                    index += 1
                    if index > 10:
                        break
        self.__l_down_after_by_big_order_dict[code] = watch_indexes
        l2_log.l_cancel_debug(code, f"L后后半段大单备用囊括范围:{watch_indexes}")
        try:
            watch_indexes_info = self.get_l_down_watch_indexes_cache(code)
            if watch_indexes_info:
                total_watch_indexes = set(watch_indexes) | set(watch_indexes_info[2])
                trade_record_log_util.add_cancel_watch_indexes_log(code,
                                                                   trade_record_log_util.CancelWatchIndexesInfo(
                                                                       trade_record_log_util.CancelWatchIndexesInfo.CANCEL_TYPE_L_DOWN,
                                                                       watch_indexes_info[0],
                                                                       list(total_watch_indexes)))
        except:
            pass
    # 设置真实下单位置
    def set_real_place_order_index(self, code, index, buy_single_index=None, is_default=False):
@@ -1395,53 +1209,11 @@
    # 计算范围内的成交位临近未撤大单
    def __compute_trade_progress_near_by_indexes(self, code, buy_single_index, start_index, end_index):
        if start_index is None or end_index is None:
            return
        total_datas = local_today_datas.get(code)
        MIN_MONEY = 99 * 100
        MAX_COUNT = 15
        watch_indexes = set()
        total_num = 0
        # thresh_hold_money = l2_trade_factor.L2PlaceOrderParamsManager.get_base_m_val(code)
        # threshold_num = thresh_hold_money // (float(gpcode_manager.get_limit_up_price(code)) * 100)
        for i in range(start_index, end_index):
            data = total_datas[i]
            val = data['val']
            if not L2DataUtil.is_limit_up_price_buy(val):
                continue
            # 小金额过滤
            if float(val['price']) * val['num'] < MIN_MONEY:
                continue
            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'] * left_count
                watch_indexes.add(i)
                if len(watch_indexes) >= MAX_COUNT:
                    break
        changed = True
        l_up_compute_info = self.__last_l_up_compute_info.get(code)
        if l_up_compute_info:
            if l_up_compute_info[1] == watch_indexes:
                changed = False
        # 保存数据
        if changed:
            threshold_time = 1 if tool.is_sz_code(code) else 2
            if l_up_compute_info and l_up_compute_info[1]:
                if time.time() - l_up_compute_info[0] < threshold_time:
                    l2_log.l_cancel_debug(code, f"L前监控更新太频繁:{threshold_time}")
                    return
            l2_log.l_cancel_debug(code, f"L前监控范围:{watch_indexes} 计算范围:{start_index}-{end_index}")
            self.__set_near_by_trade_progress_indexes(code, buy_single_index, watch_indexes)
        self.__last_l_up_compute_info[code] = (time.time(), watch_indexes)
        pass
    # 计算L后还没成交的手数
    def __compute_total_l_down_not_deal_num(self, code):
        # 只有真实获取到下单位置后才开始计算
        try:
            if code in self.__total_l_down_not_deal_num_dict and time.time() - \
                    self.__total_l_down_not_deal_num_dict[code][
@@ -1498,17 +1270,6 @@
        if total_datas is None:
            return
        if not self.__is_l_down_can_cancel(code, buy_single_index):
            # L后已经不能守护
            l2_log.l_cancel_debug(code, f"L后已经无法生效:buy_single_index-{buy_single_index}")
            HourCancelBigNumComputer().start_compute_watch_indexes(code, buy_single_index)
            try:
                # 计算L后后半段大单监控范围
                self.__compute_l_down_watch_index_after_by(code)
            except Exception as e:
                l2_log.l_cancel_debug(code, "__compute_l_down_watch_index_after_by出错")
        real_place_order_index_info = self.__real_place_order_index_dict.get(code)
        real_place_order_index = None
        if real_place_order_index_info:
@@ -1536,7 +1297,6 @@
            return
        # 重新囊括1笔
        real_place_order_info = self.__real_place_order_index_dict.get(code)
        is_ge_code = tool.is_ge_code(code)
        if real_place_order_info and real_place_order_info[0] > index:
            total_datas = local_today_datas.get(code)
            min_num = int(5000 / gpcode_manager.get_limit_up_price_as_num(code))
@@ -1559,33 +1319,6 @@
                    watch_indexes.add(data["index"])
                    l2_log.l_cancel_debug(code, f"L后有成交重新囊括:成交索引-{index} 囊括索引-{data['index']}")
                    break
            # 从真实下单位置往后囊括大单
            try:
                left_count_after = 0
                for j in range(real_place_order_info[0] + 1, total_datas[-1]["index"]):
                    data = total_datas[j]
                    val = data['val']
                    if left_count_after > 10:
                        break
                    if not L2DataUtil.is_limit_up_price_buy(val):
                        continue
                    if val["num"] < min_num:
                        continue
                    left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count_v2(code,
                                                                                                             j,
                                                                                                             total_datas,
                                                                                                             local_today_canceled_buyno_map.get(
                                                                                                                 code))
                    if left_count > 0:
                        left_count_after += 1
                        if l2_data_util.is_big_money(val, is_ge_code) and j not in watch_indexes:
                            watch_indexes.add(j)
                            l2_log.l_cancel_debug(code, f"L后有成交后半段增加囊括:{j}")
                            self.__set_cancel_l_down_after_place_order_index(code, j, left_count_after - 1)
                            break
            except:
                pass
        self.__set_watch_indexes(code, watch_indexes_info[0], watch_indexes_info[1], watch_indexes)
    def __compute_l_down_canceled_rate(self, code, total_data):
@@ -1598,31 +1331,7 @@
        if not watch_indexes_info:
            return 0, []
        # 这是下单位置之后的索引: key为字符串
        after_place_order_index_dict = self.__get_cancel_l_down_after_place_order_index_dict(code)
        if after_place_order_index_dict is None:
            after_place_order_index_dict = {}
        after_place_order_index_by_dict = self.__l_down_after_by_big_order_weight_dict.get(code)
        if after_place_order_index_by_dict is None:
            after_place_order_index_by_dict = {}
        watch_indexes = set([int(i) for i in watch_indexes_info[2]])
        try:
            # 将备用订单加进去
            watch_indexes_by = self.__l_down_after_by_big_order_dict.get(code)
            if watch_indexes_by:
                # 是否是下单30分钟内
                real_place_order_info = self.__real_place_order_index_dict.get(code)
                if real_place_order_info and tool.trade_time_sub(total_data[-1]["val"]["time"],
                                                                 total_data[real_place_order_info[0]]["val"][
                                                                     "time"]) < 30 * 60:
                    # 下单30分钟内有效
                    watch_indexes |= watch_indexes_by
                else:
                    # 清除备用大单
                    watch_indexes_by.clear()
        except Exception as e:
            l2_log.l_cancel_debug(code, "将L2后后半段备用大单加入计算出错:{}", str(e))
        # 计算监听的总条数
        total_num = 0
        # 超大单的手数
@@ -1631,17 +1340,6 @@
        thresh_hold_rate, must_buy, cancel_rate_info = LCancelRateManager.get_cancel_rate(code)
        for wi in watch_indexes:
            if str(wi) in after_place_order_index_dict:
                # 如果加红就需要计算分母
                if must_buy:
                    total_num += total_data[wi]["val"]["num"] * (
                            10 - after_place_order_index_dict[str(wi)]) // 10
                continue
            elif str(wi) in after_place_order_index_by_dict:
                if must_buy:
                    total_num += total_data[wi]["val"]["num"] * (
                            10 - after_place_order_index_by_dict[str(wi)]) // 10
                continue
            # 超过超大单就算超大单
            if total_data[wi]["val"]["num"] < super_big_num_thresold:
                total_num += total_data[wi]["val"]["num"]
@@ -1676,20 +1374,11 @@
            cancel_data = L2DataComputeUtil.is_canceled(code, wi, total_data, canceled_buyno_map,
                                                        dealing_info[0] if dealing_info else None,
                                                        deal_order_nos)
            if str(wi) in after_place_order_index_dict:
                # 真实下单位置之后的按照权重比例来计算
                if cancel_data:
                    canceled_num += total_data[wi]["val"]["num"] * (
                            10 - after_place_order_index_dict[str(wi)]) // 10
            elif str(wi) in after_place_order_index_by_dict:
                if cancel_data:
                    canceled_num += total_data[wi]["val"]["num"] * (
                            10 - after_place_order_index_by_dict[str(wi)]) // 10
            else:
                before_nums_info.append((wi, val["num"]))
                if cancel_data:
                    before_canceled_nums_info.append((wi, val['num']))
                    canceled_num += total_data[wi]["val"]["num"]
            before_nums_info.append((wi, val["num"]))
            if cancel_data:
                before_canceled_nums_info.append((wi, val['num']))
                canceled_num += total_data[wi]["val"]["num"]
            if cancel_data:
                canceled_data_indexes.append(cancel_data["index"])
        rate = round(canceled_num / total_num, 3)
@@ -1712,41 +1401,13 @@
        if not watch_indexes_info:
            return False, None
        # 这是下单位置之后的索引: key为字符串
        after_place_order_index_dict = self.__get_cancel_l_down_after_place_order_index_dict(code)
        if after_place_order_index_dict is None:
            after_place_order_index_dict = {}
        after_place_order_index_by_dict = self.__l_down_after_by_big_order_weight_dict.get(code)
        if after_place_order_index_by_dict is None:
            after_place_order_index_by_dict = {}
        watch_indexes = set([int(i) for i in watch_indexes_info[2]])
        try:
            # 将备用订单加进去
            watch_indexes_by = self.__l_down_after_by_big_order_dict.get(code)
            if watch_indexes_by:
                # 是否是下单30分钟内
                real_place_order_info = self.__real_place_order_index_dict.get(code)
                if real_place_order_info and tool.trade_time_sub(total_data[-1]["val"]["time"],
                                                                 total_data[real_place_order_info[0]]["val"][
                                                                     "time"]) < 30 * 60:
                    # 下单30分钟内有效
                    watch_indexes |= watch_indexes_by
                else:
                    # 清除备用大单
                    watch_indexes_by.clear()
        except Exception as e:
            l2_log.l_cancel_debug(code, "将L2后后半段备用大单加入计算出错:{}", str(e))
        # 计算监听的总条数
        total_num = 0
        max_num, max_num_count = 0, 0
        thresh_hold_rate, must_buy, cancel_rate_info = LCancelRateManager.get_cancel_rate(code)
        super_big_num_thresold = int(2e7 / gpcode_manager.get_limit_up_price_as_num(code) / 100)
        for wi in watch_indexes:
            if str(wi) in after_place_order_index_dict:
                continue
            elif str(wi) in after_place_order_index_by_dict:
                continue
            if total_data[wi]["val"]["num"] < super_big_num_thresold:
                total_num += total_data[wi]["val"]["num"]
            else:
@@ -1805,9 +1466,6 @@
                trade_index = None
            canceled_buyno_map = local_today_canceled_buyno_map.get(code)
            # 如果撤单比例设置为100%就不需要计算下单位后面的订单
            need_compute_after = False if thresh_hold_rate - 1.00 >= -0.0001 else True
            dealing_info = HuaXinBuyOrderManager.get_dealing_order_info(code)
            canceled_watch_indexes = set()
            for wi in watch_indexes:
@@ -1815,47 +1473,19 @@
                                                            dealing_info[0] if dealing_info else None,
                                                            deal_order_nos)
                if cancel_data:
                    if str(wi) in after_place_order_index_dict:
                        if not need_compute_after:
                            continue
                        # 真实下单位置之后的按照权重比例来计算
                        canceled_num += total_data[wi]["val"]["num"] * (
                                10 - after_place_order_index_dict[str(wi)]) // 10
                    elif str(wi) in after_place_order_index_by_dict:
                        if not need_compute_after:
                            continue
                        canceled_num += total_data[wi]["val"]["num"] * (
                                10 - after_place_order_index_by_dict[str(wi)]) // 10
                    else:
                        canceled_num += total_data[wi]["val"]["num"]
                    canceled_num += total_data[wi]["val"]["num"]
                    canceled_watch_indexes.add(wi)
                    canceled_indexes.append(cancel_data["index"])
                # if wi == watch_indexes_list[-1] and left_count == 0:
                #     # 离下单位置最近的一个撤单,必须触发撤单
                #     l2_log.l_cancel_debug(code, f"计算范围:{start_index}-{end_index},临近撤单:{wi}")
                #     return True, total_data[-1]
            rate = round(canceled_num / total_num, 3)
            if rate > 1:
                rate = 1
            # 除开最大单的影响权重
            # if not must_buy:
            #     temp_thresh_hold_rate = round((total_num - max_num * max_num_count) * 0.8 / total_num, 2)
            #     if thresh_hold_rate > temp_thresh_hold_rate:
            #         if cancel_rate_info and cancel_rate_info[1] > 0:
            #             pass
            #         else:
            #             # 没有人为设置
            #             # 目标撤单比例大于大单撤单比例就取比例均值
            #             thresh_hold_rate = round((thresh_hold_rate + temp_thresh_hold_rate) / 2, 2)
            real_place_order_info = self.__real_place_order_index_dict.get(code)
            is_default_place_order_index = real_place_order_info[1] if real_place_order_info else False
            if is_default_place_order_index and not cancel_rate_info[1]:
                # 人为设置的不能取最小
                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}, 大卖单成交:{total_sell_nums}手")
                                  f"L后计算范围:{start_index}-{end_index},已撤单比例:{rate}/{thresh_hold_rate}, 最大单-({max_num},{max_num_count}), 人为设置-{cancel_rate_info}, 真实下单位-{real_place_order_info}, 大卖单成交:{total_sell_nums}手")
            l2_log.l_cancel_debug(code, f"L后已撤手数:{canceled_num}/{total_num} 撤单索引:{canceled_watch_indexes}")
            if rate >= thresh_hold_rate:
                canceled_indexes.sort()
@@ -1863,106 +1493,6 @@
                return True, total_data[canceled_indexes[-1]]
        return False, None
    def __compute_near_by_trade_progress_need_cancel(self, code, buy_exec_index, start_index, end_index, total_data,
                                                     is_first_code):
        # L前守护时间为3分钟
        if tool.trade_time_sub(total_data[-1]['val']['time'],
                               total_data[buy_exec_index]['val']['time']) > constant.L_CANCEL_UP_EXPIRE_TIME:
            return False, None
        watch_indexes = self.__get_near_by_trade_progress_indexes_cache(code)
        if not watch_indexes:
            return False, None
        # 监听范围小于5笔不生效
        if len(watch_indexes) < 5:
            return False, None
        # 计算监听的总条数
        # 权重
        WATCH_INDEX_WEIGHTS = [3, 2, 1]
        total_count_weight = 0
        for wi in range(0, len(watch_indexes)):
            if wi < len(WATCH_INDEX_WEIGHTS):
                total_count_weight += WATCH_INDEX_WEIGHTS[wi]
            else:
                total_count_weight += WATCH_INDEX_WEIGHTS[-1]
        # 判断撤单中是否有监听中的索引
        need_compute = False
        for i in range(start_index, end_index + 1):
            data = total_data[i]
            val = data["val"]
            if L2DataUtil.is_limit_up_price_buy_cancel(val):
                # 查询买入位置
                buy_index = l2_data_source_util.L2DataSourceUtils.get_buy_index_with_cancel_data_v2(data,
                                                                                                    local_today_buyno_map.get(
                                                                                                        code))
                if buy_index is not None and buy_index in watch_indexes:
                    need_compute = True
                    break
        if need_compute:
            watch_indexes_list = list(watch_indexes)
            watch_indexes_list.sort()
            # 计算撤单比例
            canceled_count_weight = 0
            canceled_indexes = []
            for wi in watch_indexes:
                canceled_data = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_canceled_data_v2(code,
                                                                                                        wi,
                                                                                                        total_data,
                                                                                                        local_today_canceled_buyno_map.get(
                                                                                                            code))
                if canceled_data:
                    canceled_indexes.append(canceled_data["index"])
                    # 获取索引权重
                    pos_index = watch_indexes_list.index(wi)
                    if pos_index < len(WATCH_INDEX_WEIGHTS):
                        canceled_count_weight += WATCH_INDEX_WEIGHTS[pos_index]
                    else:
                        canceled_count_weight += WATCH_INDEX_WEIGHTS[-1]
            rate = round(canceled_count_weight / total_count_weight, 3)
            thresh_cancel_rate, must_buy, cancel_rate_info = LCancelRateManager.get_cancel_rate(code, is_up=True)
            l2_log.l_cancel_debug(code, f"计算范围:{start_index}-{end_index},L前已撤单比例:{rate}/{thresh_cancel_rate}")
            if rate >= thresh_cancel_rate:
                # 计算成交进度位置到当前下单位置的纯买额
                real_place_order_index_info = self.__real_place_order_index_dict.get(code)
                trade_progress_index, is_default = TradeBuyQueue().get_traded_index(code)
                if trade_progress_index is None:
                    trade_progress_index = 0
                if real_place_order_index_info and trade_progress_index:
                    total_num = 0
                    thresh_hold_money = l2_trade_factor.L2PlaceOrderParamsManager.get_base_m_val(code)
                    thresh_hold_money = thresh_hold_money * 3
                    # 阈值为2倍m值
                    thresh_hold_num = thresh_hold_money // (gpcode_manager.get_limit_up_price_as_num(code) * 100)
                    for i in range(trade_progress_index + 1, real_place_order_index_info[0]):
                        data = total_data[i]
                        val = data['val']
                        if not L2DataUtil.is_limit_up_price_buy(val):
                            continue
                        canceled_data = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_canceled_data_v2(code,
                                                                                                                i,
                                                                                                                total_data,
                                                                                                                local_today_canceled_buyno_map.get(
                                                                                                                    code))
                        if not canceled_data:
                            # 没有撤单
                            total_num += val["num"] * data["re"]
                            if total_num > thresh_hold_num:
                                # 成交位到下单位还有足够的单没撤
                                l2_log.l_cancel_debug(code,
                                                      f"L前撤阻断: 成交位-{trade_progress_index} 真实下单位-{real_place_order_index_info[0]} 阈值-{thresh_hold_money}")
                                return False, None
                canceled_indexes.sort()
                l2_log.l_cancel_debug(code, f"L前撤单,撤单位置:{canceled_indexes[-1]}")
                return True, total_data[canceled_indexes[-1]]
        return False, None
    # L后重新囊括的时间
    __recompute_l_down_time_dict = {}
    def add_big_sell_order_deal_list(self, code, deal_order_list):
        """
@@ -1982,43 +1512,6 @@
        total_datas = local_today_datas.get(code)
        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):
        watch_indexes_info = self.__get_watch_indexes_cache(code)
        if not watch_indexes_info:
            return True
        trade_index, is_default = TradeBuyQueue().get_traded_index(code)
        if trade_index is None:
            trade_index = 0
        if trade_index is None:
            return True
        real_place_order_index_info = self.__real_place_order_index_dict.get(code)
        if not real_place_order_index_info:
            return True
        # 计算已经成交的比例
        total_datas = local_today_datas.get(code)
        total_deal_nums = 0
        total_nums = 1
        for index in watch_indexes_info[2]:
            # 不能计算L后后半段
            if index > real_place_order_index_info[0]:
                continue
            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))
            total_nums += val["num"]
            if left_count > 0 and index < trade_index:
                total_deal_nums += val["num"]
        thresh_hold_rate, must_buy, cancel_rate_info = LCancelRateManager.get_cancel_rate(code)
        if total_deal_nums / total_nums > 1 - thresh_hold_rate - 0.05:
            return False
        return True
    def need_cancel(self, code, buy_exec_index, start_index, end_index, total_data, is_first_code):
        if buy_exec_index is None:
@@ -2042,35 +1535,6 @@
            logger_l2_l_cancel.exception(e)
            raise e
        extra_msg = "L后"
        # 不需要计算L前
        # if not can_cancel:
        #     # 成交位临近撤
        #     try:
        #         can_cancel, cancel_data = self.__compute_near_by_trade_progress_need_cancel(code, buy_exec_index,
        #                                                                                     start_index, end_index,
        #                                                                                     total_data,
        #                                                                                     is_first_code)
        #         if can_cancel:
        #             cancel_type = trade_constant.CANCEL_TYPE_L_UP
        #         extra_msg = "L前"
        #     except Exception as e:
        #         logger_l2_l_cancel.exception(e)
        #         raise e
        try:
            if self.__need_update_l_down_after(code, start_index, end_index):
                # 更新后半段
                watch_indexes = self.__compute_l_down_watch_index_after_real_place_order_index(code)
                if watch_indexes:
                    l2_log.l_cancel_debug(code, "L后后半段囊括:{}", watch_indexes)
                    watch_indexes_info = self.__get_watch_indexes_cache(code)
                    if watch_indexes_info and watch_indexes_info[2]:
                        # 没有囊括
                        watch_indexes |= set(watch_indexes_info[2])
                        self.__set_watch_indexes(code, watch_indexes_info[0], watch_indexes_info[1], watch_indexes)
        except Exception as e:
            l2_log.l_cancel_debug(code, "L后后半段计算出错:{}", str(e))
        return can_cancel, cancel_data, extra_msg, cancel_type
    def place_order_success(self, code):
@@ -2134,56 +1598,6 @@
            fdatas.append(item)
        fdatas.sort(key=lambda x: x[0])
        return fdatas
    # 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):
        """