Administrator
2025-04-06 d095fcfddce52be85db18f17b815c890deeb48ff
丢失撤单处理/首封是否买设置
9个文件已修改
183 ■■■■ 已修改文件
api/outside_api_command_callback.py 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cancel_strategy/s_l_h_cancel_strategy.py 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
constant.py 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
huaxin_client/l2_data_manager_v2.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/cancel_buy_strategy.py 59 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/l2_compute_util.py 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/l2_data_manager_new.py 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/l2_transaction_data_manager.py 47 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
log_module/log_export.py 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/outside_api_command_callback.py
@@ -1370,7 +1370,8 @@
                                    "zyltgb": constant.RADICAL_BUY_ZYLTGB_AS_YI_RANGES,
                                    "top_block_count_by_market_strong": constant.RADICAL_BUY_TOP_IN_COUNT_BY_MARKET_STRONG,
                                    "special_codes_max_block_in_rank": constant.RADICAL_BUY_TOP_IN_INDEX_WITH_SPECIAL,
                                    "ignore_block_in_money_market_strong": constant.IGNORE_BLOCK_IN_MONEY_MARKET_STRONG
                                    "ignore_block_in_money_market_strong": constant.IGNORE_BLOCK_IN_MONEY_MARKET_STRONG,
                                    "buy_first_limit_up": 1 if constant.CAN_BUY_FIRST_LIMIT_UP else 0
                                    }}
                self.send_response({"code": 0, "data": data, "msg": f""},
                                   client_id,
@@ -1391,6 +1392,10 @@
                    if radical_buy.get('ignore_block_in_money_market_strong') is not None:
                        constant.IGNORE_BLOCK_IN_MONEY_MARKET_STRONG = radical_buy.get(
                            'ignore_block_in_money_market_strong')
                    if radical_buy.get('buy_first_limit_up') is not None:
                        constant.CAN_BUY_FIRST_LIMIT_UP = True if radical_buy.get(
                            'buy_first_limit_up') else False
                self.send_response({"code": 0, "data": {}, "msg": f""},
                                   client_id,
                                   request_id)
cancel_strategy/s_l_h_cancel_strategy.py
@@ -1518,12 +1518,16 @@
            canceled_num = 0
            # 记录撤单索引
            canceled_indexes = []
            deal_order_nos = HuaXinBuyOrderManager().get_deal_buy_order_nos(code)
            if deal_order_nos is None:
                deal_order_nos = set()
            trade_index, is_default = TradeBuyQueue().get_traded_index(code)
            if is_default:
                trade_index = None
            canceled_buyno_map = local_today_canceled_buyno_map.get(code)
            for wi in watch_indexes:
                cancel_data = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_canceled_data_v2(code,
                                                                                                      wi,
                                                                                                      total_data,
                                                                                                      local_today_canceled_buyno_map.get(
                                                                                                          code))
                cancel_data = L2DataComputeUtil.is_canceled(code, wi, total_data, canceled_buyno_map, trade_index, deal_order_nos)
                if cancel_data:
                    if str(wi) in after_place_order_index_dict:
                        # 真实下单位置之后的按照权重比例来计算
@@ -1534,7 +1538,6 @@
                                10 - after_place_order_index_by_dict[str(wi)]) // 10
                    else:
                        canceled_num += total_data[wi]["val"]["num"]
                    canceled_indexes.append(cancel_data["index"])
                # if wi == watch_indexes_list[-1] and left_count == 0:
                #     # 离下单位置最近的一个撤单,必须触发撤单
constant.py
@@ -233,4 +233,7 @@
# 新版L2监听
IS_L2_NEW = True
# 是否可买首封
CAN_BUY_FIRST_LIMIT_UP = True
huaxin_client/l2_data_manager_v2.py
@@ -241,6 +241,7 @@
            except Exception as e:
                logging.exception(e)
                logger_local_huaxin_l2_error.exception(e)
            finally:
                temp_list.clear()
