Administrator
10 天以前 3bec07f70237ca81990279a6b2f866a2adf70575
L后撤单修改/L后重新囊括修改
7个文件已修改
189 ■■■■ 已修改文件
cancel_strategy/s_l_h_cancel_strategy.py 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
code_attribute/code_nature_analyse.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
huaxin_client/huaxin_sinfo_util.py 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/l2_transaction_data_manager.py 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/l2_transaction_data_processor.py 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
trade/buy_radical/new_block_processor.py 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
trade/buy_radical/radical_buy_data_manager.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
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]
                # 获取正在成交的大卖单
                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
        # 获取正在成交的数据
        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]):
                # 减去当前正在成交的数据中已经成交了的数据
                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"没找到真实的成交进度(大卖单):start_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):
code_attribute/code_nature_analyse.py
@@ -406,7 +406,7 @@
    # if max_price > float(limit_up_price):
    #     return False
    rate = (max_price_info[1]["high"] - min_price_info[1]["low"]) / min_price_info[1]["low"]
    THRESHOLD_RATE = 0.319 * 2 if tool.is_ge_code(code) else 0.319
    THRESHOLD_RATE = 0.249 * 2 if tool.is_ge_code(code) else 0.249
    if rate >= THRESHOLD_RATE:
        return True, rate
    return False, rate
huaxin_client/huaxin_sinfo_util.py
@@ -2,6 +2,7 @@
CHANNEL = 'z'
def create_place_order_sinfo(code, _is_buy, _is_human, _channel=CHANNEL):
    """
    创建下单sinfo
@@ -45,6 +46,7 @@
def is_own_channel(sinfo):
    channel = get_channel(sinfo)
    if channel is None:
        return None
    return channel == CHANNEL
        return True
    if channel != CHANNEL:
        return False
    return True
l2/l2_transaction_data_manager.py
@@ -329,12 +329,21 @@
    __dealing_order_info_dict = {}
    @classmethod
    def get_dealing_order_info(cls, code):
        """
        获取正在成交的卖单
        @param code:
        @return: [订单号,总股数,成交金额]
        """
        return cls.__dealing_order_info_dict.get(code)
    @classmethod
    def statistic_big_sell_data(cls, code, fdatas):
        """
        统计大卖单(299w以上)
        @param code:
        @param fdatas: [(数据本身, 是否主动买, 是否涨停, 总成交额, 不含ms时间,含ms时间)]
        @return: 返回数据里面成交的大单
        @return: 返回数据里面成交的大单:[(订单号,总股数,成交金额)]
        """
        big_sell_datas = []
        # 正在成交的卖单
l2/l2_transaction_data_processor.py
@@ -98,7 +98,7 @@
        统计大单成交
        @param code:
        @param fdatas: 格式:[(数据本身, 是否主动买, 是否涨停, 总成交额, 不含ms时间,含ms时间)]
        @return:
        @return: 大买单列表,大卖单列表
        """
        def statistic_big_buy_data():
@@ -167,6 +167,7 @@
        else:
            buy_datas = statistic_big_buy_data()
            sell_datas = statistic_big_sell_data()
        return buy_datas, sell_datas
        # L撤的比例与买卖大单无直接关系了
        # if buy_datas or sell_datas:
        #     buy_money = BigOrderDealManager().get_total_buy_money(code)
@@ -230,8 +231,9 @@
            _start_time = time.time()
            #  大单统计
            # cls.__statistic_thread_pool.submit(cls.statistic_big_order_infos, code, datas, order_begin_pos)
            big_sell_list = []
            try:
                cls.statistic_big_order_infos(code, fdatas, order_begin_pos)
                big_buy_list, big_sell_list = cls.statistic_big_order_infos(code, fdatas, order_begin_pos)
            except Exception as e:
                async_log_util.error(hx_logger_l2_debug, f"统计大单出错:{str(e)}")
            use_time_list.append(("统计大单数据", time.time() - _start_time))
@@ -254,17 +256,18 @@
                _start_time = time.time()
                if is_placed_order:
                    LCancelBigNumComputer().set_big_sell_order_info(code, big_sell_order_info)
                    # need_cancel, cancel_msg = SCancelBigNumComputer().set_big_sell_order_info_for_cancel(code,
                    #                                                                                      big_sell_order_info,
                    #                                                                                      order_begin_pos)
                    need_cancel, cancel_msg = False, ""
                    cancel_type = None
                    if need_cancel:
                        cancel_msg = f"S撤:{cancel_msg}"
                        cancel_type = trade_constant.CANCEL_TYPE_S
                    try:
                        can_cancel, cancel_data = LCancelBigNumComputer().add_big_sell_order_deal_list(code, big_sell_list)
                        if can_cancel:
                            need_cancel, cancel_msg = True, f"L后大卖单成交叠加触发撤单:{big_sell_list}"
                    except Exception as e:
                        async_log_util.error(logger_debug, f"L后大卖单成交叠加触发撤单:{str(e)}")
                    if not need_cancel:
                        need_cancel, cancel_msg = FCancelBigNumComputer().need_cancel_for_p(code,
                                                                                            order_begin_pos)
@@ -373,7 +376,6 @@
            big_sell_order_info = HuaXinSellOrderStatisticManager.statistic_continue_limit_up_sell_transaction_datas(
                code, fdatas,
                limit_up_price)
            LCancelBigNumComputer().set_big_sell_order_info(code, big_sell_order_info)
            need_cancel, cancel_msg = False, ""
            cancel_type = None
            if not need_cancel:
@@ -496,4 +498,4 @@
    @classmethod
    def get_latest_transaction_data(cls, code):
        return cls.__latest_transaction_data_dict.get(code)
        return cls.__latest_transaction_data_dict.get(code)
trade/buy_radical/new_block_processor.py
@@ -200,11 +200,13 @@
        blocks |= kpl_data_constant.limit_up_component_code_new_blocks_dict[code]
    if code in kpl_data_constant.limit_up_code_new_block_dict:
        blocks.add(kpl_data_constant.limit_up_code_new_block_dict[code])
    if blocks and l2_trade_util.is_in_forbidden_trade_codes(code) and not HumanForbiddenManager().is_in_cache(code):
        # 没有人为拉黑才能移黑
        l2_trade_util.remove_from_forbidden_trade_codes(code)
        # 加想买单要从黑名单移除
        trade_record_log_util.add_common_msg(code, "新题材移黑", f"{blocks}")
    # 暂时无需新题材移黑
    # if blocks and l2_trade_util.is_in_forbidden_trade_codes(code) and not HumanForbiddenManager().is_in_cache(code):
    #     # 没有人为拉黑才能移黑
    #     l2_trade_util.remove_from_forbidden_trade_codes(code)
    #     # 加想买单要从黑名单移除
    #     trade_record_log_util.add_common_msg(code, "新题材移黑", f"{blocks}")
    # 新板块
    if constant.TEST:
        print(code, kpl_data_constant.limit_up_code_new_block_dict.get(code),
trade/buy_radical/radical_buy_data_manager.py
@@ -1786,7 +1786,7 @@
                                                                             limit_up_price) * limit_up_price / 1e8,
        2) * 3
    if tool.is_ge_code(code):
        TOTAL_BIG_DEAL_MONEY_THRESHOLD_COUNT *= 1.5
        TOTAL_BIG_DEAL_MONEY_THRESHOLD_COUNT *= 3
    return TOTAL_BIG_DEAL_MONEY_THRESHOLD_COUNT * threshold_money_per_order