Administrator
2024-07-19 b5434ba1edc4a1733a37ba27d8107478077ea350
G撤调整/S重砸调整
3个文件已修改
315 ■■■■ 已修改文件
cancel_strategy/s_l_h_cancel_strategy.py 259 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/cancel_buy_strategy.py 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/l2_data_manager_new.py 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cancel_strategy/s_l_h_cancel_strategy.py
@@ -339,10 +339,18 @@
    # 是否有大卖单需要撤
    def __need_cancel_for_big_sell_order(self, code, big_sell_order_info, order_begin_pos: OrderBeginPosInfo):
        """
        @param code:
        @param big_sell_order_info:(总卖金额,[(卖单号,总手数,价格,('开始时间',买单号),('结束时间',买单号)),...])
        @param order_begin_pos:
        @return:
        """
        # 需要排除成交时间在下单时间之前的
        total_deal_money = 0
        max_single_deal_money = 0  # 最大单笔卖金额
        total_datas = local_today_datas.get(code)
        real_order_index_info = self.__get_real_place_order_index_info_cache(code)
        # 下单时间
        real_order_time_ms = None
        real_order_index = None
        if real_order_index_info and not real_order_index_info[1]:
@@ -355,9 +363,11 @@
            if real_order_time_ms:
                if tool.trade_time_sub_with_ms(deal_time, real_order_time_ms) >= 0:
                    m = x[1] * x[2]
                    max_single_deal_money = max(max_single_deal_money, m)
                    total_deal_money += m
            else:
                m = x[1] * x[2]
                max_single_deal_money = max(max_single_deal_money, m)
                total_deal_money += m
        zyltgb = l2_trade_factor.L2TradeFactorUtil.get_zyltgb(code)
@@ -369,43 +379,45 @@
        if total_deal_money >= threshold_big_deal:
            # S重砸必撤的金额满足以后,以前是无脑撤。现在优化一下,看成交进度位---真实下单位的区间额≤重砸金额*3.3倍,就撤。
            try:
                # 上证,下单3分钟内
                try:
                    if tool.is_sh_code(code) and real_order_index is not None and tool.trade_time_sub(
                            total_datas[-1]["val"]["time"], total_datas[real_order_index]["val"]["time"]) < 3 * 60:
                        # 上证如果重砸额大于阈值的1.5倍直接撤单
                        if not gpcode_manager.MustBuyCodesManager().is_in_cache(code):
                            if total_deal_money >= threshold_big_deal * 1.5:
                                return True, f"1s内成交({total_deal_money}) 大于大卖单({threshold_big_deal})的1.5倍"
                            # 如果没有大单成交也直接撤单
                            deal_big_order_count = BigOrderDealManager().get_total_buy_count(code)
                            if deal_big_order_count < 1:
                                return True, f"1s内成交({total_deal_money}) 大于大卖单({threshold_big_deal})且无大单成交"
                except Exception as e:
                    l2_log.s_cancel_debug(code, "S重砸出错了:{}", str(e))
                # 单笔重砸
                if max_single_deal_money >= threshold_big_deal:
                    # 上证,下单3分钟内
                    try:
                        if tool.is_sh_code(code) and real_order_index is not None and tool.trade_time_sub(
                                total_datas[-1]["val"]["time"], total_datas[real_order_index]["val"]["time"]) < 3 * 60:
                            # 上证如果重砸额大于阈值的1.5倍直接撤单
                            if not gpcode_manager.MustBuyCodesManager().is_in_cache(code):
                                if total_deal_money >= threshold_big_deal * 1.5:
                                    return True, f"1s内成交({total_deal_money}) 大于大卖单({threshold_big_deal})的1.5倍"
                                # 如果没有大单成交也直接撤单
                                deal_big_order_count = BigOrderDealManager().get_total_buy_count(code)
                                if deal_big_order_count < 1:
                                    return True, f"1s内成交({total_deal_money}) 大于大卖单({threshold_big_deal})且无大单成交"
                    except Exception as e:
                        l2_log.s_cancel_debug(code, "S重砸出错了:{}", str(e))
                need_compute = False
                trade_index, is_default = TradeBuyQueue().get_traded_index(code)
                if trade_index is None:
                    trade_index = 0
                if real_order_index_info and not real_order_index_info[1]:
                    need_compute = True
                    need_compute = False
                    trade_index, is_default = TradeBuyQueue().get_traded_index(code)
                    if trade_index is None:
                        trade_index = 0
                    if real_order_index_info and not real_order_index_info[1]:
                        need_compute = True
                if need_compute:
                    total_count, total_num = L2DataComputeUtil.compute_left_buy_order(code, trade_index,
                                                                                      real_order_index_info[0],
                                                                                      limit_up_price)
                    if total_num == 0:
                        total_num = 1
                    if need_compute:
                        total_count, total_num = L2DataComputeUtil.compute_left_buy_order(code, trade_index,
                                                                                          real_order_index_info[0],
                                                                                          limit_up_price)
                        if total_num == 0:
                            total_num = 1
                    threshold_rate, threshold_rate_msg = SCancelRateManager.get_threshhold_rate(code,
                                                                                                SCancelRateManager.TYPE_S_FAST_BIG)
                        threshold_rate, threshold_rate_msg = SCancelRateManager.get_threshhold_rate(code,
                                                                                                    SCancelRateManager.TYPE_S_FAST_BIG)
                    if total_deal_money / (total_num * limit_up_price * 100) >= threshold_rate:
                        # 大单成交额占总剩余总囊括的30%
                        return True, f"1s内大于{threshold_big_deal}({threshold_rate_msg})大卖单({total_deal_money})"
                else:
                    return True, f"1s内大于{threshold_big_deal}大卖单({total_deal_money})"
                        if total_deal_money / (total_num * limit_up_price * 100) >= threshold_rate:
                            # 大单成交额占总剩余总囊括的30%
                            return True, f"1s内大于{threshold_big_deal}({threshold_rate_msg})大卖单({total_deal_money})"
                    else:
                        return True, f"1s内大于{threshold_big_deal}大卖单({total_deal_money})"
            except Exception as e:
                l2_log.info(code, logger_debug, f"S快计算出错:{str(e)}")