l2/cancel_buy_strategy.py
@@ -151,6 +151,31 @@
                    max_info = (i, val["num"])
        return total_datas[max_info[0]]
    @classmethod
    def is_canceled(cls, code, index, total_datas, canceled_buyno_map, trade_index, deal_order_nos):
        """
        是否已经撤单
        @param deal_order_nos: 成交大单集合
        @param trade_index: 成交进度位
        @param index: 索引
        @param code: 代码
        @param total_datas:
        @param canceled_buyno_map:撤单的订单号
        @return:
        """
        cancel_data = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_canceled_data_v2(code, index,
                                                                                              total_datas,
                                                                                              canceled_buyno_map)
        if cancel_data:
            # 已经撤单
            return True
        else:
            if trade_index and trade_index > index:
                # 成交进度大于索引位置,且还没成交
                if total_datas[index]["val"]["orderNo"] not in deal_order_nos:
                    return True
            return False
# ---------------------------------D撤-------------------------------
# 计算 成交位->真实下单位置 总共还剩下多少手没有撤单
@@ -255,7 +280,7 @@
    def set_real_place_order_index(self, code, index, buy_single_index, is_default):
        if is_default:
            return
        if  code  in self.__watch_indexes_cache and len(self.__watch_indexes_cache[code]) > 1:
        if code in self.__watch_indexes_cache and len(self.__watch_indexes_cache[code]) > 1:
            # 囊括的单大于1个
            return
        # 从买入信号位开始囊括
@@ -290,6 +315,7 @@
        @param end_index:
        @return: 是否需要撤单,撤单索引, 消息
        """
        buyno_map = local_today_buyno_map.get(code)
        watch_indexes = self.__watch_indexes_cache.get(code)
        if not watch_indexes:
            return False, None, "无大单监听"
@@ -302,24 +328,28 @@
                continue
            if val["num"] * float(val["price"]) < 5000:
                continue
            buy_index = l2_data_source_util.L2DataSourceUtils.get_buy_index_with_cancel_data_v2(data,
                                                                                                local_today_buyno_map.get(
                                                                                                    code))
            buy_index = l2_data_source_util.L2DataSourceUtils.get_buy_index_with_cancel_data_v2(data, buyno_map)
            if buy_index is None:
                continue
            if buy_index in watch_indexes:
                need_compute = True
                break
        cancel_indexes = set()
        if need_compute:
        canceled_buyno_map = local_today_canceled_buyno_map.get(code)
        if need_compute or True:
            cancel_count = 0
            cancel_data = None
            # 成交买单号
            deal_order_nos = HuaXinBuyOrderManager().get_deal_buy_order_nos(code)
            if deal_order_nos is None:
                deal_order_nos = set()
            trade_index, is_default = TradeBuyQueue().get_traded_index(code)
            if is_default:
                trade_index = None
            for index in watch_indexes:
                cancel_data = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_canceled_data_v2(code, index,
                                                                                                      total_datas,
                                                                                                      local_today_canceled_buyno_map.get(
                                                                                                          code))
                if cancel_data:
                if L2DataComputeUtil.is_canceled(code, index, total_datas, canceled_buyno_map, trade_index,
                                                 deal_order_nos):
                    # 买单已撤单
                    cancel_count += 1
                    cancel_indexes.add(index)
            rate = round(cancel_count / len(watch_indexes), 2)
@@ -520,9 +550,10 @@
                if dealing_info and str(dealing_info[0]) == str(val["orderNo"]):
                    total_left_num -= dealing_info[1] // 100
        limit_up_price = gpcode_manager.get_limit_up_price(code)
        total_left_money = total_left_num * float(limit_up_price)*100
        total_left_money = total_left_num * float(limit_up_price) * 100
        if total_left_money < 1e8:
            if total_left_count <= 1 or (total_left_count <= THRESHOLD_COUNT and limit_up_price and total_left_num * float(
            if total_left_count <= 1 or (
                    total_left_count <= THRESHOLD_COUNT and limit_up_price and total_left_num * float(
                    limit_up_price) < THRESHOLD_MONEY_W * 100):
                return True, f"剩余笔数({total_left_count})/金额({round(total_left_num * float(limit_up_price) * 100)})不足,成交进度:{trade_index},真实下单位置:{real_order_index} 阈值:({THRESHOLD_MONEY_W},{THRESHOLD_COUNT}) "
        return False, f"不满足撤单条件: 成交进度-{trade_index} 真实下单位置-{real_order_index} total_left_count-{total_left_count} total_left_num-{total_left_num}"
@@ -587,13 +618,13 @@
        # 计算我们后面的大单与涨停纯买额
        total_left_num = 0
        total_big_num_count = 0
        canceled_buyno_map =  local_today_canceled_buyno_map.get(code)
        canceled_buyno_map = local_today_canceled_buyno_map.get(code)
        for i in range(real_order_index + 1, len(total_datas)):
            data = total_datas[i]
            val = data["val"]
            if not L2DataUtil.is_limit_up_price_buy(val):
                continue
            money = val["num"] * float(val["price"])*100
            money = val["num"] * float(val["price"]) * 100
            if money < 500000:
                continue
            left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count_v2(code,
l2/l2_compute_util.py
@@ -69,3 +69,28 @@
                if total_count >= max_count:
                    return i
        return end_index
    @classmethod
    def is_canceled(cls, code, index, total_datas, canceled_buyno_map, trade_index, deal_order_nos):
        """
        是否已经撤单
        @param deal_order_nos: 成交大单集合
        @param trade_index: 成交进度位
        @param index: 索引
        @param code: 代码
        @param total_datas:
        @param canceled_buyno_map:撤单的订单号
        @return:
        """
        cancel_data = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_canceled_data_v2(code, index,
                                                                                              total_datas,
                                                                                              canceled_buyno_map)
        if cancel_data:
            # 已经撤单
            return cancel_data
        else:
            if trade_index and trade_index > index:
                # 成交进度大于索引位置,且还没成交
                if total_datas[index]["val"]["orderNo"] not in deal_order_nos:
                    return total_datas[index]
            return None
l2/l2_data_manager_new.py
@@ -971,12 +971,22 @@
                                                             local_today_datas.get(code))
                return False
            else:
                l2_log.debug(code, "可以下单,原因:{}, 下单模式:{}", reason, order_begin_pos.mode)
                try:
                    # 判断是否为首封下单
                    order_begin_pos.first_limit_up_buy = radical_buy_data_manager.is_first_limit_up_buy(code)
                    if not constant.CAN_BUY_FIRST_LIMIT_UP and order_begin_pos.first_limit_up_buy:
                        reason = "首封不下单"
                        l2_log.debug(code, "不可以下单,原因:{}", reason)
                        trade_record_log_util.add_cant_place_order_log(code, reason)
                        cls.__break_current_batch_data_for_buy_dict[code] = True
                        trade_result_manager.real_cancel_success(code, order_begin_pos.buy_single_index,
                                                                 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, "开始执行买入")
                    trade_manager.start_buy(code, capture_timestamp, last_data,
                                            last_data_index, order_begin_pos.mode, order_begin_pos.buy_exec_index)
l2/l2_transaction_data_manager.py
@@ -150,6 +150,8 @@
    __dealing_active_buy_order_info_dict = {}
    # 最近成交的订单{"code":(订单号,是否成交完成)}
    __latest_deal_order_info_dict = {}
    # 成交的买单号集合:{"代码":set()}
    __deal_buy_order_nos_dict = {}
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
@@ -164,15 +166,17 @@
    @classmethod
    def __load_datas(cls):
        __redis = cls.__get_redis()
        try:
            keys = RedisUtils.keys(__redis, "dealing_order_info-*")
            for k in keys:
                code = k.split("-")[-1]
                val = RedisUtils.get(__redis, k)
                val = json.loads(val)
                tool.CodeDataCacheUtil.set_cache(cls.__dealing_order_info_dict, code, val)
        finally:
            RedisUtils.realse(__redis)
        keys = RedisUtils.keys(__redis, "dealing_order_info-*")
        for k in keys:
            code = k.split("-")[-1]
            val = RedisUtils.get(__redis, k)
            val = json.loads(val)
            tool.CodeDataCacheUtil.set_cache(cls.__dealing_order_info_dict, code, val)
        # 读取已经成交的大单
        deal_data_list_dict = log_export.load_huaxin_deal_record_all()
        for code in deal_data_list_dict:
            cls.__deal_buy_order_nos_dict[code] = set([x[0] for x in deal_data_list_dict[code]])
    # 将数据持久化到数据库
    def sync_dealing_data_to_db(self):
@@ -213,6 +217,10 @@
        dealing_order_info = cls.__dealing_order_info_dict.get(code)
        if code not in cls.__deal_buy_order_nos_dict:
            cls.__deal_buy_order_nos_dict[code] = set()
        deal_buy_order_nos = cls.__deal_buy_order_nos_dict[code]
        for data in fdatas:
            # q.append((data['SecurityID'], data['TradePrice'], data['TradeVolume'],
            #                   data['OrderTime'], data['MainSeq'], data['SubSeq'], data['BuyNo'],
@@ -252,6 +260,7 @@
                        # if abs(deal_info[5] - limit_up_price) < 0.0001:
                        big_buy_datas.append(deal_info)
                    if deal_info[2] >= 500000:
                        deal_buy_order_nos.add(deal_info[0])
                        normal_buy_datas.append(deal_info)
                    # 初始化本条数据
                    dealing_order_info = [current_order_info[6], current_order_info[2], money,
@@ -282,6 +291,14 @@
                                                                          current_order_info[3],
                                                                          current_order_info[3]]
        return big_buy_datas, normal_buy_datas
    def get_deal_buy_order_nos(self, code):
        """
        获取成交大单集合
        @param code:
        @return:
        """
        return self.__deal_buy_order_nos_dict.get(code)
# 卖单统计数据
@@ -537,11 +554,11 @@
            cls.__latest_sell_order_dict[code] = latest_sell_order
        if big_sell_order_ids:
            cls.__big_sell_order_ids_dict[code] = big_sell_order_ids
        if  big_sell_order_info:
        if big_sell_order_info:
            cls.__big_sell_order_info_dict[code] = big_sell_order_info
        if  big_sell_order_info_list:
        if big_sell_order_info_list:
            cls.__big_sell_order_info_list_dict[code] = big_sell_order_info_list
        if  latest_all_sell_orders:
        if latest_all_sell_orders:
            cls.__latest_all_sell_orders_dict[code] = latest_all_sell_orders
        use_time = time.time() - __start_time
@@ -664,3 +681,9 @@
    @classmethod
    def get_latest_trade_price_info(cls, code):
        return cls.__latest_trade_price_dict.get(code)
if __name__ == "__main__":
    code = "603300"
    order_nos = HuaXinBuyOrderManager().get_deal_buy_order_nos(code)
    print(order_nos)
log_module/log_export.py
@@ -466,18 +466,26 @@
# 加载l2订单成交数据
@cache_log
def load_huaxin_deal_record(code, date=tool.get_now_date_str()):
    datas_dict = load_huaxin_deal_record_all(date)
    return datas_dict.get(code)
@cache_log
def load_huaxin_deal_record_all(date=tool.get_now_date_str()):
    path = f"{constant.get_path_prefix()}/logs/huaxin/l2/transaction_desc.{date}.log"
    # 格式:[(订单号,手数,开始成交时间,成交结束时间,下单手数)]
    fdatas = []
    fdatas = {}
    lines = __load_file_content(path)
    for line in lines:
        data_index = line.find(f"{code}#")
        data_index = line.find(f"#")
        if data_index > 0:
            time_str, data = __parse_content(line)
            code = data.split("#")[0]
            data = data.split("#")[1]
            data = eval(data)
            fdatas.append(data)
            if code not in fdatas:
                fdatas[code] = []
            fdatas[code].append(data)
    return fdatas