@@ -732,6 +744,33 @@
        if cache_result[0]:
            return cache_result[1]
        return None
    def get_l_down_watch_indexes_cache(self, code):
        """
        获取L后的监听范围
        @param code:
        @return:(buy_single_index, re_compute, indexes)
        """
        return self.__get_watch_indexes_cache(code)
    def get_real_place_order_index_info(self, code):
        """
        获取真实下单索引信息
        @param code:
        @return:(index, is_default)
        """
        return self.__real_place_order_index_dict.get(code)
    def set_l_down_watch_index_info(self, code, buy_single_index, re_compute: int, indexes):
        """
        设置l后索引
        @param code:
        @param buy_single_index:
        @param re_compute:
        @param indexes:
        @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:
@@ -1362,7 +1401,6 @@
        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:
            # 将备用订单加进去
@@ -1398,7 +1436,6 @@
                    total_num += total_data[wi]["val"]["num"] * (
                            10 - after_place_order_index_by_dict[str(wi)]) // 10
                continue
            total_num += total_data[wi]["val"]["num"] * total_data[wi]["re"]
            if total_data[wi]["val"]["num"] > max_num:
@@ -1660,6 +1697,158 @@
        print(self.__get_cancel_l_down_after_place_order_index_dict(code))
class LCancelOutOfDateWatchIndexesManager:
    """
    L撤过期数据更新
    """
    __latest_cancel_time_dict = {}
    @classmethod
    def compute_latest_canceled_watch_index_time(cls, code, watch_indexes):
        """
        获取 最近撤单的索引
        @param code:
        @param watch_indexes:
        @return:
        """
        total_datas = local_today_datas.get(code)
        canceled_buyno_map = local_today_canceled_buyno_map.get(code)
        max_cancel_index = -1
        for index in watch_indexes:
            orderNo = total_datas[index]["val"]["orderNo"]
            canceled_data = canceled_buyno_map.get(str(orderNo))
            if canceled_data:
                max_cancel_index = max(max_cancel_index, canceled_data["index"])
        if max_cancel_index < 0:
            # 没有撤单的
            return None
        return total_datas[max_cancel_index]["val"]["time"]
    @classmethod
    def compute_l_down_common_watch_indexes(cls, code, start_index, end_index, max_count, min_num, exclude_watch_indexes):
        """
        获取L后监听数据
        @param code:
        @param re_start_index:
        @param end_index:
        @param max_count:
        @return:
        """
        total_datas = local_today_datas.get(code)
        MIN_MONEYS = [300, 200, 100, 50]
        watch_indexes = set()
        for min_money in MIN_MONEYS:
            for i in range(end_index, start_index - 1, -1):
                try:
                    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 * 100:
                        continue
                    if val['num'] < min_num:
                        continue
                    cancel_data = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_canceled_data_v2(code,
                                                                                                          i,
                                                                                                          total_datas,
                                                                                                          local_today_canceled_buyno_map.get(
                                                                                                              code))
                    if not cancel_data and i not in exclude_watch_indexes:
                        watch_indexes.add(i)
                        if len(watch_indexes) >= max_count:
                            break
                except Exception as e:
                    logger_l2_l_cancel.error(f"{code}: 范围: {start_index}-{end_index}  位置:{i}")
                    logger_l2_l_cancel.exception(e)
            if len(watch_indexes) >= max_count:
                break
        return watch_indexes
    def process(self, code, start_index, end_index):
        # 获取监听数据
        watch_indexes_info = LCancelBigNumComputer().get_l_down_watch_indexes_cache(code)
        if not watch_indexes_info:
            return
        if watch_indexes_info[1]:
            # 已经重新计算过就不再执行
            return
        watch_indexes = set(watch_indexes_info[2])
        # 获取真实下单位数据
        real_place_order_index_info = LCancelBigNumComputer().get_real_place_order_index_info(code)
        if not real_place_order_index_info or real_place_order_index_info[1]:
            return
        real_place_order_index = real_place_order_index_info[0]
        total_datas = local_today_datas.get(code)
        # 计算最近的撤单时间
        buyno_map = local_today_buyno_map.get(code)
        # 已经改过了就不需要修改
        for i in range(start_index, end_index + 1):
            # 判断里面是否有撤单
            data = total_datas[i]
            val = data["val"]
            if not L2DataUtil.is_limit_up_price_buy_cancel(val):
                continue
            if str(val["orderNo"]) not in buyno_map:
                continue
            buy_index = buyno_map[str(val["orderNo"])]["index"]
            if buy_index in watch_indexes and real_place_order_index > buy_index:
                # 下单位之前的L后囊括范围的订单被撤单
                self.__latest_cancel_time_dict[code] = val["time"]
        if tool.trade_time_sub(total_datas[-1]["val"]["time"],
                               total_datas[real_place_order_index]["val"]["time"]) < 10 * 60:
            # 下单10分钟后才能生效
            return
        if code not in self.__latest_cancel_time_dict:
            return
        if tool.trade_time_sub(total_datas[-1]["val"]["time"], self.__latest_cancel_time_dict.get(code)) < 10 * 60:
            # 最近的撤单时间小于10分钟
            return
        # TODO 查找是否有相同时间的撤单且撤单时间在10分钟之前
        canceled_buyno_map = local_today_canceled_buyno_map.get(code)
        cancel_time_dict={}
        for index in watch_indexes:
            if index > real_place_order_index:
                continue
            orderNo = str(total_datas[index]["val"]["orderNo"])
            if orderNo not in canceled_buyno_map:
                continue
            if tool.trade_time_sub(total_datas[-1]["val"]["time"], canceled_buyno_map[orderNo]["val"]["time"]) < 10 * 60:
                continue
            val = total_datas[index]["val"]
            time_str = L2DataUtil.get_time_with_ms(val)
            if time_str not in cancel_time_dict:
                cancel_time_dict[time_str] = set()
            cancel_time_dict[time_str].add(index)
        remove_indexes = set()
        for t in  cancel_time_dict:
            if len(cancel_time_dict[t])>1:
                remove_indexes|=cancel_time_dict[t]
        if remove_indexes:
            # 移除索引
            add_count = len(remove_indexes)
            limit_up_price = gpcode_manager.get_limit_up_price_as_num(code)
            min_num = int(5000/limit_up_price)
            trade_index, is_default = TradeBuyQueue().get_traded_index(code)
            if trade_index is None:
                trade_index = 0
            add_watch_index = self.compute_l_down_common_watch_indexes(code,trade_index ,real_place_order_index, add_count, min_num, watch_indexes)
            watch_indexes -= remove_indexes
            watch_indexes|=add_watch_index
            # 保存数据 /
            LCancelBigNumComputer().set_l_down_watch_index_info(code, watch_indexes_info[0], True, watch_indexes)
            l2_log.l_cancel_debug(code, f"L后稳定后更新监控范围:删除-{remove_indexes} 增加-{add_watch_index}")
# --------------------------------H撤-------------------------------
class HourCancelBigNumComputer:
    __db = 0
l2/cancel_buy_strategy.py
@@ -622,7 +622,28 @@
        total_datas = local_today_datas.get(code)
        watch_indexes = set()
        for i in range(start_index, real_order_index):
        # G撤的囊括范围向后面延申5笔
        end_index = real_order_index
        count = 0
        for i in range(real_order_index + 1, total_datas[-1]["index"] + 1):
            data = total_datas[i]
            val = data["val"]
            if not L2DataUtil.is_limit_up_price_buy(val):
                continue
            if val["num"] * float(val["price"]) < 5000:
                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:
                continue
            count += 1
            if count > 5:
                break
            end_index = i
        for i in range(start_index, end_index + 1):
            # 判断是否有未撤的大单
            data = total_datas[i]
            val = data["val"]
@@ -637,13 +658,15 @@
                                                                                                         code))
            if left_count > 0:
                watch_indexes.add(i)
        if watch_indexes:
            # 还有300万以上的大单没有撤单
            if from_real_order_index_changed or recompute:
                # 真实下单位改变后才会更新
                final_watch_indexes = origin_watch_index | watch_indexes
                self.__watch_indexes_dict[code] = final_watch_indexes
                l2_log.g_cancel_debug(code, f"大单监听:{final_watch_indexes} 是否重新计算:{recompute}")
                l2_log.g_cancel_debug(code,
                                      f"大单监听:{final_watch_indexes} 是否重新计算:{recompute} 计算范围:{start_index}-{end_index}")
                # 有大单监听,需要移除之前的小单监听
                if code in self.__watch_indexes_by_dict:
                    self.__watch_indexes_by_dict[code].clear()
l2/l2_data_manager_new.py
@@ -26,7 +26,7 @@
    transaction_progress, cancel_buy_strategy, place_order_single_data_manager
from l2.cancel_buy_strategy import DCancelBigNumComputer, \
    LatestCancelIndexManager, \
    NewGCancelBigNumComputer, JCancelBigNumComputer
    NewGCancelBigNumComputer, JCancelBigNumComputer, L2DataComputeUtil
from l2.l2_data_manager import L2DataException, OrderBeginPosInfo
from l2.l2_data_util import local_today_datas, L2DataUtil, local_today_num_operate_map, local_today_buyno_map, \
    local_latest_datas, local_today_canceled_buyno_map, local_today_sellno_map
@@ -843,16 +843,16 @@
        #     # 14:00:00后只打老大的回封
        #     return False, True, f"14:00:00不打回封"
        limit_up_price = gpcode_manager.get_limit_up_price(code)
        limit_up_price = gpcode_manager.get_limit_up_price_as_num(code)
        if constant.MIN_CODE_PRICE < float(limit_up_price) < constant.MAX_CODE_PRICE:
        if constant.MIN_CODE_PRICE < limit_up_price < constant.MAX_CODE_PRICE:
            # 满足条件的单价
            pass
        elif float(limit_up_price) > constant.MAX_CODE_PRICE:
        elif limit_up_price > constant.MAX_CODE_PRICE:
            # HighIncreaseCodeManager().add_code(code)
            # 小市值高股价可买
            zyltgb = global_util.zyltgb_map.get(code)
            if zyltgb > 25e8 or float(limit_up_price) > constant.MAX_SUBSCRIPT_CODE_PRICE:
            if zyltgb > 25e8 or limit_up_price > constant.MAX_SUBSCRIPT_CODE_PRICE:
                return False, True, f"股价大于{constant.MAX_CODE_PRICE}块/小于{constant.MIN_CODE_PRICE}块"
        else:
            return False, True, f"股价小于{constant.MIN_CODE_PRICE}块"
@@ -943,6 +943,20 @@
                                                                                                          min_money=min_money)
                    if left_count < 1:
                        return False, False, f"没有已挂或者成交的大单"
            place_order_count = trade_data_manager.PlaceOrderCountManager().get_place_order_count(code)
            # 第一和第二次下单都必须要有至少一笔未成交/待成交的大单
            # 计算大单
            if place_order_count < 2:
                trade_index, is_default = transaction_progress.TradeBuyQueue().get_traded_index(code)
                if trade_index is None:
                    trade_index = 0
                total_datas = local_today_datas.get(code)
                min_money = l2_data_util.get_big_money_val(limit_up_price, tool.is_ge_code(code))
                left_count, left_num = L2DataComputeUtil.compute_left_buy_order(code, trade_index,
                                                                                total_datas[-1]["index"],
                                                                                limit_up_price, min_money)
                if left_count < 1:
                    return False, False, f"第{place_order_count+1}下单无待成交的大单"
        # 暂时注释想买单功能
        if not cls.__WantBuyCodesManager.is_in_cache(code):
@@ -1157,7 +1171,6 @@
    @classmethod
    def can_buy_first_new(cls, code, limit_up_price):
        now_timestamp = int(tool.get_now_time_str().replace(":", ""))
        # 判断板块
        # (可以买的板块列表, 是否是独苗, 消息简介,可买的强势主线, 板块关键词)
@@ -1196,7 +1209,7 @@
                # 后排,满足自由流通市值需要下单
                return True, False, can_buy_result[2]
        else:
            place_order_count = trade_data_manager.PlaceOrderCountManager().get_place_order_count(code)
            if place_order_count > 0:
                return True, False, "之前下过单"
            if not can_buy_result[0]:
@@ -1859,7 +1872,7 @@
                            return None, buy_nums, buy_count, ii, max_buy_num_set, f"【{i}】信号不连续,囊括时间-{max_space_time_ms}ms"
            # 涨停买
            if L2DataUtil.is_limit_up_price_buy(_val):
                if l2_data_util.is_big_money(_val,is_ge_code):
                if l2_data_util.is_big_money(_val, is_ge_code):
                    max_buy_num_set.add(i)
                if _val["num"] >= bigger_num:
                    trigger_buy = True